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);
235 auto E =
d->GetEnergy();
254 if (!initial_checks_and_reset())
266 new TH1F(
"hDepth",
"Depth (mg/cm2)", 500, 0., fTarget->GetTotalEffectiveThickness());
267 fTheta =
new TH1F(
"hTheta",
"Theta (deg.)", 500, 0., 0.);
272 fTarget->SetInteractionLayer(fIntLayer, fBeamDirection);
273 IP = fTarget->GetInteractionPoint();
276 IP = fTarget->GetInteractionPoint(fBeamDirection);
281 if (fGetTargFromLay) {
284 auto zt = targ_mat->
GetZ();
287 if ((zt !=
int(zt)) || at !=
int(at)) {
288 Error(
"CalculateScattering",
"Target has non-elemental layer with effective Z=%f and A=%f. Cannot use.",
290 fGetTargFromLay =
false;
293 fKinematics->SetTarget({int(zt), int(at)});
296 for (
int i = 0; i <
N; i++) {
298 reset_before_new_scattering();
304 fTarget->SetIncoming();
305 fTarget->DetectParticle(&Projectile);
307 KV2Body scattering{Projectile, Target, fExx};
312 scattering.SetEDiss(fExx);
314 scattering.CalculateKinematics();
316 auto theta_phi = get_random_angles_for_scattering(scattering);
319 auto elab = scattering.GetELab(fNucleusOfInterest, theta_phi.first);
320 auto ejectile = scattering.GetNucleus(fNucleusOfInterest);
322 auto kine_branch = fKineSol;
324 if (!elab->second()) {
325 Warning(
"CalculateScattering",
"Low energy branch requested, but only high energy kinematics for theta = %f deg.",
327 ejectile->SetEnergy(*elab->first());
331 ejectile->SetEnergy(*elab->second());
335 if (!elab->second()) {
336 Warning(
"CalculateScattering",
"Both branches requested, but only high energy kinematics for theta = %f deg.",
338 ejectile->SetEnergy(*elab->first());
342 ejectile->SetEnergy(1.0);
343 ejectile->SetTheta(theta_phi.first);
344 auto angle_with_beam =
TMath::RadToDeg() * ejectile->Angle(fBeamDirection);
349 ejectile->SetEnergy(*elab->first());
354 ejectile->SetEnergy(*elab->second());
360 ejectile->SetEnergy(*elab->first());
362 ejectile->SetTheta(theta_phi.first);
363 ejectile->SetPhi(theta_phi.second);
367 double angle_with_beam =
TMath::RadToDeg() * ejectile->Angle(fBeamDirection);
368 auto xsec =
TMath::Abs(scattering.GetXSecRuthLab(angle_with_beam, fNucleusOfInterest, kine_branch));
371 fTheta->Fill(theta_phi.first, xsec);
374 fTarget->SetOutgoing();
376 fTarget->DetectParticle(ejectile);
377 fDepth->Fill(IP.
z());
380 detect_particle_fill_histograms(ejectile, theta_phi.first, theta_phi.second, xsec);
384 fTarget->SetInteractionLayer(fIntLayer, fBeamDirection);
385 IP = fTarget->GetInteractionPoint();
388 IP = fTarget->GetInteractionPoint(fBeamDirection);
390 if (fGetTargFromLay) {
393 auto zt = targ_mat->
GetZ();
396 if ((zt !=
int(zt)) || at !=
int(at)) {
397 Error(
"CalculateScattering",
"Target has non-elemental layer with effective Z=%f and A=%f. Cannot use.",
399 fGetTargFromLay =
false;
402 fKinematics->SetTarget({int(zt), int(at)});
419 return (fDetInd.HasParameter(label) ? GetEnergy(fDetInd.GetIntValue(label)) : 0);
451 Info(
"Print",
"CALCULATION DETAILS:");
453 Info(
"Print",
"Projectile is %s %.1f MeV/u; target nucleus depends on scattering layer.",
457 Info(
"Print",
"Entrance channel is: %s", fKinematics->GetTitle());
459 Info(
"Print",
"Inelastic scattering: outgoing Ex=%f", fExx);
461 Info(
"Print",
"Target used is:");
463 Info(
"Print",
"Scattering will be calculated for outgoing %s",
465 Info(
"Print",
"We will use %s kinematic solutions",
468 Info(
"Print",
"Particles scattered towards %s: theta:[%f,%f] phi:[%f,%f]", fDetector->GetName(),
469 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 Gaus(Double_t mean=0, Double_t sigma=1)
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()