10 #include "KVElasticScatter.h"
11 #include "KVMultiDetArray.h"
13 #include "KVDetector.h"
17 #include "TObjArray.h"
32 Error(
"KVElasticScatter",
"First define the multidetector array for the simulation");
43 KVElasticScatter::~KVElasticScatter()
63 void KVElasticScatter::SetRun(Int_t run)
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);
127 fHistos.Expand(fNDets);
150 "<KVElasticScatter::SetTargetScatteringLayer> : No target set. Set run first."
154 fIntLayer = fTarget->GetLayerIndex(name);
156 fTarget->SetInteractionLayer(fIntLayer, fBeamDirection);
177 bool KVElasticScatter::initial_checks_and_reset()
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.));
199 std::pair<double, double> KVElasticScatter::get_random_angles_for_scattering(
const KV2Body& scattering_kinematics)
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);
224 void KVElasticScatter::detect_particle_fill_histograms(
KVNucleus* ejectile,
double theta,
double phi,
double xsec)
227 TIter n(&fAlignedDetectors);
236 ((TH1F*)fHistos[j++])->Fill(gRandom->Gaus(E, get_det_resolution(E)/2.35), xsec * sin(theta * TMath::DegToRad()));
239 ((TH1F*)fHistos[j++])->Fill(d->
GetEnergy(), xsec * sin(theta * TMath::DegToRad()));
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.",
335 if (!elab->second()) {
336 Warning(
"CalculateScattering",
"Both branches requested, but only high energy kinematics for theta = %f deg.",
343 ejectile->
SetTheta(theta_phi.first);
344 auto angle_with_beam = TMath::RadToDeg() * ejectile->Angle(fBeamDirection);
345 auto xsec_hi = TMath::Abs(scattering.GetXSecRuthLab(angle_with_beam, fNucleusOfInterest,
KV2Body::high_E_branch));
346 auto xsec_lo = TMath::Abs(scattering.GetXSecRuthLab(angle_with_beam, fNucleusOfInterest,
KV2Body::low_E_branch));
347 if (gRandom->Uniform() < xsec_hi / (xsec_hi + xsec_lo)) {
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);
439 return (TH1F*)fHistos[index];
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());
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
const Char_t * GetLabel() const
KVDBSystem * GetSystem() const
KV2Body * GetKinematics()
Base class for detector geometry description, interface to energy-loss calculations.
virtual Double_t GetEnergy() const
void DetectParticle(KVNucleus *, TVector3 *norm=0) override
const TVector3 GetCentreOfEntranceWindow() const
void Clear(Option_t *opt="") override
Calculate elastic scattering spectra in specific detectors of a multidetector array ,...
void SetDetector(const Char_t *det)
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)
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 SetTheta(Double_t theta)
void SetPhi(Double_t phi)
void SetEnergy(Double_t e)
void SetRandomized(Bool_t r=kTRUE)
void Warning(UserClass p, const char *location, const char *va_(fmt),...)