KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
KVTarget.cpp
1#include "KVTarget.h"
2#include "KVNucleusEvent.h"
3#include "KVUnits.h"
4#include "TMath.h"
5#include "Riostream.h"
6
7using namespace std;
8
10
11
12
14
15void KVTarget::init()
16{
17 //Default initialisations
18 SetRandomized(kFALSE);
19 SetIncoming(kFALSE);
20 SetOutgoing(kFALSE);
21 fTargets = new KVList;
22 SetName("KVTarget");
23 SetTitle("Target for experiment");
24 fNLayers = 0;
25
26 fNormal.SetXYZ(0, 0, 1);
27 fIntPoint.SetXYZ(0, 0, 0);
28}
29
30
31
34
36{
37 //Default costructor
38 init();
39}
40
41
42
43
47
48KVTarget::KVTarget(const Char_t* material, const Double_t thick)
49{
50 // Just give the type & "thickness" of material for target
51 // The "thickness" is the area density of the target in mg/cm**2.
52
53 init();
54 AddLayer(material, thick);
55}
56
57
58//
59
62
64{
65 //Copy ctor
66 init();
67#if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
68 obj.Copy(*this);
69#else
70 ((KVTarget&) obj).Copy(*this);
71#endif
72}
73
74
75
76#if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
77
80
81void KVTarget::Copy(TObject& obj) const
82#else
83void KVTarget::Copy(TObject& obj)
84#endif
85{
86 //Copy this to obj
87 ((KVTarget&)obj).fTargets->Clear();// delete any existing layers
88 ((KVTarget&) obj).fNLayers = 0;
90 ((KVTarget&) obj).SetRandomized(IsRandomized());
91 ((KVTarget&) obj).SetIncoming(IsIncoming());
92 ((KVTarget&) obj).SetOutgoing(IsOutgoing());
93
94 ((KVTarget&) obj).fNormal = fNormal;
95
96 TIter next(GetLayers());
97 KVMaterial* mat;
98 while ((mat = (KVMaterial*) next())) {
99 ((KVTarget&) obj).AddLayer(mat->GetName(), mat->GetAreaDensity() / KVUnits::mg);
100 }
101}
102
103
104
110
111void KVTarget::AddLayer(const Char_t* material, Double_t thick)
112{
113 // Add a layer to a target, with 'thickness' in mg/cm**2 (area density).
114 // Sets/updates name of target with name of material.
115 // In case of multi-layer target the name is
116 // material1/material2/material3/...
117
118 fTargets->Add(new KVMaterial(thick * KVUnits::mg, material));
119 fNLayers++;
120 if (fNLayers == 1) {
121 SetName(material);
122 }
123 else {
124 TString _name(GetName());
125 _name += "/";
126 _name += material;
127 SetName(_name.Data());
128 }
129}
130
131
132
133
137
139{
140 // return sum of 'thicknesses' (area densities in mg/cm**2)
141 // of all layers in target
142
143 Float_t thick = 0.;
144 TIter next(fTargets);
145 KVMaterial* mat = 0;
146 while ((mat = (KVMaterial*) next())) {
147 thick += mat->GetAreaDensity();
148 }
149 return thick / KVUnits::mg;
150}
151
152
153
154
158
160{
161 //return sum of 'thicknesses' (area densities in mg/cm**2)
162 // of layers lay1 to lay2 in target
163
164 Double_t thick = 0.;
165 for (int i = lay1; i <= lay2; i++) {
166 thick += GetThickness(i);
167 }
168 return thick;
169}
170
171
172
173
177
179{
180 //Sets angle of target to incident beam direction by rotating about the +x axis (12 o'clock)
181 //Angle 'a' is given in degrees.
182
183 fNormal.SetXYZ(0, 0, 1);
185}
186
187
188
189
192
194{
195 //Gives angle of target to incident beam direction in degrees
196
197 return TMath::RadToDeg() * fNormal.Angle(TVector3(0, 0, 1));
198}
199
200
201
202
213
215{
216 //Return effective 'thickness' (in mg/cm**2) of layer ilayer (ilayer=1, 2, ...)
217 //By default ilayer=1 (i.e. for single layer target)
218 //The effective thickness depends on the angle of the target (rotation about
219 //x-axis => theta wrt z- (beam)-axis).
220 //It also depends on the direction of motion of the incident particle.
221 //If no particle is given, effective thicknesses are calculated as for
222 //particles travelling in the beam direction.
223
224 //get (or make) vector in particle direction of motion (z-direction if no particle)
225 //Info("KVTarget::GetEffectiveThickness","(KVParticle * part, Int_t ilayer)");
226
227 TVector3 p;
228 if (part)
229 p = part->GetMomentum();
230 else
231 p = TVector3(0, 0, 1);
232
233 return GetEffectiveThickness(p, ilayer);
234}
235
236
237
238
245
247 Int_t ilayer)
248{
249 //Return effective 'thickness' (in mg/cm**2) of layer ilayer (ilayer=1, 2, ...)
250 //By default ilayer=1 (i.e. for single layer target)
251 //The effective thickness depends on the orientation of the target (given by
252 //the direction of the normal to its surface) and on the direction (e.g. direction of a particle)
253 // Info("KVTarget::GetEffectiveThickness","TVector3 & direction,Int_t ilayer");
254 if (ilayer < 1 || ilayer > NumberOfLayers()) {
255 Error("GetEffectiveThickness(Int_t ilayer, TVector3& direction)",
256 "Layer number %d is illegal. Valid values are between 1 and %d.",
257 ilayer, NumberOfLayers());
258 return 0.0;
259 }
260 return GetLayerByIndex(ilayer)->GetEffectiveAreaDensity(fNormal, direction) / KVUnits::mg;
261}
262
263
264
265
271
273{
274 //Returns absorber corresponding to 'depth' inside target, starting from the 'entrance'
275 //layer and following the direction of 'depth'. Note: 'depth' is measured in the same
276 //'thickness' units as the thickness of the different layers of the target (mg/cm2)
277 //WARNING : returns 0 if no layer is found (depth is outside of target)
278
279 return GetLayerByIndex(GetLayerIndex(depth));
280}
281
282
283
284
291
293{
294 //Returns absorber index corresponding to 'depth' inside target, starting from the 'entrance'
295 //layer and following the direction of 'depth'. Note: 'depth' is measured in the same
296 //'thickness' units as the thickness of the different layers of the target (mg/cm2)
297 //WARNING : user should check returned index is >0
298 //If not, this means that the given depth does not correspond to a layer inside the target
299
300 Double_t thick = 0.0;
301 Double_t D = depth.Mag();
302 Int_t i = 0;
303
304 while (thick < D && i < NumberOfLayers()) {
305 //increase total thickness by effective thickness 'seen' in direction of 'depth' vector
306 thick += GetEffectiveThickness(depth, ++i);
307 }
308
309 return (thick < D ? 0 : i);
310}
311
312
313
314
320
322{
323 //Returns absorber corresponding to 'depth' inside target, starting from the 'entrance'
324 //layer and following the normal direction. Note: 'depth' is measured in the same
325 //'thickness' units as the thickness of the different layers of the target (mg/cm2, um, etc.)
326 //WARNING : returns 0 if no layer is found (depth is outside of target)
327
328 return GetLayerByIndex(GetLayerIndex(depth));
329}
330
331
332
333
338
340{
341 //Returns layer index corresponding to absorber of type 'name'.
342 //WARNING : user should check returned index is >0
343 //If not, this means that the given material name does not correspond to a layer inside the target
344 KVMaterial* mat = GetLayer(name);
345 return (mat ? GetLayers()->IndexOf(mat) + 1 : 0);
346}
347
348
349
350
353
355{
356 //Returns layer corresponding to absorber of type 'name'.
358}
359
360
361
362
365
367{
368 //'Thickness' in mg/cm**2 of layer 'ilayer' in target
369 KVMaterial* lay = GetLayerByIndex(ilayer);
370 return (lay ? lay->GetAreaDensity() / KVUnits::mg : 0.0);
371}
372
373
374
375
382
384{
385 //Returns absorber index corresponding to 'depth' inside target, starting from the 'entrance'
386 //layer and following the normal direction. Note: 'depth' is measured in the same
387 //'thickness' units as the thickness of the different layers of the target (mg/cm2)
388 //WARNING : user should check returned index is >0
389 //If not, this means that the given depth does not correspond to a layer inside the target
390
391 Double_t thick = 0.0;
392 Int_t i = 0;
393
394 while (thick < depth && i < NumberOfLayers()) {
395 //increase total thickness by thickness of layer
396 thick += GetThickness(++i);
397 }
398
399 return (thick < depth ? 0 : i);
400}
401
402
403
404
411
413{
414 //return sum of effective 'thicknesses' (mg/cm**2) of all layers in target
415 //taking into account the angle of the target to the beam
416 //and the direction of motion of the incident particle.
417 //If no particle is given, effective thicknesses are calculated as for
418 //particles travelling in the beam direction.
419
420 TVector3 p = (part ? part->GetMomentum() : TVector3(0, 0, 1));
422}
423
424
425
426
435
437 Int_t ilay2)
438{
439 //return sum of effective 'thicknesses' (mg/cm**2) of layers ilay1 to ilay2 in target
440 //taking into account the angle of the target to the beam
441 //and the given direction.
442 //
443 //GetTotalEffectiveThickness(dir) --> thickness of all layers
444 //GetTotalEffectiveThickness(dir,ilay1) --> thickness of layers ilay1 to last
445 //GetTotalEffectiveThickness(dir,ilay1,ilay2) --> thickness of layers ilay1 to ilay2
446
447 Double_t thick = 0.0;
448 ilay2 =
449 (ilay2
450 ? (ilay2 <=
451 NumberOfLayers() ? (ilay2 >=
452 ilay1 ? ilay2 : ilay1) : NumberOfLayers()) :
454 for (Int_t i = ilay1; i <= ilay2; i++) {
455 thick += GetEffectiveThickness(dir, i);
456 }
457 return thick;
458}
459
460
461
462
464
466{
467 delete fTargets;
468 fTargets = 0;
469}
470
471
472//#define DBG_TRGT
473
484
486{
487 //Simulate passage of a particle through a target.
488 //Energy losses are calculated and the particle is slowed down.
489 //We take into account the direction of motion of the particle and an arbitrary orientation of the target.
490 //
491 //The' 'TVector3* dummy'argument is not used.
492 //
493 //If IsIncoming()=kFALSE & IsOutgoing()=kFALSE, the particle will pass through the whole of the target.
494 //If IsIncoming()=kTRUE, calculate energy loss up to interaction point
495 //If IsOutgoing()=kTRUE, calculate energy loss from interaction point onwards (outwards)
496 if (kvp->GetKE() <= 0.)
497 return;
498
499 if (!IsIncoming() && !IsOutgoing()) {
500 //calculate losses in all layers
501 for (int i = 1;
502 i <= NumberOfLayers() && kvp->GetKE() > 0.;
503 i++) {
505 }
506 }
507 else {
508
509 //find starting or ending layer (where is I.P. ?)
510 Int_t iplay_index = GetLayerIndex(GetInteractionPoint());
511#ifdef DBG_TRGT
512 cout << "IP is in layer " << iplay_index << endl;
513#endif
514 //particle going forwards or backwards ?
515 TVector3 p = kvp->GetMomentum();
516 Bool_t backwards = (p * GetNormal() < 0.0);
517#ifdef DBG_TRGT
518 cout << "Particle is going ";
519 backwards ? cout << "backwards" : cout << "forwards";
520 cout << endl;
521#endif
522
523 if (iplay_index) {
524
525 KVMaterial* iplay = GetLayerByIndex(iplay_index);
526
527 //effective thickness of I.P. layer is reduced because we start/stop from inside it
528 //the effective thickness (measured along the normal) after the I.P. is given by the
529 //sum of all thicknesses up to and including this layer minus the scalar product of
530 //'depth' with the normal (i.e. the projection of 'depth' along the normal)
531
532 Double_t e_thick_iplay = GetTotalThickness(1,
533 iplay_index) -
535 e_thick_iplay =
536 (IsIncoming() ? iplay->GetAreaDensity() / KVUnits::mg -
537 e_thick_iplay : e_thick_iplay);
538
539 if (backwards)
540 e_thick_iplay = iplay->GetAreaDensity() / KVUnits::mg - e_thick_iplay;
541#ifdef DBG_TRGT
542 cout << "Effective thickness of IP layer is " << e_thick_iplay <<
543 " (real:" << iplay->GetAreaDensity() / KVUnits::mg << ")" << endl;
544#endif
545 //modify effective physical thickness of layer
546 Double_t thick_iplay = iplay->GetAreaDensity();// in g/cm**2
547 iplay->SetAreaDensity(e_thick_iplay * KVUnits::mg);
548
549 //first and last indices of layers to pass through
550 Int_t ilay1 =
551 (IsIncoming() ? (backwards ? NumberOfLayers() : 1) :
552 iplay_index);
553 Int_t ilay2 =
554 (IsIncoming() ? iplay_index
555 : (backwards ? 1 : NumberOfLayers()));
556
557 if (backwards) {
558 for (int i = ilay1;
559 i >= ilay2 && kvp->GetKE() > 0.; i--)
561 }
562 else {
563 for (int i = ilay1;
564 i <= ilay2 && kvp->GetKE() > 0.; i++)
566 }
567
568 //reset original thickness of IP layer
569 iplay->SetAreaDensity(thick_iplay);
570
571 }
572 else {
573 Error("DetectParticle", "Interaction point is outside of target");
574 }
575 }
576}
577
578
579
580
592
594{
595 //Simulate passage of a particle through a target.
596 //Energy losses are calculated but the particle's energy is not modified.
597 //We take into account the direction of motion of the particle and an arbitrary
598 //orientation of the target.
599 //
600 //The' 'TVector3* dummy'argument is not used.
601 //
602 //If IsIncoming()=kFALSE & IsOutgoing()=kFALSE, the particle will pass through the whole of the target.
603 //If IsIncoming()=kTRUE, calculate energy loss up to interaction point
604 //If IsOutgoing()=kTRUE, calculate energy loss from interaction point onwards (outwards)
605
606 Double_t Eloss = 0.0, E0 = kvp->GetKE();
607
608 if (E0 <= 0.)
609 return E0;
610
611 //make 'clone' of nucleus to simulate energy losses
612 KVNucleus clone_part(kvp->GetZ(), kvp->GetA());
613 clone_part.SetMomentum(kvp->GetMomentum());
614
615 if (!IsIncoming() && !IsOutgoing()) {
616 //calculate losses in all layers
617 for (int i = 1;
618 i <= NumberOfLayers() && clone_part.GetKE() > 0.;
619 i++) {
620 Eloss +=
621 GetLayerByIndex(i)->GetELostByParticle(&clone_part, &fNormal);
622 clone_part.SetKE(E0 - Eloss);
623 }
624 }
625 else {
626
627 //find starting or ending layer (where is I.P. ?)
628 Int_t iplay_index = GetLayerIndex(GetInteractionPoint());
629#ifdef DBG_TRGT
630 cout << "IP is in layer " << iplay_index << endl;
631#endif
632 //particle going forwards or backwards ?
633 TVector3 p = clone_part.GetMomentum();
634 Bool_t backwards = (p * GetNormal() < 0.0);
635#ifdef DBG_TRGT
636 cout << "Particle is going ";
637 backwards ? cout << "backwards" : cout << "forwards";
638 cout << endl;
639#endif
640
641 if (iplay_index) {
642
643 KVMaterial* iplay = GetLayerByIndex(iplay_index);
644
645 //effective thickness of I.P. layer is reduced because we start/stop from inside it
646 //the effective thickness (measured along the normal) after the I.P. is given by the
647 //sum of all thicknesses up to and including this layer minus the scalar product of
648 //'depth' with the normal (i.e. the projection of 'depth' along the normal)
649
650 Double_t e_thick_iplay = GetTotalThickness(1,
651 iplay_index) -
653 e_thick_iplay =
654 (IsIncoming() ? iplay->GetAreaDensity() / KVUnits::mg -
655 e_thick_iplay : e_thick_iplay);
656
657 if (backwards)
658 e_thick_iplay = iplay->GetAreaDensity() / KVUnits::mg - e_thick_iplay;
659#ifdef DBG_TRGT
660 cout << "Effective thickness of IP layer is " << e_thick_iplay <<
661 " (real:" << iplay->GetAreaDensity() / KVUnits::mg << ")" << endl;
662#endif
663 //modify effective physical thickness of layer
664 Double_t thick_iplay = iplay->GetAreaDensity(); // g/cm**2
665 iplay->SetAreaDensity(e_thick_iplay * KVUnits::mg);
666
667 //first and last indices of layers to pass through
668 Int_t ilay1 =
669 (IsIncoming() ? (backwards ? NumberOfLayers() : 1) :
670 iplay_index);
671 Int_t ilay2 =
672 (IsIncoming() ? iplay_index
673 : (backwards ? 1 : NumberOfLayers()));
674
675 if (backwards) {
676 for (int i = ilay1;
677 i >= ilay2 && clone_part.GetKE() > 0.; i--) {
678 Eloss +=
679 GetLayerByIndex(i)->GetELostByParticle(&clone_part,
680 &fNormal);
681 clone_part.SetKE(E0 - Eloss);
682 }
683 }
684 else {
685 for (int i = ilay1;
686 i <= ilay2 && clone_part.GetKE() > 0.; i++) {
687 Eloss +=
688 GetLayerByIndex(i)->GetELostByParticle(&clone_part,
689 &fNormal);
690 clone_part.SetKE(E0 - Eloss);
691 }
692 }
693
694 //reset original thickness of IP layer
695 iplay->SetAreaDensity(thick_iplay);
696
697 }
698 else {
699 Error("DetectParticle", "Interaction point is outside of target");
700 }
701 }
702 return Eloss;
703}
704
705
706
707
715
717{
718 //Simulate passage of particles from some simulation through the target material.
719 //The particles will be slowed down according to their calculated energy losses.
720 //First we SetOutgoing(): for a simulated event, energy losses are only calculated from some
721 //interaction point inside the target to the outside. This interaction point will be taken half-way
722 //through the target (by default) or at some random depth in the target if SetRandomized() is
723 //called first.
724
725 SetOutgoing();
726 for (auto& part : EventIterator(event)) { // loop over particles
728 }
729}
730
731
732
733
735
736void KVTarget::Print(Option_t* opt) const
737{
738 cout << "Target " << GetName() << ", " << GetTitle() << endl;
739 fTargets->Print(opt);
740}
741
742
743
744
746
748{
750 fTargets->Execute("Clear", Form("%s", opt));
751}
752
753
754
755
766
768{
769 //Returns last known interaction point (if part=0) or generates a new one if part!=0.
770 //
771 //if IsRandomized()=kTRUE the generated interaction point is at a random distance along the
772 //direction 'of the incident particle's trajectory through target.
773 //if IsRandomized()=kFALSE the generated interaction point is half way along the direction.
774 //
775 //If no interaction point is set by the user (i.e. GetInteractionPoint never called with
776 //the address of a KVParticle), the default is to generate an interaction point using the
777 //beam (+ve Z-)direction.
778
779 TVector3 dir;
780 if (!part) {
781 //check fIntPoint is valid
782 if (fIntPoint.Mag() > 0)
783 return fIntPoint;
784 //set default direction - beam direction
785 dir.SetXYZ(0, 0, 1);
786 }
787 else {
788 dir = part->GetMomentum();
789 }
791 Double_t depth;
792 depth = (IsRandomized() ? gRandom->Uniform(e_eff) : 0.5 * e_eff);
793 fIntPoint = depth * (dir.Unit());
794 return fIntPoint;
795}
796
797
798
799
808
810{
811 //Sets the interaction point inside the layer with index 'ilayer'
812 //
813 //if IsRandomized()=kTRUE the generated interaction point is at a random distance along the
814 //direction 'dir' inside layer (e.g. incident particle's trajectory through layer).
815 //if IsRandomized()=kFALSE the generated interaction point is half way along the direction 'dir'
816 //inside the layer
817
818 //total effective thickness (along 'dir') of all layers before 'ilayer'
819 Double_t e_eff =
820 (ilayer > 1 ? GetTotalEffectiveThickness(dir, 1, ilayer - 1) : 0.0);
821#ifdef DBG_TRGT
822 cout <<
823 "total effective thickness (along 'dir') of all layers before 'ilayer'="
824 << e_eff << endl;
825#endif
826 //effective depth inside layer (along 'dir')
827 Double_t e_eff_ilayer = GetEffectiveThickness(dir, ilayer);
828 Double_t depth =
829 (IsRandomized() ? gRandom->Uniform(e_eff_ilayer) : 0.5 *
830 e_eff_ilayer);
831#ifdef DBG_TRGT
832 cout << "dpeth inside interaction layer=" << depth << endl;
833#endif
834 fIntPoint = (e_eff + depth) * (dir.Unit());
835#ifdef DBG_TRGT
836 cout << "generated IP vector:" << endl;
838#endif
839}
840
841
842
843
851
853{
854 //Sets the interaction point inside the layer made of absorber type 'name'
855 //
856 //if IsRandomized()=kTRUE the generated interaction point is at a random distance along the
857 //direction 'dir' inside layer (e.g. incident particle's trajectory through layer).
858 //if IsRandomized()=kFALSE the generated interaction point is half way along the direction 'dir'
859 //inside the layer
860
861 Int_t ilayer = GetLayerIndex(name);
862 if (!ilayer) {
863 Error("SetInteractionLayer",
864 "No layer in target with material type %s", name);
865 }
866 SetInteractionLayer(ilayer, dir);
867}
868
869
870
871
879
881{
882 //Sets the interaction point inside the layer made of absorber type 'name'
883 //
884 //if IsRandomized()=kTRUE the generated interaction point is at a random distance along the
885 //direction along the incident particle's trajectory through layer.
886 //if IsRandomized()=kFALSE the generated interaction point is half way along the direction
887 //inside the layer
888
889 TVector3 dir = part->GetMomentum();
891}
892
893
894
895
898
900{
901 // Set material of first layer
902 if (GetLayerByIndex(1))
904}
905
906
907
908
911
913{
914 // Set 'thickness' in mg/cm**2 of a layer, by default this is the first layer
915 if (GetLayerByIndex(ilayer))
917}
918
919
920
921
925
927{
928 //Calculates total number of atoms per square centimetre of the target.
929 //For a multilayer target, the area densities for each layer are summed up.
930 Double_t atom_cib = 0;
931 for (int i = 1; i <= NumberOfLayers(); i++) {
932 //N_atoms = N_Avogadro * target_thickness (mg/cm**2) * 1.e-3 / atomic_mass_of_target
933 atom_cib +=
934 TMath::Na() * GetThickness(i) * 1.e-3 /
936 }
937 return atom_cib;
938}
939
940
941
942
956
958{
959 // Calculate initial energy of particle from its current (residual) energy, assumed
960 // to correspond to the state of the particle after passage through all or some part
961 // of the target, taking into account the particle's direction of motion and an arbitrary
962 // orientation of the target.
963 //
964 // The 'TVector3*' argument is not used.
965 //
966 // If IsIncoming()=kFALSE & IsOutgoing()=kFALSE, we assume the particle passed through the whole of the target.
967 // If IsIncoming()=kTRUE, assume current energy is energy on reaching interaction point;
968 // we calculate energy of particle before entering target
969 // If IsOutgoing()=kTRUE, assume current energy is energy on exiting from target;
970 // we calculate energy of particle at interactio point
971
972 Double_t ERes = 0.0;
973
974 //make 'clone' of nucleus to simulate energy losses
975 KVNucleus clone_part(kvp->GetZ(), kvp->GetA());
976 clone_part.SetMomentum(kvp->GetMomentum());
977
978 if (!IsIncoming() && !IsOutgoing()) {
979
980 //correct for losses in all layers
981 for (int i = NumberOfLayers(); i > 0; i--) {
982 ERes = GetLayerByIndex(i)->GetParticleEIncFromERes(&clone_part, &fNormal);
983 clone_part.SetKE(ERes);
984 }
985 return ERes;
986
987 }
988 else {
989
990 //find starting or ending layer (where is I.P. ?)
991 Int_t iplay_index = GetLayerIndex(GetInteractionPoint());
992#ifdef DBG_TRGT
993 cout << "IP is in layer " << iplay_index << endl;
994#endif
995 //particle going forwards or backwards ?
996 TVector3 p = clone_part.GetMomentum();
997 Bool_t backwards = (p * GetNormal() < 0.0);
998#ifdef DBG_TRGT
999 cout << "Particle is going ";
1000 backwards ? cout << "backwards" : cout << "forwards";
1001 cout << endl;
1002#endif
1003
1004 if (iplay_index) {
1005
1006 KVMaterial* iplay = GetLayerByIndex(iplay_index);
1007
1008 //effective thickness of I.P. layer is reduced because we start/stop from inside it
1009 //the effective thickness (measured along the normal) after the I.P. is given by the
1010 //sum of all thicknesses up to and including this layer minus the scalar product of
1011 //'depth' with the normal (i.e. the projection of 'depth' along the normal)
1012
1013 Double_t e_thick_iplay = GetTotalThickness(1,
1014 iplay_index) -
1016 e_thick_iplay =
1017 (IsIncoming() ? iplay->GetAreaDensity() / KVUnits::mg -
1018 e_thick_iplay : e_thick_iplay);
1019
1020 if (backwards)
1021 e_thick_iplay = iplay->GetAreaDensity() / KVUnits::mg - e_thick_iplay;
1022#ifdef DBG_TRGT
1023 cout << "Effective thickness of IP layer is " << e_thick_iplay <<
1024 " (real:" << iplay->GetAreaDensity() / KVUnits::mg << ")" << endl;
1025#endif
1026 //modify effective physical thickness of layer
1027 Double_t thick_iplay = iplay->GetAreaDensity();
1028 iplay->SetAreaDensity(e_thick_iplay * KVUnits::mg);
1029
1030 //first and last indices of layers to pass through
1031 Int_t ilay1 =
1032 (IsIncoming() ? (backwards ? NumberOfLayers() : 1) :
1033 iplay_index);
1034 Int_t ilay2 =
1035 (IsIncoming() ? iplay_index
1036 : (backwards ? 1 : NumberOfLayers()));
1037
1038 //correct for losses in different layers
1039 if (backwards) {
1040
1041 for (int i = ilay2;
1042 i <= ilay1; i++) {
1043 ERes =
1045 &fNormal);
1046 clone_part.SetKE(ERes);
1047 }
1048
1049 }
1050 else {
1051
1052 for (int i = ilay2;
1053 i >= ilay1 ; i--) {
1054 ERes =
1056 &fNormal);
1057 clone_part.SetKE(ERes);
1058 }
1059
1060 }
1061
1062 //reset original thickness of IP layer
1063 iplay->SetAreaDensity(thick_iplay);
1064
1065 }
1066 else {
1067 Error("GetParticleEIncFromERes", "Interaction point is outside of target");
1068 }
1069 }
1070 return ERes;
1071}
1072
1073
1074
1075
1094
1096{
1097 // Calculate initial energy of nucleus (Z,A) from given residual energy Eres, assumed
1098 // to correspond to the state of the particle after passage through all or some part
1099 // of the target, taking into account an arbitrary orientation of the target.
1100 //
1101 // *** WARNING ***
1102 // Obviously we cannot know the particle's direction of motion,
1103 // therefore we assume it to be travelling in the beam direction (0,0,1)
1104 // Normally you should use GetParticleEIncFromERes
1105 //
1106 // The' 'TVector3*' argument is not used.
1107 //
1108 // If IsIncoming()=kFALSE & IsOutgoing()=kFALSE, we assume the particle passed through the whole of the target.
1109 // If IsIncoming()=kTRUE, assume current energy is energy on reaching interaction point;
1110 // we calculate energy of particle before entering target
1111 // If IsOutgoing()=kTRUE, assume current energy is energy on exiting from target;
1112 // we calculate energy of particle at interactio point
1113
1114 //Fake nucleus
1115 KVNucleus dummy(Z, A);
1116 dummy.SetKE(Eres);
1117 return GetParticleEIncFromERes(&dummy);
1118}
1119
1120
1121
int Int_t
bool Bool_t
char Char_t
float Float_t
constexpr Bool_t kFALSE
double Double_t
const char Option_t
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
R__EXTERN TRandom * gRandom
char * Form(const char *fmt,...)
Class for iterating over nuclei in events accessed through base pointer/reference.
Abstract base class container for multi-particle events.
Definition KVEvent.h:67
Extended TList class which owns its objects by default.
Definition KVList.h:28
Description of physical materials used to construct detectors & targets; interface to range tables.
Definition KVMaterial.h:94
virtual void Copy(TObject &obj) const
Make a copy of this material object.
Double_t GetEffectiveAreaDensity(TVector3 &norm, TVector3 &direction)
void SetAreaDensity(Double_t dens)
Double_t GetAreaDensity() const
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=nullptr)
virtual void DetectParticle(KVNucleus *, TVector3 *norm=nullptr)
virtual void SetMaterial(const Char_t *type)
virtual Double_t GetELostByParticle(KVNucleus *, TVector3 *norm=nullptr)
virtual void Clear(Option_t *opt="")
Reset absorber - set stored energy lost by particles in absorber to zero.
KVMaterial()
default ctor
Double_t GetMass() const
Description of properties and kinematics of atomic nuclei.
Definition KVNucleus.h:126
Int_t GetA() const
Int_t GetZ() const
Return the number of proton / atomic number.
Base class for relativistic kinematics of massive particles.
Definition KVParticle.h:396
TVector3 GetMomentum() const
Definition KVParticle.h:604
void SetKE(Double_t ecin)
void SetMomentum(const TVector3 *v)
Definition KVParticle.h:542
Double_t GetKE() const
Definition KVParticle.h:614
virtual void Execute(const char *method, const char *params, Int_t *error=0)
virtual TObject * FindObjectByType(const Char_t *) const
virtual void Add(TObject *obj)
Calculation/correction of energy losses of particles through an experimental target.
Definition KVTarget.h:127
void Print(Option_t *opt="") const
Definition KVTarget.cpp:736
Bool_t IsIncoming() const
Definition KVTarget.h:206
KVTarget()
Default costructor.
Definition KVTarget.cpp:35
void SetAngleToBeam(Double_t a)
Definition KVTarget.cpp:178
const TVector3 & GetNormal()
Definition KVTarget.h:154
void init()
Default initialisations.
Definition KVTarget.cpp:15
virtual void Copy(TObject &obj) const
Copy this to obj.
Definition KVTarget.cpp:81
virtual void DetectParticle(KVNucleus *, TVector3 *norm=0)
Definition KVTarget.cpp:485
virtual Double_t GetELostByParticle(KVNucleus *, TVector3 *norm=0)
Definition KVTarget.cpp:593
Int_t NumberOfLayers() const
Definition KVTarget.h:166
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=0)
Definition KVTarget.cpp:957
KVList * fTargets
list of layers
Definition KVTarget.h:139
Bool_t IsOutgoing() const
Definition KVTarget.h:225
virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres)
void Clear(Option_t *opt="")
Definition KVTarget.cpp:747
TVector3 & GetInteractionPoint(KVParticle *part=0)
Definition KVTarget.cpp:767
KVMaterial * GetLayerByIndex(Int_t ilayer) const
Definition KVTarget.h:174
Int_t fNLayers
number of layers
Definition KVTarget.h:140
Double_t GetEffectiveThickness(KVParticle *part=0, Int_t ilayer=1)
Definition KVTarget.cpp:214
KVMaterial * GetLayer(TVector3 &depth)
Definition KVTarget.cpp:272
virtual ~KVTarget()
Definition KVTarget.cpp:465
KVMaterial * GetLayerByDepth(Double_t depth)
Definition KVTarget.cpp:321
void AddLayer(const Char_t *material, Double_t thick)
Definition KVTarget.cpp:111
Double_t GetTotalEffectiveThickness(KVParticle *part=0)
Definition KVTarget.cpp:412
Double_t GetThickness() const
Definition KVTarget.h:190
void SetInteractionLayer(Int_t ilayer, TVector3 &dir)
Definition KVTarget.cpp:809
void DetectEvent(KVEvent *)
Definition KVTarget.cpp:716
virtual void SetMaterial(const Char_t *type)
Set material of first layer.
Definition KVTarget.cpp:899
TVector3 fNormal
normal to target - (0,0,1) by default
Definition KVTarget.h:141
Bool_t IsRandomized() const
Definition KVTarget.h:246
void SetOutgoing(Bool_t r=kTRUE)
Definition KVTarget.h:237
Double_t GetTotalThickness()
Definition KVTarget.cpp:138
Double_t GetAtomsPerCM2() const
virtual UInt_t GetUnits() const;
Definition KVTarget.cpp:926
Double_t GetAngleToBeam()
Gives angle of target to incident beam direction in degrees.
Definition KVTarget.cpp:193
void SetLayerThickness(Float_t thick, Int_t ilayer=1)
Set 'thickness' in mg/cm**2 of a layer, by default this is the first layer.
Definition KVTarget.cpp:912
Int_t GetLayerIndex(TVector3 &depth)
Definition KVTarget.cpp:292
TVector3 fIntPoint
last randomly generated interaction point
Definition KVTarget.h:142
KVList * GetLayers() const
Definition KVTarget.h:170
virtual void Print(Option_t *option, const char *wildcard, Int_t recurse=1) const
const char * GetName() const override
const char * GetTitle() const override
virtual void SetName(const char *name)
virtual void Error(const char *method, const char *msgfmt,...) const
virtual Double_t Uniform(Double_t x1, Double_t x2)
const char * Data() const
void SetXYZ(Double_t x, Double_t y, Double_t z)
void Print(Option_t *option="") const override
TVector3 Unit() const
void RotateX(Double_t)
Double_t Angle(const TVector3 &) const
Double_t Mag() const
gr SetName("gr")
const long double mg
Definition KVUnits.h:74
constexpr Double_t DegToRad()
constexpr Double_t Na()
constexpr Double_t RadToDeg()
TArc a
ClassImp(TPyArg)