Particle.cpp

Ivan Muzalevsky, 02/26/2018 09:35 AM

Download (16.2 KB)

 
1
#include "Particle.h"
2
#include <sstream>
3
#include <string>
4

    
5
/////////////////////////////////////////////////////////
6
//
7
// Particle
8
//
9
// This class enables you to set
10
// a mass and an impulse of a particle,
11
// change values and get them back.
12
// fA and fZ variables are still ambiguous
13
// and need to be discussed.
14
// Each particle also stores information about its energy states
15
//
16
////////////////////////////////////////////////////////
17

    
18
ExcitationState::ExcitationState() {
19
        //Default constructor
20
        fMean = 0.;
21
        fWidth = 0.1;
22
        fShape = "gauss";
23
        fStrength = 1;
24
}
25
;
26

    
27
ExcitationState::ExcitationState(Double_t mean, Double_t width, TString shape,
28
                Int_t strength) :
29
                fMean(mean), fWidth(width), fShape(shape), fStrength(strength) {
30
        //Constructor initializing all necessary variables for exc. state
31
}
32

    
33
TString ExcitationState::CreateConfigString() {
34
        ConfigDictionary CD;
35
        CD.SetDouble("mean", fMean);
36
        CD.SetDouble("width", fWidth);
37
        CD.SetString("shape", fShape.Data());
38
        CD.SetInt("strength", fStrength);
39
        return TString(CD.ToString().c_str());
40
}
41
;
42

    
43
int ExcitationState::ReadConfigString(TString cs) {
44
        ConfigDictionary CD(cs.Data());
45
        try {
46
                fMean = CD.GetDouble("mean");
47
                fWidth = CD.GetDouble("width");
48
                fShape = CD.GetString("shape").c_str();
49
                fStrength = CD.GetInt("strength");
50
                return SUCCESS;
51
        } catch (std::string & e) {
52
                Error("ExcitationState::ReadConfigString",
53
                                "Couldn't find parameter: %s", e.c_str());
54
                return NOTFOUND;
55
        }
56
        if (fWidth <= 0.) {
57
                Error("ExcitationState::ReadConfigString", "Width parameter <= 0!");
58
                return FAILURE;
59
        }
60
        if (fMean <= 0.) {
61
                Error("ExcitationState::ReadConfigString", "Mean parameter <= 0!");
62
                return FAILURE;
63
        }
64
        if (fStrength <= 0) {
65
                Error("ExcitationState::ReadConfigString", "Strength parameter <= 0!");
66
                return FAILURE;
67
        }
68

    
69
        return SUCCESS;
70
}
71
;
72

    
73
/////////////////////////////////////////////////////////////////////////////////////////
74
/////////////////////////////////////////////////////////////////////////////////////////
75
/////////////////////////////////////////////////////////////////////////////////////////
76

    
77
ClassImp(Particle);
78

    
79
Int_t Particle::numberOfParticles = 0;
80

    
81
Particle::Particle() {
82
// default constructor
83
// set Z = 0, A = 0
84
        Reset();
85
        fZ = 0;
86
        fA = 0;
87
        numberOfParticles++;
88
        std::stringstream ss;
89
        ss << "unnamed particle no. ";
90
        ss << numberOfParticles;
91
        SetName(ss.str().c_str());
92

    
93
//        cout << "kjadbhfkjasdf" << endl;
94

    
95
}
96
;
97

    
98
Particle::Particle(const char *name, Double_t mass, Int_t A, Int_t Z,
99
                Bool_t obs) {
100
        //name: name of the object
101
        //mass: rest-mass of the object, in MeV
102
        //A: mass number, number of nucleons
103
        //Z: charge, equals number in periodic table
104
        //set total energy equal to the mass of the particle
105

    
106
        fName = name;
107
        fMass = mass;
108
        fGroundStateMass = mass;
109
        Info("Particle::Particle", "Ground state mass was set to %f",
110
                        fGroundStateMass);
111
        fA = A;
112
        fZ = Z;
113
        fObservable = obs;
114
        fImpulse.SetE(mass);
115

    
116
}
117

    
118
Particle::Particle(TString cs) {
119
//config constructor
120
        ReadConfigString(cs);
121
        CreateStateMassFunctions();
122
}
123

    
124
Particle::~Particle() {
125
//destructor
126
        for (UInt_t i = 0; i < fState.size(); i++) {
127
                delete fState[i];
128
//                Info("DetManager::~DetManager", "Detector %s deleting", det->GetName());
129
//                delete det;
130
        }
131
        fState.clear();
132

    
133
}
134

    
135
//public functions
136

    
137
//_____________________________________________________________________________
138
void Particle::AddExcitationState(ExcitationState exstate) {
139
//add new excitation states to the particle
140
        fExcitationStates.push_back(exstate);
141
}
142

    
143
//_____________________________________________________________________________
144
void Particle::ClearExcitationStates() {
145
//clear excitation states
146
        fExcitationStates.clear();
147
}
148

    
149
//_____________________________________________________________________________
150
Int_t Particle::GetNumberOfExStates() {
151
//return number of excitation states
152
        return fExcitationStates.size();
153
}
154

    
155
//_____________________________________________________________________________
156
ExcitationState Particle::GetExcitationState(Int_t index) {
157
//return "index"th excitation state
158
        return fExcitationStates[index];
159
}
160

    
161
void Particle::Reset() {
162
        // Set mass and impulse of particle as zero value
163

    
164
        fMass = 0.;
165
        fGroundStateMass = 0.;
166
        fImpulse.SetPxPyPzE(0., 0., 0., 0.);
167
        return;
168
}
169

    
170
int Particle::CopyValues(Particle * other) {
171
        //Copies kinetic energy and direction angles from other particle
172
        //Dont check if other == null to increase speed, be careful!
173
        fImpulse.SetPxPyPzE(other->GetPx(), other->GetPy(), other->GetPz(),
174
                        other->GetE());
175
        return SUCCESS;
176
}
177

    
178
void Particle::SetMPxPyPz(Double_t m, Double_t px, Double_t py, Double_t pz) {
179
        // m: set mass in the MeV
180
        // px: x cordinate of impulse
181
        // py: y cordinate of impulse
182
        // pz: z cordinate of impulse
183

    
184
        fImpulse.SetPx(px);
185
        fImpulse.SetPy(py);
186
        fImpulse.SetPz(pz);
187
        fImpulse.SetE(CalcT(m, px, py, pz) + m);
188
        fMass = m;
189
}
190

    
191
void Particle::SetMTNxNyNz(Double_t m, Double_t T, Double_t nx, Double_t ny,
192
                Double_t nz) {
193
// m: set mass in MeV
194
// T: set kinetic energy in MeV
195
// set direction vector of impulse with (nx,ny,nz) components
196
//todo: function restored, check if it works properly
197

    
198
        fMass = m;
199
        TVector3 vect(nx, ny, nz);
200
        vect.SetMag(CalcP(m, T));
201
        fImpulse.SetVectMag(vect, m);
202
        fImpulse.SetE(Sqrt(vect.Mag2() + m * m));
203

    
204
        return;
205
}
206
;
207

    
208
void Particle::SetMTDir(Double_t m, Double_t T, TVector3 dir) {
209
        // dir: set direction vector of impulse
210
        // m: set mass in MeV
211
        // T: set kinetic energy in MeV
212
        // imp: need to use TVector3 dir(dir(0),dir(1),dir(2))
213
        // where dir(0), dir(1), dir(2) are coordinates of direction vector of impulse
214

    
215
        Double_t p = CalcP(m, T); // impulse magnitude
216
        fMass = m;
217
        fImpulse.SetE(T + m);
218
        fImpulse.SetPx(dir.Unit().x() * p);
219
        fImpulse.SetPy(dir.Unit().y() * p);
220
        fImpulse.SetPz(dir.Unit().z() * p);
221
}
222

    
223
void Particle::SetP(TVector3 P) {
224
        // set impulse of the particle
225
        fImpulse.SetXYZM(P(0), P(1), P(2), fMass);
226
}
227

    
228
void Particle::SetPx(Double_t px) {
229
// set cartesian x coordinate of impulse in MeV
230
        fImpulse.SetPx(px);
231
        //fImpulse.SetE(0.);
232
        fImpulse.SetE(Sqrt(fMass * fMass + fImpulse.Mag() * fImpulse.Mag()));
233
        return;
234
}
235
;
236

    
237
void Particle::SetPy(Double_t py) {
238
// set cartesian y coordinate of impulse in MeV
239
        fImpulse.SetPy(py);
240
        //fImpulse.SetE(0.);
241
        fImpulse.SetE(Sqrt(fMass * fMass + fImpulse.Mag() * fImpulse.Mag()));
242
}
243
;
244
void Particle::SetPz(Double_t pz) {
245
// set cartesian z coordinate of impulse in MeV
246
        fImpulse.SetPz(pz);
247
        fImpulse.SetE(0.);
248
        fImpulse.SetE(Sqrt(fMass * fMass + fImpulse.Mag() * fImpulse.Mag()));
249
}
250
;
251
void Particle::SetE(Double_t E) {
252
        // set total energy in MeV
253
        fImpulse.SetE(E);
254
}
255
;
256

    
257
void Particle::SetObservable(Bool_t obs) {
258
//whether object is observable or not
259
        fObservable = obs;
260
}
261
;
262

    
263
void Particle::SetMass(Double_t mass) {
264
        // Set particle mass.
265
        // Impulse and Kinetic energy are remained
266
        Double_t T = GetT();
267
        fMass = mass;
268
        fImpulse.SetE(T + mass);
269
}
270

    
271
void Particle::SetT(Double_t T) {
272
//set kinetic energy in MeV
273
//NB! impulse should be nonzero else you'll receive message "zero vector can't be stretched"
274

    
275
        if (T <= 0)
276
                fImpulse = TLorentzVector(0, 0, 0, fMass);
277
        else {
278
                fImpulse.SetRho(CalcP(fMass, T));
279
                fImpulse.SetE(fMass + T);
280
        }
281
}
282

    
283
void Particle::SetImpulse(TLorentzVector *P) {
284
        //set TLorenzVector
285
                fImpulse.SetPx(P->Px()*1000.);
286
                fImpulse.SetPy(P->Py()*1000.);
287
                fImpulse.SetPz(P->Pz()*1000.);
288
                fImpulse.SetE(P->E()*1000.);
289
}
290

    
291
void Particle::SetTPhiTheta(Double_t T, Double_t phi, Double_t theta) {
292
//change kinetic energy and direction
293
//T: kinetic energy in MeV
294
//phi: azimuthal angle of impulse in rad
295
//theta: polar angle of impulse in rad
296
//NB! impulse should be nonzero else you'll receive message "zero vector can't be stretched"
297

    
298
        fImpulse.SetRho(CalcP(fMass, T));
299
        fImpulse.SetE(fMass + T);
300
        fImpulse.SetPhi(phi);
301
        fImpulse.SetTheta(theta);
302
}
303
;
304

    
305
void Particle::Print(Option_t * option){
306
        // Print values:
307
        //                particle name, whether particle is observable,
308
        //                mass number and charge (in units of electron charge) of the particle,
309
        //                rest-mass and total energy in MeV, kinetic energy in MeV,
310
        //                coordinates of impulse and value of impulse in MeV,
311
        //                phi and theta angles in rad
312
        if (option != NULL) {
313
                //just checking
314
        }
315
        cout << "Name: " << fName;
316
        if (fObservable == 0)
317
                cout << " is not observable" << endl;
318
        else
319
                cout << " is observable" << endl;
320
        cout << "A, Z = " << fA << ",  " << fZ << endl << "Mass = " << fMass << endl
321
                        << "Energy = " << fImpulse.E() << endl << "Kinetic Energy = "
322
                        << GetT() << endl << "Impulse (Px;Py;Pz) = " << "(" << fImpulse.Px()
323
                        << " " << fImpulse.Py() << " " << fImpulse.Pz() << ")" << endl
324
                        << "P = " << fImpulse.Rho() << endl << "Phi = " << fImpulse.Phi()
325
                        << endl << "Theta = " << fImpulse.Theta() << endl;
326
}
327
;
328

    
329
TString Particle::CreateConfigString() {
330
        //Creates string containing config info about particle
331
        //so it can be saved to file or used anywhere else (gui?)
332
        //It saves direction of impulse as phi and theta angles
333
        //Its format looks like: (for example proton) #mass is stored in MeV I presume?
334
        //"name"="proton" "mass"="938" "observable"="true" "a_number"="1" "z_number"="1" "phi"="0.0" "theta"="0.0"
335

    
336
        ConfigDictionary CD;
337
        CD.SetString("name", GetName());
338
        CD.SetDouble("mass", GetM());
339
        CD.SetBool("observable", fObservable);
340
        CD.SetInt("a_number", GetA());
341
        CD.SetInt("z_number", GetZ());
342
        CD.SetDouble("phi", GetPhi());
343
        CD.SetDouble("theta", GetTheta());
344
        CD.SetDouble("k_energy", GetT()); //kinetic energy = GetT()
345
        CD.SetInt("exNumber", GetNumberOfExStates());
346
        TString ret(CD.ToString());
347

    
348
        return ret;
349
}
350

    
351
void Particle::ReadConfigString(TString conf) {
352
        //conf - string formatted as list of "key=value" pairs
353
        //Reads and sets parameters from config string
354
        //Parameters for impulse direction are phi and theta angles
355

    
356
        ConfigDictionary CD(conf.Data());
357
        try {
358
                SetName(CD.GetString("name").c_str());
359
                SetMass(CD.GetDouble("mass"));
360
                fGroundStateMass = GetM();
361
                Info("Particle::ReadConfigString", "Ground state mass was set to %f",
362
                                fGroundStateMass);
363
                SetObservable(CD.GetBool("observable"));
364
                SetA(CD.GetInt("a_number"));
365
                SetZ(CD.GetInt("z_number"));
366
                SetPz(1.);
367
                SetTPhiTheta(CD.GetDouble("k_energy"), CD.GetDouble("phi"),
368
                                CD.GetDouble("theta"));
369
        } catch (...) {
370
                Error("Particle::ReadConfigString", "Couldn't find all parameters!");
371
                return;
372
        }
373
}
374

    
375
TVector3 Particle::GetBoost() {
376
        // return vector beta (impulse components divided by the time component)
377
        return fImpulse.BoostVector();
378
}
379
;
380

    
381
void Particle::BoostTransform(TVector3 beta) {
382
//perform a boost transformation
383
//to correct working,we input (-beta), see TLorentzVector documentation
384
//this bug will be corrected soon
385
        fImpulse.Boost(-beta);
386
        return;
387
}
388
;
389

    
390
void Particle::CreateStatesWeigthsHist() {
391

    
392
        fStatesWeigths.SetBins(GetNumberOfExStates(), 0, GetNumberOfExStates());
393
//        fStatesWeigths.SetBins(8, 1, 8+1);
394

    
395
        for (Int_t i = 0; i < GetNumberOfExStates(); i++) {
396
//                cout << "\t\tjhagvdjhavsdasvd" << endl;
397
//                cout << i << endl;
398
//                cout << GetExcitationState(i).GetStrength() << endl;
399
//                cout << fStatesWeigths.GetNbinsX() << endl;
400
                fStatesWeigths.AddBinContent(i + 1,
401
                                GetExcitationState(i).GetStrength());
402
        }
403
}
404

    
405
void Particle::DrawWeigths() {
406
        fStatesWeigths.Draw();
407
        return;
408
}
409

    
410
void Particle::DrawMassDistribution(Int_t i, Option_t *option) {
411
        //"i" is number of excitation state
412
        //"option" is draw option in TF1
413
        if (fState.empty()) {
414
                Error("Particle::DrawMassDistribution",
415
                                "There are no defined states for particle %s", GetName());
416
                return;
417
        }
418

    
419
        if (i > (Int_t) fState.size()) {
420
                Error("Particle::DrawMassDistribution", "Maximum possible index is %d",
421
                                (Int_t) (fState.size()));
422
                return;
423
        }
424

    
425
        fState[i]->Draw(option);
426
        return;
427
}
428

    
429
void Particle::CreateStateMassFunctions() {
430
        //method creates TF1 function for each state as defined e.g.
431
        //in configuration file
432
        //
433
        //Two distributions are realized for the present in the code:
434
        //Gauss and Lorentz distributions.
435
        //In future releases other distributions will be added.
436
        //
437
        //In order to optimize the calculation process there exist
438
        //limits of distribution:
439
        //(-3*sigma ; 4*sigma) for Gauss;
440
        //(-3*FWHM ; 4*FWHM) for Lorentz.
441
        //This limits provide 98% of integral area.
442

    
443
        CreateStatesWeigthsHist();
444

    
445
        TF1 *massSpectrum;
446
        massSpectrum = NULL;
447
        Double_t xmin = 0.; //lower and
448
        Double_t xmax = 0.; //upper range for each state
449

    
450
        for (Int_t i = 0; i < GetNumberOfExStates(); i++) {
451
                // cout << GetNumberOfExStates()<< " WTF!!!!! " << GetName() << endl; 
452
                //gauss distribution of the excited state
453
                if (GetExcitationState(i).GetShape() == "gauss") {
454

    
455
                        const Double_t mean = GetExcitationState(i).GetMean();
456
                        const Double_t sigma = GetExcitationState(i).GetWidth() / 2.35;
457

    
458
                        Info(
459
                                        "Particle::CreateStateMassFunctions",
460
                                        "Creating gauss distribution with mean %f and FWHM of %f MeV",
461
                                        mean, sigma);
462

    
463
//                        const Double_t mean = GetExcitationState(i).GetMean();
464
//                        const Double_t sigma = GetExcitationState(i).GetWidth()/2.35;
465
                        xmin = mean - 4 * sigma; // important cuz for high mean and little sigma it doesnt work cuz of fNpx (see TRandom)
466
                        if (mean - 3 * sigma < 0. || sigma < 0.) {
467
                                Warning("Particle::CreateStateMassFunctions",
468
                                                "There is something weird in this state");
469
                                xmin = mean - 3 * sigma;
470
                        } //if
471

    
472
                        xmax = mean + 4 * sigma;
473
                        Info("Particle::CreateStateMassFunctions",
474
                                        "Range for this state was set from %f to %f", xmin, xmax);
475
                        //        (-3*sigma, +4*sigma)
476
                        massSpectrum = new TF1("massGauss", "TMath::Gaus(x, [0], [1])",
477
                                        xmin, xmax);
478
                        massSpectrum->SetParameters(mean, sigma); //1st parameter is mean value
479
                                                                                                          //2nd parameter is sigma
480
                } //if gauss
481

    
482
                if (GetExcitationState(i).GetShape() == "lorentzian") {
483

    
484
                        const Double_t mean = GetExcitationState(i).GetMean();
485
                        const Double_t fwhm = GetExcitationState(i).GetWidth();
486

    
487
                        Info(
488
                                        "Particle::CreateStateMassFunctions",
489
                                        "Creating lorentz distribution with mean %f and FWHM of %f MeV",
490
                                        mean, fwhm);
491

    
492
                        //                        const Double_t mean = GetExcitationState(i).GetMean();
493
                        //                        const Double_t sigma = GetExcitationState(i).GetWidth()/2.35;
494

    
495
                        if (-3 * fwhm < 0.) {
496
                                Warning("Particle::CreateStateMassFunctions",
497
                                                "There is something weird in this state");
498
                                xmin = mean - 3 * fwhm;
499
                        } //if
500

    
501
                        xmax = mean + 4 * fwhm;
502
                        Info("Particle::CreateStateMassFunctions",
503
                                        "Range for this state was set from %f to %f", xmin, xmax);
504
                        //        (-3*sigma, +4*sigma)
505
                        massSpectrum = new TF1("massLorentz",
506
                                        "TMath::BreitWigner(x, [0], [1])", xmin, xmax);
507
                        massSpectrum->SetParameters(mean, fwhm); //1st parameter is mean value
508

    
509
                } //if lorentz
510

    
511
                if (massSpectrum) {
512
                        fState.push_back(massSpectrum);
513
                        Info("Particle::CreateStateMassFunctions",
514
                                        "Function %s was created", fState[i]->GetName());
515
                } else {
516
                        Warning("Particle::CreateStateMassFunctions",
517
                                        "Function for e.s. number %d of type %s was not created", i,
518
                                        GetExcitationState(i).GetShape().Data());
519
                }
520
        }
521

    
522
        return;
523
}
524

    
525
void Particle::GenerateMass() {
526
        //calculate and set mass according to mass distribution functions
527

    
528
        if (!GetNumberOfExStates())
529
                return;
530

    
531
        //choose state:
532
        Int_t state = (Int_t) fStatesWeigths.GetRandom();
533
        //fixme Vratislav: random mass
534
        //for a few reaction in chain the same random numbers are obtained in each event
535
        //same situation as for angles
536
        Double_t mass = fGroundStateMass + fState[state]->GetRandom();
537
        SetMass(mass);
538

    
539
        return;
540
}
541

    
542
Bool_t Particle::IsObservable() {
543
//whether particle is observable (1) or not (0)
544
        return fObservable;
545
        /*
546
         if(fObservable==0)
547
         {
548
         cout << fName << " is not observable" << endl;
549
         return fObservable;
550
         }
551
         else
552
         {
553
         cout << fName << " is observable" << endl;
554
         return fObservable;
555
         }*/
556
}
557

    
558
//private functions
559
Double_t Particle::CalcT(Double_t m, Double_t px, Double_t py, Double_t pz) {
560
// Calculate kinetic energy
561
        TVector3 p(px, py, pz);
562
        return (Sqrt(p.Mag2() + m * m) - m);
563
}
564
;
565

    
566
Double_t Particle::CalcP(Double_t m, Double_t T) {
567
// Calculate value of impulse
568
        return (Sqrt(T * T + 2 * T * m));
569
}
570
;
571

    
572
Double_t Particle::CalcE() {
573
        return GetE();
574
}
575
;
576

    
577
Bool_t Particle::CheckEnergyConservation() {
578
// Check energy conservation
579
        Double_t ls = Power(fImpulse.Energy(), 2);
580
        Double_t ps = Power(fImpulse.Rho(), 2) + fMass * fMass;
581
        printf("%2.18f\t\n", ls);
582
        printf("%2.18f\t\n", ps);
583
        printf("%2.18f\t\n", TMath::Abs(ls / ps - 1.0));
584
        printf("%2.18f\t\n", 1.0e-15);
585
        printf("%f\t%f\n", Power(fImpulse.Rho(), 2), fMass * fMass);
586

    
587
        if (TMath::Abs(ls / ps - 1.0) < 1.0e-14) {
588
                cout << "Energy is conserved" << endl;
589
                return true;
590
        } else {
591
                cout << "Energy's not conserved" << endl;
592
                return false;
593
        }
594
}