10 #include "KVElasticScatter.h"
11 #include "KVMultiDetArray.h"
13 #include "KVDetector.h"
32 Error(
"KVElasticScatter",
"First define the multidetector array for the simulation");
43 KVElasticScatter::~KVElasticScatter()
73 fAtomicDensity = fTarget->GetAtomsPerCM2() * 1.e-24;
75 fMultiLayer = (fTarget->NumberOfLayers() > 1);
101 Error(
"SetDetector",
"Detector %s is unknown!", det);
105 if (fDetector->GetNode()->GetNTraj() > 1) {
106 Warning(
"SetDetector",
"Ambiguous trajectory choice: detector %s has %d trajectories", det, fDetector->GetNode()->GetNTraj());
108 auto traj = (
KVGeoDNTrajectory*)fDetector->GetNode()->GetTrajectories()->First();
109 Info(
"SetDetector",
"Using trajectory: %s", traj->GetName());
113 fAlignedDetectors.Clear();
115 traj->IterateBackFrom();
119 while ((gdn = traj->GetNextNode())) {
121 fAlignedDetectors.Add(
d);
122 fDetInd.SetValue(
d->GetLabel(), i);
127 fHistos.Expand(fNDets);
150 "<KVElasticScatter::SetTargetScatteringLayer> : No target set. Set run first."
154 fIntLayer = fTarget->GetLayerIndex(
name);
156 fTarget->SetInteractionLayer(fIntLayer, fBeamDirection);
181 "<KVElasticScatter::CalculateScattering> : Set detector first" <<
188 TIter n(&fAlignedDetectors);
190 fHistos.Add(
new TH1F(
Form(
"hEloss_%s",
d->GetName()),
"Eloss (MeV)", fBinE, 0., 0.));
201 auto max_scattering_angle = scattering_kinematics.
GetMaxAngleLab(fNucleusOfInterest);
202 if (fDetector->GetEntranceWindow().GetThetaMin() > max_scattering_angle) {
204 "Detector %s has minimum theta %f deg. > max scattering angle of %s, %f deg.: abandon calculation",
205 fDetector->GetName(), fDetector->GetEntranceWindow().GetThetaMin(), scattering_kinematics.
GetNucleus(fNucleusOfInterest)->
GetSymbol(),
206 max_scattering_angle);
213 fDetector->GetRandomAngles(th, ph);
215 while (th > max_scattering_angle);
227 TIter n(&fAlignedDetectors);
230 auto cew =
d->GetCentreOfEntranceWindow();
231 d->DetectParticle(ejectile, &cew);
248 if (!initial_checks_and_reset())
260 new TH1F(
"hDepth",
"Depth (mg/cm2)", 500, 0., fTarget->GetTotalEffectiveThickness());
261 fTheta =
new TH1F(
"hTheta",
"Theta (deg.)", 500, 0., 0.);
266 fTarget->SetInteractionLayer(fIntLayer, fBeamDirection);
267 IP = fTarget->GetInteractionPoint();
270 IP = fTarget->GetInteractionPoint(fBeamDirection);
275 if (fGetTargFromLay) {
278 auto zt = targ_mat->
GetZ();
281 if ((zt !=
int(zt)) || at !=
int(at)) {
282 Error(
"CalculateScattering",
"Target has non-elemental layer with effective Z=%f and A=%f. Cannot use.",
284 fGetTargFromLay =
false;
287 fKinematics->SetTarget({int(zt), int(at)});
290 for (
int i = 0; i <
N; i++) {
292 reset_before_new_scattering();
298 fTarget->SetIncoming();
299 fTarget->DetectParticle(&Projectile);
301 KV2Body scattering{Projectile, Target, fExx};
306 scattering.SetEDiss(fExx);
308 scattering.CalculateKinematics();
310 auto theta_phi = get_random_angles_for_scattering(scattering);
313 auto elab = scattering.GetELab(fNucleusOfInterest, theta_phi.first);
314 auto ejectile = scattering.GetNucleus(fNucleusOfInterest);
316 auto kine_branch = fKineSol;
318 if (!elab->second()) {
319 Warning(
"CalculateScattering",
"Low energy branch requested, but only high energy kinematics for theta = %f deg.",
321 ejectile->SetEnergy(*elab->first());
325 ejectile->SetEnergy(*elab->second());
329 if (!elab->second()) {
330 Warning(
"CalculateScattering",
"Both branches requested, but only high energy kinematics for theta = %f deg.",
332 ejectile->SetEnergy(*elab->first());
336 ejectile->SetEnergy(1.0);
337 ejectile->SetTheta(theta_phi.first);
338 auto angle_with_beam =
TMath::RadToDeg() * ejectile->Angle(fBeamDirection);
343 ejectile->SetEnergy(*elab->first());
348 ejectile->SetEnergy(*elab->second());
354 ejectile->SetEnergy(*elab->first());
356 ejectile->SetTheta(theta_phi.first);
357 ejectile->SetPhi(theta_phi.second);
361 double angle_with_beam =
TMath::RadToDeg() * ejectile->Angle(fBeamDirection);
362 auto xsec =
TMath::Abs(scattering.GetXSecRuthLab(angle_with_beam, fNucleusOfInterest, kine_branch));
365 fTheta->Fill(theta_phi.first, xsec);
368 fTarget->SetOutgoing();
370 fTarget->DetectParticle(ejectile);
371 fDepth->Fill(IP.
z());
374 detect_particle_fill_histograms(ejectile, theta_phi.first, theta_phi.second, xsec);
378 fTarget->SetInteractionLayer(fIntLayer, fBeamDirection);
379 IP = fTarget->GetInteractionPoint();
382 IP = fTarget->GetInteractionPoint(fBeamDirection);
384 if (fGetTargFromLay) {
387 auto zt = targ_mat->
GetZ();
390 if ((zt !=
int(zt)) || at !=
int(at)) {
391 Error(
"CalculateScattering",
"Target has non-elemental layer with effective Z=%f and A=%f. Cannot use.",
393 fGetTargFromLay =
false;
396 fKinematics->SetTarget({int(zt), int(at)});
413 return (fDetInd.HasParameter(label) ? GetEnergy(fDetInd.GetIntValue(label)) : 0);
445 Info(
"Print",
"CALCULATION DETAILS:");
447 Info(
"Print",
"Projectile is %s %.1f MeV/u; target nucleus depends on scattering layer.",
451 Info(
"Print",
"Entrance channel is: %s", fKinematics->GetTitle());
453 Info(
"Print",
"Inelastic scattering: outgoing Ex=%f", fExx);
455 Info(
"Print",
"Target used is:");
457 Info(
"Print",
"Scattering will be calculated for outgoing %s",
459 Info(
"Print",
"We will use %s kinematic solutions",
462 Info(
"Print",
"Particles scattered towards %s: theta:[%f,%f] phi:[%f,%f]", fDetector->GetName(),
463 fDetector->GetThetaMin(), fDetector->GetThetaMax(), fDetector->GetPhiMin(), fDetector->GetPhiMax());
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
R__EXTERN TRandom * gRandom
char * Form(const char *fmt,...)
Relativistic binary kinematics calculator.
Double_t GetMaxAngleLab(nucleus_of_interest i) const
void SetOutgoing(const KVNucleus &proj_out)
KVNucleus * GetNucleus(nucleus_of_interest i) const
KVDBSystem * GetSystem() const
KV2Body * GetKinematics()
Base class for detector geometry description, interface to energy-loss calculations.
Calculate elastic scattering spectra in specific detectors of a multidetector array ,...
virtual std::pair< double, double > get_random_angles_for_scattering(const KV2Body &scattering_kinematics)
void SetDetector(const Char_t *det)
virtual bool initial_checks_and_reset()
TH1F * GetEnergy()
Return pointer to energy loss histogram for chosen detector (in MeV)
void CalculateScattering(Int_t N)
Perform scattering 'N' times.
void Print() const
Print details of calculation to be performed.
void SetTargetScatteringLayer(const Char_t *name)
virtual void detect_particle_fill_histograms(KVNucleus *ejectile, double theta, double phi, double xsec)
void SetEbinning(Int_t nbins)
KVDBRun * GetDBRun(Int_t number) const
Path taken by particles through multidetector geometry.
Information on relative positions of detectors & particle trajectories.
KVDetector * GetDetector() const
virtual KVDetector * GetDetector(const Char_t *name) const
Return detector in this structure with given name.
Description of physical materials used to construct detectors & targets; interface to range tables.
virtual void SetParameters(UInt_t n, Bool_t physics_parameters_only=kFALSE)
virtual void SetSimMode(Bool_t on=kTRUE)
Description of properties and kinematics of atomic nuclei.
const Char_t * GetSymbol(Option_t *opt="") const
void SetRandomized(Bool_t r=kTRUE)
virtual Double_t Uniform(Double_t x1, Double_t x2)
RVec< PromoteType< T > > sin(const RVec< T > &v)
constexpr Double_t DegToRad()
constexpr Double_t RadToDeg()