kaliveda-dev team mailing list archive
-
kaliveda-dev team
-
Mailing list archive
-
Message #00127
[Merge] lp:~kaliveda-dev/kaliveda/kvedaloss into lp:kaliveda
John Frankland has proposed merging lp:~kaliveda-dev/kaliveda/kvedaloss into lp:kaliveda.
Requested reviews:
Eric Bonnet (ebonnet)
For more details, see:
https://code.launchpad.net/~kaliveda-dev/kaliveda/kvedaloss/+merge/53265
new implementation of VEDALOSS routines (range & energy loss)
separates VEDALOSS from KVMaterial/KVDetector
improved methods for correcting dE for pulse-height defect (silicon detectors) or dead-zones (ChIo etc.)
--
https://code.launchpad.net/~kaliveda-dev/kaliveda/kvedaloss/+merge/53265
Your team KaliVeda Development Team is subscribed to branch lp:kaliveda.
=== modified file 'KVIndra/detectors/KVBIC.cpp'
--- KVIndra/detectors/KVBIC.cpp 2009-11-10 04:41:34 +0000
+++ KVIndra/detectors/KVBIC.cpp 2011-03-14 15:58:00 +0000
@@ -80,24 +80,18 @@
fBomb = bomb;
//build detector
- AddAbsorber(new KVMaterial("Myl", 1.5)); //mylar entry window
+ AddAbsorber(new KVMaterial("Myl", 1.5*KVUnits::um)); //mylar entry window
Float_t e = GetEffectiveEntryThickness();
- KVMaterial *gas = new KVMaterial("CF4", e);
- gas->SetPressure(pressure);
- gas->SetUnits(KVMaterial::kTORR); //set units for pressure to Torr
+ KVMaterial *gas = new KVMaterial("CF4", e*KVUnits::mm, pressure);
AddAbsorber(gas); //gas between two windows
- AddAbsorber(new KVMaterial("Myl", 1.0)); //interior window
- gas = new KVMaterial("CF4", 60);
- gas->SetPressure(pressure);
- gas->SetUnits(KVMaterial::kTORR); //set units for pressure to Torr
+ AddAbsorber(new KVMaterial("Myl", 1.0*KVUnits::um)); //interior window
+ gas = new KVMaterial("CF4", 60*KVUnits::mm,pressure);
AddAbsorber(gas); //main body of gas
SetActiveLayer(gas); //active layer - energy loss is measured
- AddAbsorber(new KVMaterial("Myl", 1.0)); //2nd interor window
- gas = new KVMaterial("CF4", e);
- gas->SetPressure(pressure);
- gas->SetUnits(KVMaterial::kTORR); //set units for pressure to Torr
+ AddAbsorber(new KVMaterial("Myl", 1.0*KVUnits::um)); //2nd interor window
+ gas = new KVMaterial("CF4", e*KVUnits::mm, pressure);
AddAbsorber(gas); //gas between two exit windows
- AddAbsorber(new KVMaterial("Myl", 1.5)); //exit window
+ AddAbsorber(new KVMaterial("Myl", 1.5*KVUnits::um)); //exit window
}
@@ -194,8 +188,8 @@
Bool_t maxDE = kFALSE;
//egas > max possible ?
- if (egas > GetBraggDE(z, a)) {
- egas = GetBraggDE(z, a);
+ if (egas > GetMaxDeltaE(z, a)) {
+ egas = GetMaxDeltaE(z, a);
maxDE = kTRUE;
}
//calculate incident energy
=== modified file 'KVIndra/detectors/KVBIC.h'
--- KVIndra/detectors/KVBIC.h 2009-11-10 04:41:34 +0000
+++ KVIndra/detectors/KVBIC.h 2011-03-14 15:58:00 +0000
@@ -55,6 +55,16 @@
{
return (fLinCal && fLinCal->GetStatus());
};
+ virtual void SetPressure(Double_t P /* torr*/)
+ {
+ // Set pressure of gas in torr
+ GetActiveLayer()->SetPressure(P);
+ };
+ virtual Double_t GetPressure() const /* torr */
+ {
+ // Give pressure of gas in torr
+ return GetActiveLayer()->GetPressure();
+ };
ClassDef(KVBIC, 2) //Blocking ChIo for E416 experiment
};
=== modified file 'KVIndra/detectors/KVChIo.cpp'
--- KVIndra/detectors/KVChIo.cpp 2010-12-03 09:16:52 +0000
+++ KVIndra/detectors/KVChIo.cpp 2011-03-14 15:58:00 +0000
@@ -64,20 +64,19 @@
}
//______________________________________________________________________________
-KVChIo::KVChIo(Float_t pressure, Float_t thick):KVINDRADetector("Myl", 2.5)
+KVChIo::KVChIo(Float_t pressure, Float_t thick):KVINDRADetector("Myl", 2.5*KVUnits::um)
{
- //Make an INDRA ChIo: 2.5micron mylar windows enclosing 'thick' mm of C3F8.
- //By default 'thick'=50mm
- //By default 'pressure'=0mbar
- //The type of these detectors is "CI"
+ // Make an INDRA ChIo: 2.5micron mylar windows enclosing 'thick' cm of C3F8,
+ // give gas pressure in mbar
+ // By default 'thick'=5cm
+ // The type of these detectors is "CI"
//gas layer
- KVMaterial *mat = new KVMaterial("C3F8", thick);
- mat->SetPressure(pressure);
+ KVMaterial *mat = new KVMaterial("C3F8", thick, pressure*KVUnits::mbar);
AddAbsorber(mat);
SetActiveLayer(mat); //gas is the active layer
// mylar for second window
- mat = new KVMaterial("Myl", 2.5);
+ mat = new KVMaterial("Myl", 2.5*KVUnits::um);
AddAbsorber(mat);
SetType("CI");
@@ -181,76 +180,21 @@
//if stopped=kTRUE, we give the correction for a particle which stops in the detector
//(by default we assume the particle continues after the detector)
//
- //If the dE energy loss in the gas is > maximum theoretical dE (GetBraggDE)
- //this calculation is not valid. The mylar energy loss is calculated for a dE
- //corresponding to dE = GetBraggDE(z,a), and then we scale up according
- //to: dE_Mylar = dE_Mylar_Bragg * (dE_measured / dE_Bragg).
- //if dE_measured - dE_Bragg > 2 MeV, a warning is printed.
+ // WARNING: if stopped=kFALSEE, and if the residual energy after the detector
+ // is known (i.e. measured in a detector placed after this one), you should
+ // first call
+ // SetEResAfterDetector(Eres);
+ // before calling this method. Otherwise, especially for heavy ions, the
+ // correction may be false for particles which are just above the punch-through energy.
egas = ((egas < 0.) ? GetEnergy() : egas);
if (egas <= 0.)
return 0.0; //check measured (calibrated) energy in gas is reasonable (>0)
- Bool_t maxDE = kFALSE;
-
- //egas > max possible ?
- Double_t de_measured = 0.;
- if (egas > GetBraggDE(z, a)) {
- de_measured = egas;
- egas = GetBraggDE(z, a);
- maxDE = kTRUE;
-// if(de_measured-egas>2.0)
-// Warning("GetELossMylar","%s: Measured de_ChIo (%f) is greater than maximum for Z=%d (%f)",
-// GetName(), de_measured, (int)z, egas);
- }
- enum KVMaterial::SolType solution = KVMaterial::kEmax;
- if(stopped) solution = KVMaterial::kEmin;
- //calculate incident energy
- Double_t e_inc = GetIncidentEnergy(z, a, egas, solution);
-
- //calculate residual energy
- Double_t e_res = GetERes(z, a, e_inc);
-
- //calculate mylar energy
- Double_t emylar = e_inc - e_res - egas;
-
- emylar = ((emylar < 0.) ? 0. : emylar);
-
- if (maxDE){
- //If the dE energy loss in the gas is > maximum theoretical dE (GetBraggDE)
- //this calculation is not valid. The mylar energy loss is calculated for a dE
- //corresponding to dE = GetBraggDE(z,a), and then we scale up according
- //to: dE_Mylar = dE_Mylar_Bragg * (dE_measured / dE_Bragg)
- emylar *= (de_measured/egas);
- }
-
+ Double_t emylar = GetCorrectedEnergy(z,a,egas,!stopped) - egas;
return emylar;
}
-//__________________________________________________________________________________________________________________________
-
-Double_t KVChIo::GetCorrectedEnergy(UInt_t z, UInt_t a, Double_t egas, Bool_t transmission)
-{
- //Redefinition of KVDetector method.
- //Based on energy loss in gas, calculates correction for mylar windows
- //from energy loss tables. Returns total energy loss in mylar+gas+mylar
- //If argument 'egas' not given, KVChIo::GetEnergy() is used
- //If transmission=kFALSE we give the correction for a particle stopping in the
- //detector (i.e. we calculate the incident energy for a particle with dE<dE_Bragg)
- //By default transmission=kTRUE & we assume the particle continues after the
- //detector.
- //
- //If the dE energy loss in the gas is > maximum theoretical dE (GetBraggDE)
- //this calculation is not valid. The mylar energy loss is calculated for a dE
- //corresponding to dE = GetBraggDE(z,a), and then we scale up according
- //to: dE_Mylar = dE_Mylar_Bragg * (dE_measured / dE_Bragg)
-
- egas = ((egas < 0.) ? GetEnergy() : egas);
- if( egas <=0 ) return 0;
- Double_t emyl = GetELossMylar(z, a, egas, !transmission);
- return (egas + emyl);
-}
-
//_______________________________________________________________________________
Double_t KVChIo::GetCalibratedEnergy()
=== modified file 'KVIndra/detectors/KVChIo.h'
--- KVIndra/detectors/KVChIo.h 2010-12-03 09:16:52 +0000
+++ KVIndra/detectors/KVChIo.h 2011-03-14 15:58:00 +0000
@@ -41,8 +41,7 @@
public:
KVChIo();
- KVChIo(Float_t pressure, Float_t thick = 50.0);
-// KVChIo(Float_t thick = 50.0);
+ KVChIo(Float_t pressure, Float_t thick = 5.0*KVUnits::cm);
virtual ~ KVChIo();
Double_t GetVoltsFromCanalPG(Double_t chan = 0.0);
@@ -77,11 +76,21 @@
};
Double_t GetELossMylar(UInt_t z, UInt_t a, Double_t egas = -1.0, Bool_t stopped=kFALSE);
- Double_t GetCorrectedEnergy(UInt_t z, UInt_t a, Double_t egas = -1.0, Bool_t transmission=kTRUE);
inline Bool_t IsCalibrated() const;
virtual Short_t GetCalcACQParam(KVACQParam*,Double_t) const;
+ virtual void SetPressure(Double_t P /* mbar */)
+ {
+ // Set pressure of gas in mbar
+ GetActiveLayer()->SetPressure(P*KVUnits::mbar);
+ };
+ virtual Double_t GetPressure() const /* mbar */
+ {
+ // Give pressure of gas in mbar
+ return GetActiveLayer()->GetPressure()/KVUnits::mbar;
+ };
+
ClassDef(KVChIo, 4) //The ionisation chamber detectors (ChIo) of the INDRA array
};
=== modified file 'KVIndra/detectors/KVChIo_e475s.h'
--- KVIndra/detectors/KVChIo_e475s.h 2010-12-03 09:16:52 +0000
+++ KVIndra/detectors/KVChIo_e475s.h 2011-03-14 15:58:00 +0000
@@ -25,7 +25,7 @@
public:
KVChIo_e475s();
- KVChIo_e475s(Float_t pressure, Float_t thick=50.0);
+ KVChIo_e475s(Float_t pressure, Float_t thick=50.0*KVUnits::mm);
virtual ~KVChIo_e475s(){};
virtual void SetCalibrators(){};
=== modified file 'KVIndra/detectors/KVPhoswich.cpp'
--- KVIndra/detectors/KVPhoswich.cpp 2009-11-02 08:25:48 +0000
+++ KVIndra/detectors/KVPhoswich.cpp 2011-03-14 15:58:00 +0000
@@ -60,10 +60,6 @@
KVPhoswich::~KVPhoswich()
{
- //If gIndra exists, remove from list of phoswich
-// if (gIndra) {
-// gIndra->GetListOfPhoswich()->Remove(this);
-// }
}
=== modified file 'KVIndra/detectors/KVSiB.cpp'
--- KVIndra/detectors/KVSiB.cpp 2009-11-10 04:41:34 +0000
+++ KVIndra/detectors/KVSiB.cpp 2011-03-14 15:58:00 +0000
@@ -32,7 +32,7 @@
KVSiB::KVSiB(Float_t thickness):KVSilicon(thickness),fLinCal(0)
{
- //Make a 'thickness' um thick silicon detector with type="SIB"
+ // Make a 'thickness' um thick silicon detector with type="SIB"
SetType("SIB");
}
=== modified file 'KVIndra/detectors/KVSilicon.cpp'
--- KVIndra/detectors/KVSilicon.cpp 2010-12-03 09:16:52 +0000
+++ KVIndra/detectors/KVSilicon.cpp 2011-03-14 15:58:00 +0000
@@ -39,7 +39,7 @@
//
//Used to describe Silicon detectors of the INDRA array.
//In order to create a detector, use the KVSilicon::KVSilicon(Float_t thick)
-//constructor with "thick" the thickness in microns.
+//constructor with "thick" the thickness in centimetres
//
//Type of detector : "SI"
@@ -70,10 +70,10 @@
}
//______________________________________________________________________________
-KVSilicon::KVSilicon(Float_t thick):KVINDRADetector("Si", thick)
+KVSilicon::KVSilicon(Float_t thick):KVINDRADetector("Si", thick*KVUnits::um)
{
- // constructor for silicon detector
- //Type of detector: "SI"
+ // constructor for silicon detector, thickness in microns
+ // Type of detector: "SI"
SetType("SI");
init();
}
@@ -235,30 +235,6 @@
return fPHD->Compute(Einc);
}
-//____________________________________________________________________________________________
-
-Double_t KVSilicon::GetCorrectedEnergy(UInt_t z, UInt_t a, Double_t e, Bool_t trn)
-{
- //Returns total energy lost by particle in silicon detector corrected for PHD.
- //
- //If "e" (measured/apparent energy loss in detector) not given, current value
- //measured in detector is used. If PHD for detector has not been set, no correction
- //is performed
- //See GetPHD() and class KVPulseHeightDefect.
- //
- //transmission=kTRUE (default): particle does not stop in the detector
- //transmission=kFALSE: particle stops in the detector
-
- if (e < 0.) e = GetEnergy();
- if( e <= 0 ) return 0;
- // calculate incident energy from measured energy loss in detector
- enum KVMaterial::SolType solution = KVMaterial::kEmax;
- if(!trn) solution = KVMaterial::kEmin;
- Double_t EINC = GetIncidentEnergy(z, a, e, solution);
- //incident energy - residual energy = total real energy loss
- return (EINC - GetERes(z, a, EINC));
-}
-
//__________________________________________________________________________________________
Double_t KVSilicon::GetCalibratedEnergy()
{
@@ -414,63 +390,6 @@
//______________________________________________________________________________
-void KVSilicon::SetELossParams(Int_t Z, Int_t A)
-{
- //Initialise energy loss coefficients for this detector and a given incident nucleus (Z,A)
- //We redefine the KVDetector::SetELossParams method in order to include the
- //pulse height defect (if defined) for the silicon detector in the calculation of
- //the energy loss in the active (silicon) layer.
-
- //PHD not defined ? ignore
- if(!fPHD || !fPHD->GetStatus()){
- KVDetector::SetELossParams(Z,A);
- return;
- }
-
- //do we need to set up the ELoss function ?
- //only if it has never been done for PHD before
- Int_t npar_siphd = 19+6; //number of params for eloss function = 19 params for energy loss + 6 for PHD (Z,a_1,a_2,b_1,b_2,Zmin)
-
- if( npar_loss != npar_siphd ){
- npar_loss = npar_siphd;
- if( par_loss ) delete [] par_loss; //delete previous parameter array
- par_loss = new Double_t[npar_loss];
- //find/create function
- //search in list of functions for one corresponding to this detector
- //the name of the required function is ELoss_SiPHD
- ELoss =
- (TF1 *) gROOT->GetListOfFunctions()->FindObject("ELoss_SiPHD");
- if (!ELoss)
- ELoss = new TF1("ELoss_SiPHD", ELossSiPHD, 0.1, 5000., npar_loss);
- }
-
- //fill parameter array
- ((KVMaterial*)fAbsorbers->At(0))->GetELossParams(Z, A, par_loss);
- par_loss[19] = Z;
- for (register int i = 0; i < 5; i++) par_loss[i+20] = fPHD->GetParameter(i);
-
- //set parameters of energy loss function
- ELoss->SetParameters(par_loss);
-}
-
-//_____________________________________________________________________________________//
-
-Double_t ELossSiPHD(Double_t * x, Double_t * par)
-{
- //Calculates measured/apparent energy loss in silicon detector, taking into account PHD
- //Parameters par[0] to par [18] are energy loss parameters for Silicon
- //Parameter par[19] is Z of nucleus
- //Parameters par[20] to par[24] are Moulton PHD parameters (see KVPulseHeightDefect
- //source file for function & parameter definitions).
- //Argument x[0] is incident energy in MeV
-
- //measured/apparent dE = real dE - PHD
- return (ELossSaclay(x, par) - PHDMoulton(x, &par[19]));
-}
-
-
-//______________________________________________________________________________
-
Short_t KVSilicon::GetCalcACQParam(KVACQParam* ACQ,Double_t ECalc) const
{
// Calculates & returns value of given acquisition parameter corresponding to
@@ -484,6 +403,26 @@
return -1;
}
+//______________________________________________________________________________
+
+TF1* KVSilicon::GetELossFunction(Int_t Z, Int_t A)
+{
+ // Overrides KVDetector::GetELossFunction
+ // If the pulse height deficit (PHD) has been set for this detector,
+ // we return an energy loss function which takes into account the PHD,
+ // i.e. for an incident energy E we calculate dEphd(E,Z,A) = dE(E,Z,A) - PHD(E',Z)
+ // (where E' is the energy just before the active layer, in case there are
+ // dead zones before it)
+ // If no PHD is set, we return the usual KVDetector::GetELossFunction
+ // which calculates dE(E,Z,A)
+
+ if(fPHD && fPHD->GetStatus()) {
+ fELossF = fPHD->GetELossFunction(Z,A);
+ fELossF->SetRange(0., GetSmallestEmaxValid(Z,A));
+ }
+ return KVDetector::GetELossFunction(Z,A);
+}
+
//__________________________________________________________________________________________
ClassImp(KVSi75)
@@ -541,7 +480,7 @@
//Default ctor
// first layer (active) : 2mm silicon (nominal)
// second layer (dead) : 40um silicon (nominal)
- AddAbsorber( new KVMaterial("Si", 40.0) );
+ AddAbsorber( new KVMaterial("Si", 40.0*KVUnits::um) );
SetType("SILI");
SetLabel("SILI");
}
=== modified file 'KVIndra/detectors/KVSilicon.h'
--- KVIndra/detectors/KVSilicon.h 2010-12-03 09:16:52 +0000
+++ KVIndra/detectors/KVSilicon.h 2011-03-14 15:58:00 +0000
@@ -29,8 +29,6 @@
class KVChIo;
class KVDBParameterSet;
-Double_t ELossSiPHD(Double_t * x, Double_t * par);
-
class KVSilicon:public KVINDRADetector {
protected:
@@ -52,7 +50,7 @@
public:
KVSilicon();
- KVSilicon(Float_t thick);
+ KVSilicon(Float_t thick /* um */);
virtual ~ KVSilicon();
Double_t GetVoltsFromCanalPG(Double_t chan = 0.0);
@@ -90,8 +88,6 @@
};
Double_t GetPHD(Double_t Einc, UInt_t Z);
- Double_t GetCorrectedEnergy(UInt_t z, UInt_t a, Double_t e = -1., Bool_t transmission=kTRUE);
- virtual void SetELossParams(Int_t Z, Int_t A);
inline Bool_t IsCalibrated() const;
@@ -100,7 +96,19 @@
void SetZminPHD(Int_t zmin) { fZminPHD = zmin; };
Int_t GetZminPHD() { return fZminPHD; };
virtual Short_t GetCalcACQParam(KVACQParam*,Double_t) const;
+ virtual TF1* GetELossFunction(Int_t Z, Int_t A);
+ virtual void SetThickness(Double_t thick /* um */)
+ {
+ // Sets thickness of active layer in microns
+ GetActiveLayer()->SetThickness(thick*KVUnits::um);
+ };
+ virtual Double_t GetThickness() const /* um */
+ {
+ // Returns thickness of active layer in microns
+ return GetActiveLayer()->GetThickness()/KVUnits::um;
+ };
+
ClassDef(KVSilicon, 7) //INDRA forward-rings silicon detector
};
=== modified file 'KVIndra/particles/KVINDRAReconNuc.cpp'
--- KVIndra/particles/KVINDRAReconNuc.cpp 2011-01-21 16:40:26 +0000
+++ KVIndra/particles/KVINDRAReconNuc.cpp 2011-03-14 15:58:00 +0000
@@ -846,6 +846,7 @@
// therefore we have to estimate the silicon energy for this particle using the CsI energy
if(!fPileup && fCoherent && GetSi()->IsCalibrated()){
// all is apparently well
+ GetSi()->SetEResAfterDetector(fECsI);
fESi = GetSi()->GetCorrectedEnergy(GetZ(),GetA());
if(fESi<=0) {
SetECode(kECode15);// bad - no Si energy
@@ -856,6 +857,7 @@
{
Double_t e0 = GetSi()->GetDeltaEFromERes(GetZ(),GetA(),fECsI);
// calculated energy: negative
+ GetSi()->SetEResAfterDetector(fECsI);
fESi = -GetSi()->GetCorrectedEnergy(GetZ(),GetA(),e0);
SetECode(kECode2);
}
@@ -865,12 +867,14 @@
// if fUseFullChIoEnergyForCalib = kFALSE, we have to estimate the ChIo energy for this particle
if(fUseFullChIoEnergyForCalib && GetChIo()->IsCalibrated()){
// all is apparently well
+ GetChIo()->SetEResAfterDetector(TMath::Abs(fESi)+fECsI);
fEChIo = GetChIo()->GetCorrectedEnergy(GetZ(),GetA());
}
else
{
- Double_t e0 = GetChIo()->GetDeltaEFromERes(GetZ(),GetA(),fECsI+fESi);
+ Double_t e0 = GetChIo()->GetDeltaEFromERes(GetZ(),GetA(),TMath::Abs(fESi)+fECsI);
// calculated energy: negative
+ GetChIo()->SetEResAfterDetector(TMath::Abs(fESi)+fECsI);
fEChIo = -GetChIo()->GetCorrectedEnergy(GetZ(),GetA(),e0);
SetECode(kECode2);
}
=== modified file 'KVMultiDet/KVMultiDetLinkDef.h'
--- KVMultiDet/KVMultiDetLinkDef.h 2011-03-14 08:44:04 +0000
+++ KVMultiDet/KVMultiDetLinkDef.h 2011-03-14 15:58:00 +0000
@@ -17,6 +17,7 @@
#pragma link C++ enum KVBase::EKaliVedaBits;
#pragma link C++ function SearchFile(const Char_t*, TString&, int);
#pragma link C++ namespace KVTGIDFunctions;
+#pragma link C++ namespace KVUnits;
#pragma link C++ nestedclass;
#pragma link C++ nestedtypedef;
#pragma extra_include "Rtypes.h";
@@ -126,7 +127,7 @@
#pragma link C++ class KVLVContainer;
#pragma link C++ class KVLVEntry;
#pragma link C++ class KVLVColumnData;
-#pragma link C++ class KVMaterial-;
+#pragma link C++ class KVMaterial+;
#pragma link C++ class KVMemoryChunk+;
#pragma link C++ class KVMemoryPool+;
#pragma link C++ class KVModule+;
@@ -253,6 +254,7 @@
#pragma link C++ class SRBFile_t+;
#pragma link C++ class SRBDataRepository+;
#pragma link C++ class SRBAvailableRunsFile+;
+<<<<<<< TREE
#pragma link C++ class KVNuclData+;
#pragma link C++ class KVLifeTime+;
#pragma link C++ class KVAbundance+;
@@ -264,4 +266,9 @@
#pragma link C++ class KVAbundanceTable+;
#pragma link C++ class KVMassExcessTable+;
#pragma link C++ class KVNDTManager+;
+=======
+#pragma link C++ class KVIonRangeTable+;
+#pragma link C++ class KVedaLossMaterial+;
+#pragma link C++ class KVedaLoss+;
+>>>>>>> MERGE-SOURCE
#endif
=== modified file 'KVMultiDet/Makefile'
--- KVMultiDet/Makefile 2009-12-08 08:32:41 +0000
+++ KVMultiDet/Makefile 2011-03-14 15:58:00 +0000
@@ -3,7 +3,7 @@
PROJ_NAME = KVMultiDet
-MODULES = analysis base calibration daq_cec data_management db detectors events geometry gui identification idmaps idtelescopes particles \
+MODULES = analysis base stopping calibration daq_cec data_management db detectors events geometry gui identification idmaps idtelescopes particles \
vg_base vg_charge vg_energy vg_multiplicity vg_shape vg_momentum trieur
EXTRA_HEADERS = base/KVError.h base/KVParameter.h
=== modified file 'KVMultiDet/calibration/KVPulseHeightDefect.cpp'
--- KVMultiDet/calibration/KVPulseHeightDefect.cpp 2009-01-22 15:03:32 +0000
+++ KVMultiDet/calibration/KVPulseHeightDefect.cpp 2011-03-14 15:58:00 +0000
@@ -37,7 +37,7 @@
// --> END_HTML
////////////////////////////////////////////////////////////////////////////////
-Double_t PHDMoulton(Double_t * x, Double_t * par)
+Double_t KVPulseHeightDefect::PHDMoulton(Double_t * x, Double_t * par)
{
//Returns Moulton PHD for given E and Z:
//
@@ -51,21 +51,14 @@
//
// x[0] = E (MeV)
// par[0] = Z
- // par[1] = a_1
- // par[2] = a_2
- // par[3] = b_1
- // par[4] = b_2
- // par[5] = Zmin
- if( par[0] <= par[5] ) return 0;
- Double_t Z = par[0];
- Double_t a = par[1]*Z*Z/1000. + par[2];
- Double_t b = par[3]*100./Z + par[4];
+ Int_t Z = par[0];
+ if( Z <= fZmin ) return 0;
+ Double_t a = a_1*Z*Z/1000. + a_2;
+ Double_t b = b_1*100./Z + b_2;
return (TMath::Power(10,b)*TMath::Power(x[0],a));
}
-TF1 KVPulseHeightDefect::fMoulton("fMoulton", PHDMoulton, 0., 5000., 6);
-
//___________________________________________________________________//
void KVPulseHeightDefect::init()
@@ -73,6 +66,9 @@
//default initialisations
SetType("Pulse Height Defect");
SetZ(1);
+ fMoulton = fDeltaEphd = 0;
+ a_1=a_2=b_1=b_2=0.;
+ fZmin=0;
}
KVPulseHeightDefect::KVPulseHeightDefect():KVCalibrator(5)
@@ -109,19 +105,7 @@
// b(Z) = b_1*(100/Z) + b_2
// E = incident energy of particle
- const_cast<KVPulseHeightDefect*>(this)->SetPars();
- return fMoulton.Eval(energy);
-}
-
-//___________________________________________________________________________
-
-void KVPulseHeightDefect::SetPars()
-{
- // Set parameters of TF1 prior to calculation (PRIVATE)
- Double_t par[6];
- for (register int i = 0; i < 5; i++) par[i+1] = GetParameter(i);
- par[0] = (Double_t) GetZ();
- fMoulton.SetParameters(par);
+ return const_cast<KVPulseHeightDefect*>(this)->GetMoultonPHDFunction(GetZ())->Eval(energy);
}
//___________________________________________________________________________
@@ -133,6 +117,62 @@
return Compute(energy);
}
+TF1* KVPulseHeightDefect::GetELossFunction(Int_t Z, Int_t A)
+{
+ // Return pointer to TF1 giving energy loss in active layer of detector minus
+ // the pulse height defect for a given nucleus (Z,A).
+
+ if(!fDeltaEphd){
+ fDeltaEphd = new TF1(Form("KVPulseHeightDefect:%s:ELossActive", GetDetector()->GetName()),
+ this, &KVPulseHeightDefect::ELossActive, 0., 1.e+04, 2, "KVPulseHeightDefect", "ELossActive");
+ fDeltaEphd->SetNpx( gEnv->GetValue("KVPulseHeightDefect.EnergyLoss.Npx", 20) );
+ }
+ fDeltaEphd->SetParameters((Double_t)Z, (Double_t)A);
+ GetMoultonPHDFunction(Z);
+ return fDeltaEphd;
+}
+
+Double_t KVPulseHeightDefect::ELossActive(Double_t *x, Double_t *par)
+{
+ // Calculate energy lost in active layer of detector minus the Moulton PHD
+ // x[0] = incident energy
+ // par[0] = Z
+ // par[1] = A
+
+ Double_t e = x[0];
+ TIter next(GetDetector()->GetListOfAbsorbers()); KVMaterial* mat;
+ while( (mat = (KVMaterial*)next()) != GetDetector()->GetActiveLayer() ){
+ // calculate energy losses in absorbers before active layer
+ e = mat->GetERes(par[0], par[1], e); //residual energy after layer
+ if (e < KVDETECTOR_MINIMUM_E)
+ return 0.; // return 0 if particle stops in layers before active layer
+ }
+ // calculate energy loss in active layer
+ Double_t dE = mat->GetDeltaE(par[0], par[1], e);
+ // calculate Moulton PHD corresponding to incident energy in active layer
+ Double_t phd = PHDMoulton(&e, par);
+
+ return dE - phd;
+}
+
+ TF1* KVPulseHeightDefect::GetMoultonPHDFunction(Int_t Z)
+ {
+ // Create TF1* fMoulton if not already done
+
+ if(!fMoulton) {
+ fMoulton = new TF1(Form("MoultonPHD:%s", GetDetector()->GetName()),
+ this, &KVPulseHeightDefect::PHDMoulton, 0., 1.e+04, 1, "KVPulseHeightDefect", "PHDMoulton");
+ a_1 = GetParameter(0);
+ a_2 = GetParameter(1);
+ b_1 = GetParameter(2);
+ b_2 = GetParameter(3);
+ fZmin = (Int_t)GetParameter(4);
+ fMoulton->SetNpx(500);
+ }
+ fMoulton->SetParameter(0,Z);
+ return fMoulton;
+ }
+
//___________________________________________________________________________
Double_t KVPulseHeightDefect::Invert(Double_t energy)
@@ -141,7 +181,7 @@
//(set using SetZ() method), this method inverts the Moulton formula
//in order to find the incident energy of the particle.
- const_cast<KVPulseHeightDefect*>(this)->SetPars();
- Double_t xmin, xmax; fMoulton.GetRange(xmin,xmax);
- return fMoulton.GetX(energy,xmin,xmax);
+ const_cast<KVPulseHeightDefect*>(this)->GetMoultonPHDFunction(GetZ());
+ Double_t xmin, xmax; fMoulton->GetRange(xmin,xmax);
+ return fMoulton->GetX(energy,xmin,xmax);
}
=== modified file 'KVMultiDet/calibration/KVPulseHeightDefect.h'
--- KVMultiDet/calibration/KVPulseHeightDefect.h 2009-01-22 15:03:32 +0000
+++ KVMultiDet/calibration/KVPulseHeightDefect.h 2011-03-14 15:58:00 +0000
@@ -12,14 +12,14 @@
#include <KVCalibrator.h>
-Double_t PHDMoulton(Double_t * x, Double_t * par);
class KVPulseHeightDefect : public KVCalibrator
{
- static TF1 fMoulton; //Moulton formula for PHD = f(E,Z)
- UInt_t fZ; //!Z of nucleus to be calibrated
-
- void SetPars();
+ TF1* fMoulton; //!Moulton formula for PHD = f(E,Z)
+ TF1* fDeltaEphd; //!deltaE calculated including PHD
+ Int_t fZ; //!Z of nucleus to be calibrated
+ Int_t fZmin; //!minimum Z for which PHD is considered
+ Double_t a_1, a_2, b_1, b_2; //! parameters of Moulton formula
public:
@@ -33,12 +33,16 @@
virtual Double_t operator() (Double_t );
virtual Double_t Invert(Double_t);
- void SetZ(UInt_t z) {
+ void SetZ(Int_t z) {
fZ = z;
};
- UInt_t GetZ() const {
+ Int_t GetZ() const {
return fZ;
};
+ Double_t PHDMoulton(Double_t * x, Double_t * par);
+ TF1* GetMoultonPHDFunction(Int_t Z);
+ Double_t ELossActive(Double_t *x, Double_t *par);
+ TF1* GetELossFunction(Int_t Z, Int_t A);
ClassDef(KVPulseHeightDefect,1)//Silicon PHD described by Moulton formula
};
=== modified file 'KVMultiDet/data/kvloss.data'
--- KVMultiDet/data/kvloss.data 2010-05-18 08:51:06 +0000
+++ KVMultiDet/data/kvloss.data 2011-03-14 15:58:00 +0000
@@ -1,14 +1,14 @@
//$Id: kvloss.data,v 1.4 2007/06/14 12:29:37 franklan Exp $
//Modified version of loss1.vedasac for KVMaterial classes
//First line gives
-// type-name, name, units flag, density, Z, atomic mass, thickness of gas (mm),
-// molecular weight, temperature [last 3 only used for gases].
-// units flag is for internal purposes and determines how "thickness" is calculated.
+// type-name, name, state, density (g/cm**3), Z, atomic mass,
+// molecular weight, temperature [last 2 only used for gases].
+// 'state' can be 'solid' or 'gas'
//Lines beginning "Z" give limits of validity for energy loss calculation
//as a function of Z and E/A.
-+ Si Silicon 1 2.33 14.0 28.0855 0. 0. 0.
++ Si Silicon solid 2.33 14.0 28.0855 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1391E+1 0.1432E+1 0.1042E+0 -.1066E-1 0.5099E-4 0.4765E-5
-.1073E+1 0.8721E+0 -.8156E-1 0.1146E-1 -.8426E-3 0.2541E-4
2. 4. 0.1500E+1 0.1309E+1 0.1525E+0 -.1717E-1 -.1733E-3 0.7908E-4
@@ -210,9 +210,9 @@
100. 252. 0.1634E+1 0.5772E+0 -.1199E-1 0.1884E-1 0.2472E-2 -.5296E-3
-.2370E+1 0.7501E+0 0.8252E+0 -.2933E+0 0.3903E-1 -.1851E-2
-+ Myl Mylar 1 1.395 4.545 8.735 0. 0. 0.
++ Myl Mylar solid 1.395 4.545 8.735 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.9435E+0 0.1577E+1 0.8671E-1 -.1634E-1 0.1885E-2 -.1336E-3
-.6187E+0 0.7095E+0 -.4930E-1 0.8294E-2 -.7041E-3 0.2359E-4
2. 4. 0.1044E+1 0.1454E+1 0.1395E+0 -.2414E-1 0.1769E-2 -.6188E-4
@@ -414,9 +414,9 @@
100. 252. 0.1182E+1 0.5533E+0 0.1721E-1 0.1818E-1 0.1377E-2 -.3958E-3
-.2066E+1 0.1569E+1 0.3647E+0 -.2140E+0 0.3561E-1 -.2003E-2
-+ NE102 Plastic 3 1.032 3.5 6.509 0. 0. 0.
++ NE102 Plastic solid 1.032 3.5 6.509 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.8330E+0 0.1605E+1 0.8125E-1 -.1629E-1 0.2028E-2 -.1501E-3
-.5293E+0 0.6794E+0 -.4110E-1 0.7086E-2 -.6185E-3 0.2139E-4
2. 4. 0.9288E+0 0.1486E+1 0.1340E+0 -.2498E-1 0.2146E-2 -.9344E-4
@@ -618,9 +618,9 @@
100. 252. 0.1102E+1 0.5582E+0 0.1074E-1 0.1767E-1 0.2284E-2 -.5073E-3
-.1922E+1 0.1616E+1 0.3091E+0 -.1967E+0 0.3324E-1 -.1881E-2
-+ Ni Nickel 2 8.902 28.0 58.6934 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ Ni Nickel solid 8.902 28.0 58.6934 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1794E+1 0.1345E+1 0.9702E-1 -.4056E-2 -.8964E-3 0.4412E-4
-.1508E+1 0.9607E+0 -.8070E-1 0.9007E-2 -.5604E-3 0.1557E-4
2. 4. 0.1892E+1 0.1234E+1 0.1429E+0 -.1142E-1 -.8038E-3 0.9291E-4
@@ -822,9 +822,9 @@
100. 252. 0.2010E+1 0.5539E+0 -.9370E-2 0.2132E-1 0.4241E-3 -.2647E-3
-.2367E+1 -.3687E+0 0.1447E+1 -.4287E+0 0.5236E-1 -.2345E-2
-+ C3F8 C3F8 0 0 8.182 17.093 50.0 188.0202 19.0
++ C3F8 Octofluoropropane gas 0 8.182 17.093 188.0202 19.0
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1187E+1 0.1512E+1 0.9917E-1 -.1521E-1 0.1205E-2 -.7625E-4
-.8428E+0 0.7909E+0 -.6996E-1 0.1100E-1 -.8766E-3 0.2780E-4
2. 4. 0.1297E+1 0.1385E+1 0.1502E+0 -.2191E-1 0.8933E-3 0.9256E-5
@@ -1026,9 +1026,9 @@
100. 252. 0.1387E+1 0.5537E+0 0.6666E-1 0.2016E-1 -.4188E-2 0.2614E-3
-.2498E+1 0.1574E+1 0.3905E+0 -.2295E+0 0.3905E-1 -.2237E-2
-+ C Carbon 2 1.90 6.0 12.011 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ C Carbon solid 1.90 6.0 12.011 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1010E+1 0.1559E+1 0.9390E-1 -.1724E-1 0.1840E-2 -.1249E-3
-.6781E+0 0.7369E+0 -.5892E-1 0.9897E-2 -.8293E-3 0.2731E-4
2. 4. 0.1117E+1 0.1431E+1 0.1464E+0 -.2438E-1 0.1560E-2 -.3813E-4
@@ -1230,9 +1230,9 @@
100. 252. 0.1263E+1 0.5824E+0 0.7019E-2 0.1550E-1 0.2413E-2 -.4678E-3
-.2102E+1 0.1482E+1 0.3437E+0 -.1808E+0 0.2776E-1 -.1451E-2
-+ Ag Silver 2 10.5 47.0 107.8682 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ Ag Silver solid 10.5 47.0 107.8682 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2170E+1 0.1307E+1 0.8207E-1 -.6085E-3 -.7715E-3 -.1175E-5
-.1877E+1 0.9851E+0 -.6665E-1 0.5782E-2 -.3041E-3 0.8360E-5
2. 4. 0.2253E+1 0.1206E+1 0.1275E+0 -.8997E-2 -.4412E-3 0.3295E-4
@@ -1434,9 +1434,9 @@
100. 252. 0.2256E+1 0.5653E+0 0.1612E-2 0.1933E-1 -.8577E-3 -.5125E-4
-.2326E+1 -.8741E+0 0.1598E+1 -.4352E+0 0.5037E-1 -.2167E-2
-+ Sn Tin 2 5.75 50.0 118.710 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ Sn Tin solid 5.75 50.0 118.710 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2238E+1 0.1304E+1 0.7985E-1 -.3463E-3 -.7042E-3 -.1061E-4
-.1941E+1 0.9876E+0 -.6487E-1 0.5446E-2 -.2817E-3 0.7822E-5
2. 4. 0.2319E+1 0.1205E+1 0.1252E+0 -.8871E-2 -.3341E-3 0.1999E-4
@@ -1639,9 +1639,9 @@
-.2595E+1 -.5102E+0 0.1384E+1 -.3793E+0 0.4376E-1 -.1875E-2
-+ CsI Cesium_Iodide 3 4.51 54. 129.905 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ CsI CesiumIodide solid 4.51 54. 129.905 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2294E+1 0.1302E+1 0.7701E-1 -.8533E-4 -.6047E-3 -.2335E-4
-.1990E+1 0.9862E+0 -.6225E-1 0.5043E-2 -.2581E-3 0.7331E-5
2. 4. 0.2372E+1 0.1204E+1 0.1223E+0 -.8750E-2 -.2054E-3 0.5590E-5
@@ -1844,9 +1844,9 @@
-.2908E+1 -.2595E-1 0.1068E+1 -.2878E+0 0.3175E-1 -.1291E-2
-+ Au Gold 2 19.3 79.0 196.96655 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ Au Gold solid 19.3 79.0 196.96655 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2536E+1 0.1300E+1 0.6188E-1 0.3559E-3 0.8626E-4 -.9808E-4
-.2178E+1 0.9665E+0 -.5087E-1 0.3869E-2 -.2256E-3 0.7655E-5
2. 4. 0.2601E+1 0.1208E+1 0.1075E+0 -.8978E-2 0.6010E-3 -.7457E-4
@@ -2049,9 +2049,9 @@
-.9877E+0 -.3494E+1 0.2679E+1 -.6177E+0 0.6352E-1 -.2468E-2
-+ U Uranium 2 18.95 92. 238.0289 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ U Uranium solid 18.95 92. 238.0289 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2652E+1 0.1304E+1 0.5572E-1 0.1675E-3 0.4154E-3 -.1292E-3
-.2263E+1 0.9587E+0 -.4833E-1 0.3900E-2 -.2553E-3 0.9003E-5
2. 4. 0.2711E+1 0.1214E+1 0.1016E+0 -.9389E-2 0.9604E-3 -.1066E-3
@@ -2254,9 +2254,9 @@
-.2286E+0 -.4604E+1 0.3112E+1 -.6884E+0 0.6837E-1 -.2567E-2
-+ Air Air 0 0 7.212 14.428 50.0 28.848 19.0
++ Air Air gas 0 7.212 14.428 28.848 19.0
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1086E+1 0.1532E+1 0.9708E-1 -.1632E-1 0.1539E-2 -.1001E-3
-.7506E+0 0.7647E+0 -.6505E-1 0.1061E-1 -.8693E-3 0.2808E-4
2. 4. 0.1194E+1 0.1403E+1 0.1490E+0 -.2301E-1 0.1179E-2 -.1159E-4
@@ -2459,9 +2459,9 @@
-.2494E+1 0.1599E+1 0.4181E+0 -.2492E+0 0.4320E-1 -.2521E-2
-+ Nb Nobium 2 8.57 41.0 92.9064 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ Nb Nobium solid 8.57 41.0 92.9064 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2082E+1 0.1314E+1 0.8674E-1 -.1315E-2 -.8874E-3 0.1774E-4
-.1795E+1 0.9853E+0 -.7145E-1 0.6646E-2 -.3636E-3 0.9829E-5
2. 4. 0.2169E+1 0.1211E+1 0.1321E+0 -.9419E-2 -.5992E-3 0.5259E-4
@@ -2664,9 +2664,9 @@
-.2307E+1 -.8474E+0 0.1626E+1 -.4498E+0 0.5264E-1 -.2283E-2
-+ Ta Tantalum 2 16.654 73. 180.9479 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ Ta Tantalum solid 16.654 73. 180.9479 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2488E+1 0.1299E+1 0.6507E-1 0.3753E-3 -.7426E-4 -.8208E-4
-.2144E+1 0.9715E+0 -.5281E-1 0.3983E-2 -.2205E-3 0.7233E-5
2. 4. 0.2556E+1 0.1206E+1 0.1106E+0 -.8829E-2 0.4173E-3 -.5739E-4
@@ -2869,9 +2869,9 @@
-.1138E+1 -.3268E+1 0.2621E+1 -.6159E+0 0.6429E-1 -.2531E-2
-+ Al Aluminium 2 2.6989 13.0 26.9815 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ Al Aluminium solid 2.6989 13.0 26.9815 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1389E+1 0.1443E+1 0.1040E+0 -.1138E-1 0.2061E-3 -.5113E-5
-.1063E+1 0.8660E+0 -.8158E-1 0.1164E-1 -.8629E-3 0.2610E-4
2. 4. 0.1499E+1 0.1319E+1 0.1527E+0 -.1785E-1 -.4496E-4 0.7172E-4
@@ -3074,9 +3074,9 @@
-.2350E+1 0.7300E+0 0.8520E+0 -.3065E+0 0.4146E-1 -.2001E-2
-+ KCl KCl 2 1.987 18.0 37.27565 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ KCl KCl solid 1.987 18.0 37.27565 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1549E+1 0.1397E+1 0.1033E+0 -.8198E-2 -.4010E-3 0.3012E-4
-.1242E+1 0.9134E+0 -.8462E-1 0.1105E-1 -.7693E-3 0.2246E-4
2. 4. 0.1656E+1 0.1278E+1 0.1506E+0 -.1491E-1 -.5298E-3 0.9645E-4
@@ -3279,9 +3279,9 @@
-.2593E+1 0.8169E+0 0.7883E+0 -.2800E+0 0.3712E-1 -.1760E-2
-+ CF4 CF4 0 0 8.40 17.601 50.0 88.046 19.0
++ CF4 Tetrafluoromethane gas 0 8.40 17.601 88.046 19.0
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1201E+1 0.1508E+1 0.9964E-1 -.1504E-1 0.1150E-2 -.7201E-4
-.8563E+0 0.7956E+0 -.7093E-1 0.1110E-1 -.8806E-3 0.2784E-4
2. 4. 0.1310E+1 0.1381E+1 0.1505E+0 -.2171E-1 0.8374E-3 0.1327E-4
@@ -3484,9 +3484,9 @@
-.2530E+1 0.1568E+1 0.4070E+0 -.2358E+0 0.3998E-1 -.2285E-2
-+ Ca Calcium 2 1.550 20.0 40.078 0. 0. 0.
++ Ca Calcium solid 1.550 20.0 40.078 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1570E+1 0.1384E+1 0.1024E+0 -.7159E-2 -.5674E-3 0.3821E-4
-.1271E+1 0.9212E+0 -.8349E-1 0.1058E-1 -.7226E-3 0.2094E-4
2. 4. 0.1675E+1 0.1267E+1 0.1492E+0 -.1404E-1 -.6303E-3 0.9995E-4
@@ -3689,9 +3689,9 @@
-.2509E+1 0.4779E+0 0.9968E+0 -.3303E+0 0.4250E-1 -.1972E-2
-+ Ge Germanium 2 5.323 32.0 72.64 0. 0. 0.
++ Ge Germanium solid 5.323 32.0 72.64 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1946E+1 0.1333E+1 0.9387E-1 -.2968E-2 -.9443E-3 0.3906E-4
-.1661E+1 0.9806E+0 -.7940E-1 0.8308E-2 -.4920E-3 0.1336E-4
2. 4. 0.2040E+1 0.1224E+1 0.1392E+0 -.1052E-1 -.7384E-3 0.7290E-4
@@ -3894,9 +3894,9 @@
-.2308E+1 -.8158E+0 0.1715E+1 -.4976E+0 0.6075E-1 -.2739E-2
-+ Cu Copper 2 8.96 29.0 63.546 0. 0. 0.
++ Cu Copper solid 8.96 29.0 63.546 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1857E+1 0.1342E+1 0.9627E-1 -.3763E-2 -.9160E-3 0.4353E-4
-.1571E+1 0.9701E+0 -.8112E-1 0.8887E-2 -.5444E-3 0.1497E-4
2. 4. 0.1954E+1 0.1231E+1 0.1425E+0 -.1116E-1 -.8653E-3 0.9969E-4
@@ -4099,9 +4099,9 @@
-.2375E+1 -.4707E+0 0.1519E+1 -.4513E+0 0.5569E-1 -.2528E-2
-+ Ti Titanium 2 4.54 22.0 47.867 0. 0. 0.
++ Ti Titanium solid 4.54 22.0 47.867 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1703E+1 0.1372E+1 0.1013E+0 -.6260E-2 -.6836E-3 0.4217E-4
-.1404E+1 0.9461E+0 -.8558E-1 0.1043E-1 -.6891E-3 0.1953E-4
2. 4. 0.1806E+1 0.1256E+1 0.1478E+0 -.1324E-1 -.7105E-3 0.1002E-3
@@ -4304,9 +4304,9 @@
-.2437E+1 -.1083E-1 0.1313E+1 -.4180E+0 0.5378E-1 -.2521E-2
-+ Bi Bismuth 2 9.747 83.0 208.98038 0. 0. 0.
++ Bi Bismuth solid 9.747 83.0 208.98038 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2572E+1 0.1301E+1 0.5992E-1 0.2980E-3 0.1936E-3 -.1084E-3
-.2204E+1 0.9642E+0 -.5002E-1 0.3867E-2 -.2341E-3 0.8064E-5
2. 4. 0.2666E+1 0.1199E+1 0.1000E+0 -.6415E-2 0.4247E-3 -.8060E-4
@@ -4509,9 +4509,9 @@
-.2321E+1 -.1423E+1 0.1639E+1 -.3809E+0 0.3806E-1 -.1413E-2
-+ V Vanadium 2 6.11 23. 50.9415 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ V Vanadium solid 6.11 23. 50.9415 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1743E+1 0.1367E+1 0.1007E+0 -.5818E-2 -.7426E-3 0.4433E-4
-.1446E+1 0.9535E+0 -.8556E-1 0.1024E-1 -.6671E-3 0.1876E-4
2. 4. 0.1846E+1 0.1252E+1 0.1470E+0 -.1285E-1 -.7460E-3 0.1000E-3
@@ -4714,9 +4714,9 @@
-.2479E+1 0.2175E-1 0.1277E+1 -.4073E+0 0.5263E-1 -.2483E-2
-+ C4H10 Isobutane 0 0 2.429 4.152 50.0 58.0 19.0
++ C4H10 Isobutane gas 0 2.429 4.152 58.12 19.0
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.6534E+0 0.1643E+1 0.7193E-1 -.1573E-1 0.2192E-2 -.1704E-3
-.3984E+0 0.6425E+0 -.3041E-1 0.5452E-2 -.4990E-3 0.1815E-4
2. 4. 0.7417E+0 0.1529E+1 0.1249E+0 -.2546E-1 0.2586E-2 -.1347E-3
@@ -4919,9 +4919,9 @@
-.1660E+1 0.1866E+1 -.2700E-1 -.9656E-1 0.2255E-1 -.1550E-2
-+ Pb Lead 2 11.35 82. 207.2 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ Pb Lead solid 11.35 82. 207.2 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2569E+1 0.1301E+1 0.6035E-1 0.3209E-3 0.1681E-3 -.1060E-3
-.2203E+1 0.9651E+0 -.5021E-1 0.3860E-2 -.2315E-3 0.7947E-5
2. 4. 0.2669E+1 0.1197E+1 0.9961E-1 -.5993E-2 0.3577E-3 -.7784E-4
@@ -5124,9 +5124,9 @@
-.1936E+1 -.2071E+1 0.1994E+1 -.4702E+0 0.4870E-1 -.1902E-2
-+ PbS Lead_sulphide 2 7.5 49. 120. 0. 0. 0.
-Z = 1,2 0.1 < E/A < 500 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
++ PbS LeadSulphide solid 7.5 49. 120. 0. 0.
+Z = 1,2 0.1 < E/A < 400 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.2332E+1 0.1340E+1 0.6956E-1 -.3771E-2 0.5808E-3 -.1136E-3
-.1977E+1 0.9829E+0 -.7385E-1 0.8338E-2 -.5732E-3 0.1743E-4
2. 4. 0.2427E+1 0.1226E+1 0.1142E+0 -.9551E-2 0.3095E-3 -.3971E-4
@@ -5329,9 +5329,9 @@
-.2333E+1 -.1236E+1 0.1689E+1 -.4269E+0 0.4632E-1 -.1876E-2
-+ Mg Magnesium 2 1.738 12.0 24.3050 0. 0. 0.
++ Mg Magnesium solid 1.738 12.0 24.3050 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1327E+1 0.1454E+1 0.1036E+0 -.1213E-1 0.3751E-3 -.1623E-4
-.1001E+1 0.8495E+0 -.7926E-1 0.1156E-1 -.8722E-3 0.2670E-4
2. 4. 0.1446E+1 0.1320E+1 0.1566E+0 -.1906E-1 0.8074E-4 0.6822E-4
@@ -5534,9 +5534,9 @@
-.2382E+1 0.8949E+0 0.7874E+0 -.3016E+0 0.4242E-1 -.2118E-2
-+Li Lithium 1 0.534 3.0 6.941 0. 0. 0.
++Li Lithium solid 0.534 3.0 6.941 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.9314E+0 0.1634E+1 0.8194E-1 -.1796E-1 0.2213E-2 -.1475E-3
-.5856E+0 0.6761E+0 -.4253E-1 0.7258E-2 -.6097E-3 0.2010E-4
2. 4. 0.1030E+1 0.1514E+1 0.1360E+0 -.2708E-1 0.2363E-2 -.8904E-4
@@ -5738,9 +5738,9 @@
100. 252. 0.1217E+1 0.5142E+0 0.1427E-1 0.2357E-1 0.1572E-2 -.5516E-3
-.2171E+1 0.1448E+1 0.5935E+0 -.3137E+0 0.5230E-1 -.2971E-2
-+Zn Zinc 1 7.133 30.0 65.390 0. 0. 0.
++Zn Zinc solid 7.133 30.0 65.390 0. 0.
Z = 1,2 0.1 < E/A < 400 MeV
-Z = 3,100 0.1 < E/A < 150 MeV
+Z = 3,100 0.1 < E/A < 250 MeV
1. 1. 0.1871E+1 0.1339E+1 0.9546E-1 -.3501E-2 -.9226E-3 0.4174E-4
-.1585E+1 0.9714E+0 -.8023E-1 0.8677E-2 -.5270E-3 0.1447E-4
2. 4. 0.1972E+1 0.1223E+1 0.1439E+0 -.1129E-1 -.8221E-3 0.9275E-4
=== modified file 'KVMultiDet/detectors/KVDetector.cpp'
--- KVMultiDet/detectors/KVDetector.cpp 2011-02-18 14:02:41 +0000
+++ KVMultiDet/detectors/KVDetector.cpp 2011-03-14 15:58:00 +0000
@@ -108,11 +108,11 @@
fIDTelAlign->SetCleanup(kTRUE);
fIDTele4Ident=0;
fIdentP = fUnidentP = 0;
- npar_loss = npar_res = 0;
- par_loss = par_res = 0;
fTotThickness = 0.;
fDepthInTelescope = 0.;
fFiredMask.Set("0");
+ fELossF = fEResF = 0;
+ fEResforEinc = -1.;
}
KVDetector::KVDetector()
@@ -125,7 +125,7 @@
KVDetector::KVDetector(const Char_t * type,
const Float_t thick):KVMaterial()
{
- //Create a new detector of a given material and thickness (default value = 0.0)
+ // Create a new detector of a given material and thickness in centimetres (default value = 0.0)
init();
SetType("DET");
@@ -176,22 +176,22 @@
SafeDelete(fParticles);
delete fAbsorbers;
SafeDelete(fACQParams);
+ SafeDelete(fELossF);
+ SafeDelete(fEResF);
init();
fActiveLayer = -1;
fIDTelAlign->Clear();
SafeDelete(fIDTelAlign);
- if(par_loss) delete [] par_loss;
- if(par_res) delete [] par_res;
SafeDelete(fIDTele4Ident);
-
}
//________________________________________________________________
void KVDetector::SetMaterial(const Char_t * type)
{
- //Set material of active layer.
- //If no absorbers have been added to the detector, create and add
- //one (active layer by default)
+ // Set material of active layer.
+ // If no absorbers have been added to the detector, create and add
+ // one (active layer by default)
+
if (!GetActiveLayer())
AddAbsorber(new KVMaterial(type));
else
@@ -546,6 +546,7 @@
while ((mat = (KVMaterial *) next())) {
mat->Clear();
}
+ fEResforEinc=-1.;
}
//______________________________________________________________________________
@@ -602,7 +603,7 @@
if (fcon == KVD_RECPRC_CNXN)
T->AddDetector(this, KVD_NORECPRC_CNXN);
} else {
- Warning("AddToTelescope", KVDETECTOR_ADD_TO_UNKNOWN_TELESCOPE);
+ Warning("AddToTelescope", "Pointer to telescope is null");
}
}
@@ -808,32 +809,55 @@
Double_t KVDetector::GetCorrectedEnergy(UInt_t z, UInt_t a, Double_t e, Bool_t transmission)
{
- //This function should be redefined in specific detector child classes in order
- //to return the total energy loss in the detector for a given nucleus
- //including inactive absorber layers, and any particle-dependent correction to
- //the 'raw' energy calibration.
+ // Returns the total energy loss in the detector for a given nucleus
+ // including inactive absorber layers.
+ // e = energy loss in active layer (if not given, we use current value)
+ // transmission = kTRUE (default): the particle is assumed to emerge with
+ // a non-zero residual energy Eres after the detector.
+ // = kFALSE: the particle is assumed to stop in the detector.
//
- //If not redefined, this just returns the same as GetEnergy()
+ // WARNING: if transmission=kTRUE, and if the residual energy after the detector
+ // is known (i.e. measured in a detector placed after this one), you should
+ // first call
+ // SetEResAfterDetector(Eres);
+ // before calling this method. Otherwise, especially for heavy ions, the
+ // correction may be false for particles which are just above the punch-through energy.
- if (e > 0.)
- return e;
- return GetEnergy();
+ if (e < 0.) e = GetEnergy();
+ if( e <= 0 ) { SetEResAfterDetector(-1.); return 0; }
+
+ enum KVIonRangeTable::SolType solution = KVIonRangeTable::kEmax;
+ if(!transmission) solution = KVIonRangeTable::kEmin;
+
+ Double_t EINC, ERES = GetEResAfterDetector();
+ if(transmission && ERES>0.){
+ // if residual energy is known we use it to calculate EINC.
+ // if EINC < max of dE curve, we change solution
+ EINC = GetIncidentEnergyFromERes(z, a, ERES);
+ if(EINC < GetEIncOfMaxDeltaE(z,a)) solution = KVIonRangeTable::kEmin;
+ // we could keep the EINC value calculated using ERES, but then
+ // the corrected dE of this detector would not depend on the
+ // measured dE !
+ }
+ EINC = GetIncidentEnergy(z, a, e, solution);
+ ERES = GetERes(z,a,EINC);
+
+ SetEResAfterDetector(-1.);
+ //incident energy - residual energy = total real energy loss
+ return (EINC - ERES);
}
//______________________________________________________________________________//
-UInt_t KVDetector::FindZmin(Double_t ELOSS, Char_t mass_formula)
+Int_t KVDetector::FindZmin(Double_t ELOSS, Char_t mass_formula)
{
//For particles which stop in the first stage of an identification telescope,
//we can at least estimate a minimum Z value based on the energy lost in this
//detector.
//
- //This is based on the KVMaterial::GetBraggDE method, giving the maximum
- //energy loss in the detector for a given nucleus. For e.g. single-layer silicon
- //detectors this energy corresponds to the threshold or punch-through energy
- //(including correction for pulse-height deficit, if known), whereas
- //for e.g. gas detectors with mylar windows this energy is slightly higher than that
- //corresponding to the limit of the particle stopping in the detector.
+ //This is based on the KVMaterial::GetMaxDeltaE method, giving the maximum
+ //energy loss in the active layer of the detector for a given nucleus (A,Z).
+ //
//The "Zmin" is the Z of the particle which gives a maximum energy loss just greater
//than that measured in the detector. Particles with Z<Zmin could not lose as much
//energy and so are excluded.
@@ -864,7 +888,7 @@
particle.SetZ(z);
- difference = GetBraggDE(z,particle.GetA()) - ELOSS;
+ difference = GetMaxDeltaE(z,particle.GetA()) - ELOSS;
//if difference < 0 the z is too small
if (difference < 0.0) {
@@ -890,133 +914,56 @@
//_____________________________________________________________________________________//
-Double_t ELossActive(Double_t * x, Double_t * par)
+Double_t KVDetector::ELossActive(Double_t * x, Double_t * par)
{
- //Calculates energy loss in active layer of detector, taking into account preceding layers
- //First parameter is number of active layer, first layer is numbered 1
- //Following parameters (by sets of 19) are parameters for energy loss in different layers
- //Argument x[0] is incident energy in MeV
-
- Int_t n_active = (Int_t) par[0];
- if (n_active < 2)
- return ELossSaclay(x, &par[1]);
- else {
- Int_t par_ind = 1;
- Double_t e = x[0];
- for (Int_t layer = 1; layer < n_active; layer++) {
-
- e = EResSaclay(&e, &par[par_ind]); //residual energy after layer
+ // Calculates energy loss (in MeV) in active layer of detector, taking into account preceding layers
+ //
+ // Arguments are:
+ // x[0] is incident energy in MeV
+ // Parameters are:
+ // par[0] Z of ion
+ // par[1] A of ion
+
+ Double_t e = x[0];
+ TIter next(fAbsorbers); KVMaterial* mat;
+ if(fActiveLayer>0){
+ // calculate energy losses in absorbers before active layer
+ for (Int_t layer = 0; layer < fActiveLayer; layer++) {
+
+ mat = (KVMaterial*)next();
+ e = mat->GetERes(par[0], par[1], e); //residual energy after layer
if (e < KVDETECTOR_MINIMUM_E)
return 0.; // return 0 if particle stops in layers before active layer
- par_ind += 19;
}
- //calculate energy loss in active layer
- return ELossSaclay(&e, &par[par_ind]);
}
- return 0.;
+ mat = (KVMaterial*)next();
+ //calculate energy loss in active layer
+ return mat->GetDeltaE(par[0], par[1], e);
}
//_____________________________________________________________________________________//
-Double_t EResDet(Double_t * x, Double_t * par)
-{
- //Calculates residual energy of particle after traversing all layers of detector.
- //Returned value is 0 if particle stops in one of the layers of the detector.
- //First parameter par[0]=number of layers of detector
- //Following parameters (by sets of 19) are parameters for energy loss in different layers
- //Argument x[0] is incident energy in MeV
-
- Int_t n_layers = (Int_t) par[0];
- if (n_layers < 2)
- return EResSaclay(x, &par[1]);
- else {
- Int_t par_ind = 1;
- Double_t e = x[0];
- for (Int_t layer = 1; layer <= n_layers; layer++) {
-
- e = EResSaclay(&e, &par[par_ind]); //residual energy after layer
- if (e < KVDETECTOR_MINIMUM_E)
- return 0.; // return 0 if particle stops in one of layers in detector
- par_ind += 19;
-
- }
- return e;
- }
- return 0.;
-}
-
-//______________________________________________________________________________________________//
-
-void KVDetector::SetELossParams(Int_t Z, Int_t A)
-{
- //Initialise energy loss coefficients for this detector and a given incident nucleus (Z,A)
-
- //do we need to set up the ELoss function ?
- //only if it has never been done or if the index of the active layer has changed...
- if( !npar_loss || (npar_loss != 1 + ((Int_t) fActiveLayer + 1) * 19) ){
- //number of params for eloss function = 1 (index of active layer) + 19 params for each layer up to & including active layer
- npar_loss = 1 + ((Int_t) fActiveLayer + 1) * 19;
- if( par_loss ) delete [] par_loss; //delete previous parameter array
- par_loss = new Double_t[npar_loss];
- par_loss[0] = (Int_t) fActiveLayer + 1;
- //find/create function
- TString name_eloss; name_eloss.Form("ELoss_nact%d", ((Int_t) fActiveLayer + 1));
- //search in list of functions for one corresponding to this detector
- //the name of the required function is ELoss_nactx with x = number of active layer (1, 2, etc.)
- ELoss =
- (TF1 *) gROOT->GetListOfFunctions()->FindObject(name_eloss.Data());
- if (!ELoss)
- ELoss = new TF1(name_eloss.Data(), ELossActive, 0.1, 5000., npar_loss);
- }
-
- //loop over layers to fill parameter arrays
- TIter next_abs(fAbsorbers); int i=0; KVMaterial*abs;
- while( (abs = (KVMaterial*)next_abs()) ){
- if (i <= (int) fActiveLayer)
- abs->GetELossParams(Z, A, (par_loss + 1 + 19 * i));
- else break;
- i++;
- }
-
- //set parameters of energy loss function
- ELoss->SetParameters(par_loss);
-}
-
-//______________________________________________________________________________________________//
-
-void KVDetector::SetEResParams(Int_t Z, Int_t A)
-{
- //Initialise coefficients of residual energy function for this detector and a given incident nucleus (Z,A)
-
- //do we need to set up the ERes function ?
- //only if it has never been done or if the number of layers has changed...
- if( !npar_res || (npar_res != 1 + fAbsorbers->GetSize() * 19) ){
- //number of params for eres function = 1 (number of layers) + 19 params for each layer in detector
- npar_res = 1 + fAbsorbers->GetSize() * 19;
- if( par_res ) delete [] par_res; //delete previous parameter array
- par_res = new Double_t[npar_res];
- par_res[0] = fAbsorbers->GetSize();
- //find/create function
- TString name_eres; name_eres.Form("ERes_nlay%d", fAbsorbers->GetSize());
- //search in list of functions for one corresponding to this material
- //the name of the required function is ERes_nlayx with x= number of absorbers in detector
- ERes =
- (TF1 *) gROOT->GetListOfFunctions()->FindObject(name_eres.Data());
- if (!ERes)
- ERes =
- new TF1(name_eres.Data(), EResDet, 0.1, 5000., npar_res);
- }
-
- //loop over layers to fill parameter arrays
- TIter next_abs(fAbsorbers); int i=0; KVMaterial*abs;
- while( (abs = (KVMaterial*)next_abs()) ){
- abs->GetELossParams(Z, A, (par_res + 1 + 19 * i));
- i++;
- }
-
- //set parameters of residual energy function
- ERes->SetParameters(par_res);
+Double_t KVDetector::EResDet(Double_t * x, Double_t * par)
+{
+ // Calculates residual energy (in MeV) of particle after traversing all layers of detector.
+ // Returned value is -1000 if particle stops in one of the layers of the detector.
+ //
+ // Arguments are:
+ // x[0] is incident energy in MeV
+ // Parameters are:
+ // par[0] Z of ion
+ // par[1] A of ion
+
+ Double_t e = x[0];
+ TIter next(fAbsorbers); KVMaterial* mat;
+ while( (mat = (KVMaterial*)next()) ){
+ Double_t eres = mat->GetERes(par[0], par[1], e); //residual energy after layer
+ if (eres <= 0.)
+ return -1000.; // return -1000 if particle stops in layers before active layer
+ e = eres;
+ }
+ return e;
}
//____________________________________________________________________________________
@@ -1146,7 +1093,7 @@
while( (abs = (KVMaterial*)next()) ){
// get medium for absorber
med = abs->GetGeoMedium();
- Double_t thick = abs->GetThicknessInCM();
+ Double_t thick = abs->GetThickness();
GetVerticesInOwnFrame(coords, fDepthInTelescope+depth_in_det, thick);
for(register int i=0;i<8;i++){
vertices[2*i] = coords[i].X();
@@ -1299,4 +1246,210 @@
return surf;
}
+
+TF1* KVDetector::GetEResFunction(Int_t Z, Int_t A)
+{
+ // Return pointer toTF1 giving residual energy after detector as function of incident energy,
+ // for a given nucleus (Z,A).
+ // The TF1::fNpx parameter is taken from environment variable KVDetector.ResidualEnergy.Npx
+
+ if(!fEResF){
+ fEResF = new TF1(Form("KVDetector:%s:ERes", GetName()), this, &KVDetector::EResDet,
+ 0., 1.e+04, 2, "KVDetector", "EResDet");
+ fEResF->SetNpx( gEnv->GetValue("KVDetector.ResidualEnergy.Npx", 20) );
+ }
+ fEResF->SetParameters((Double_t)Z, (Double_t)A);
+ fEResF->SetRange(0., GetSmallestEmaxValid(Z,A));
+
+ return fEResF;
+}
+
+TF1* KVDetector::GetELossFunction(Int_t Z, Int_t A)
+{
+ // Return pointer to TF1 giving energy loss in active layer of detector as function of incident energy,
+ // for a given nucleus (Z,A).
+ // The TF1::fNpx parameter is taken from environment variable KVDetector.EnergyLoss.Npx
+
+ if(!fELossF){
+ fELossF = new TF1(Form("KVDetector:%s:ELossActive", GetName()), this, &KVDetector::ELossActive,
+ 0., 1.e+04, 2, "KVDetector", "ELossActive");
+ fELossF->SetNpx( gEnv->GetValue("KVDetector.EnergyLoss.Npx", 20));
+ }
+ fELossF->SetParameters((Double_t)Z, (Double_t)A);
+ fELossF->SetRange(0., GetSmallestEmaxValid(Z,A));
+ return fELossF;
+}
+
+Double_t KVDetector::GetEIncOfMaxDeltaE(Int_t Z, Int_t A)
+{
+ // Overrides KVMaterial::GetEIncOfMaxDeltaE
+ // Returns incident energy corresponding to maximum energy loss in the
+ // active layer of the detector, for a given nucleus.
+
+ return GetELossFunction(Z,A)->GetMaximumX();
+}
+
+Double_t KVDetector::GetDeltaE(Int_t Z, Int_t A, Double_t Einc)
+{
+ // Overrides KVMaterial::GetDeltaE
+ // Returns energy loss of given nucleus in the active layer of the detector.
+
+ return GetELossFunction(Z,A)->Eval(Einc);
+}
+
+Double_t KVDetector::GetTotalDeltaE(Int_t Z, Int_t A, Double_t Einc)
+{
+ // Returns calculated total energy loss of ion in ALL layers of the detector.
+ // This is just (Einc - GetERes(Z,A,Einc))
+
+ return Einc-GetERes(Z,A,Einc);
+}
+
+Double_t KVDetector::GetERes(Int_t Z, Int_t A, Double_t Einc)
+{
+ // Overrides KVMaterial::GetERes
+ // Returns residual energy of given nucleus after the detector.
+
+ Double_t eres = GetEResFunction(Z,A)->Eval(Einc);
+ // Eres function returns -1000 when particle stops in detector,
+ // in order for function inversion (GetEIncFromEres) to work
+ if(eres<0.) eres = 0.;
+ return eres;
+}
+
+Double_t KVDetector::GetIncidentEnergy(Int_t Z, Int_t A, Double_t delta_e, enum KVIonRangeTable::SolType type)
+{
+ // Overrides KVMaterial::GetIncidentEnergy
+ // Returns incident energy corresponding to energy loss delta_e in active layer of detector for a given nucleus.
+ // If delta_e is not given, the current energy loss in the active layer is used.
+ //
+ // By default the solution corresponding to the highest incident energy is returned
+ // This is the solution found for Einc greater than the maximum of the dE(Einc) curve.
+ // If you want the low energy solution set SolType = KVIonRangeTable::kEmin.
+ //
+ // WARNING: calculating the incident energy of a particle using only the dE in a detector
+ // is ambiguous, as in general (and especially for very heavy ions) the maximum of the dE
+ // curve occurs for Einc greater than the punch-through energy, therefore it is not always
+ // true to assume that if the particle does not stop in the detector the required solution
+ // is that for type=KVIonRangeTable::kEmax. For a range of energies between punch-through
+ // and dE_max, the required solution is still that for type=KVIonRangeTable::kEmin.
+ // If the residual energy of the particle is unknown, there is no way to know which is the
+ // correct solution.
+ //
+ // If the given energy loss in the active layer is greater than the maximum theoretical dE
+ //(dE > GetMaxDeltaE(Z,A)) then we return the incident energy corresponding to the maximum,
+ // GetEIncOfMaxDeltaE(Z,A)
+
+ if(Z<1) return 0.;
+
+ Double_t DE = (delta_e > 0 ? delta_e : GetEnergyLoss());
+
+ TF1* dE = GetELossFunction(Z, A);
+ Double_t e1,e2;
+ dE->GetRange(e1,e2);
+ switch(type){
+ case KVIonRangeTable::kEmin:
+ e2=GetEIncOfMaxDeltaE(Z,A);
+ break;
+ case KVIonRangeTable::kEmax:
+ e1=GetEIncOfMaxDeltaE(Z,A);
+ break;
+ }
+ return dE->GetX(DE,e1,e2);
+}
+
+Double_t KVDetector::GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres)
+{
+ // Overrides KVMaterial::GetDeltaEFromERes
+ //
+ // Calculate energy loss in active layer of detector for nucleus (Z,A)
+ // having a residual kinetic energy Eres (MeV)
+
+ if(Z<1 || Eres<KVDETECTOR_MINIMUM_E) return 0.;
+ Double_t Einc = GetIncidentEnergyFromERes(Z,A,Eres);
+ if(Einc < KVDETECTOR_MINIMUM_E) return 0.;
+ return GetELossFunction(Z,A)->Eval(Einc);
+}
+
+Double_t KVDetector::GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres)
+{
+ // Overrides KVMaterial::GetIncidentEnergyFromERes
+ //
+ // Calculate incident energy of nucleus from residual energy
+
+ if(Z<1 || Eres<KVDETECTOR_MINIMUM_E) return 0.;
+ return GetEResFunction(Z,A)->GetX(Eres);
+}
+
+Double_t KVDetector::GetSmallestEmaxValid(Int_t Z, Int_t A)
+{
+ // Returns the smallest maximum energy for which range tables are valid
+ // for all absorbers in the detector, and given ion (Z,A)
+
+ Double_t maxmin=-1.;
+ TIter next(fAbsorbers);
+ KVMaterial *abs;
+ while( (abs = (KVMaterial*)next()) ){
+ if(maxmin<0.) maxmin = abs->GetEmaxValid(Z,A);
+ else {
+ if(abs->GetEmaxValid(Z,A) < maxmin) maxmin = abs->GetEmaxValid(Z,A);
+ }
+ }
+ return maxmin;
+}
+
+void KVDetector::ReadDefinitionFromFile(const Char_t* envrc)
+{
+ // Create detector from text file in 'TEnv' format.
+ //
+ // Example:
+ // ========
+ //
+ // Layer: Gold
+ // Gold.Material: Au
+ // Gold.AreaDensity: 200.*KVUnits::ug
+ // +Layer: Gas1
+ // Gas1.Material: C3F8
+ // Gas1.Thickness: 5.*KVUnits::cm
+ // Gas1.Pressure: 50.*KVUnits::mbar
+ // Gas1.Active: yes
+ // +Layer: Si1
+ // Si1.Material: Si
+ // Si1.Thickness: 300.*KVUnits::um
+
+ TEnv fEnvFile(envrc);
+
+ KVString layers(fEnvFile.GetValue("Layer", ""));
+ layers.Begin(" ");
+ while( !layers.End() ){
+ KVString layer = layers.Next();
+ KVString mat = fEnvFile.GetValue(Form("%s.Material",layer.Data()),"");
+ KVString tS = fEnvFile.GetValue(Form("%s.Thickness",layer.Data()),"");
+ KVString pS = fEnvFile.GetValue(Form("%s.Pressure",layer.Data()),"");
+ KVString dS = fEnvFile.GetValue(Form("%s.AreaDensity",layer.Data()),"");
+ Double_t thick, dens, press;
+ thick=dens=press=0.;KVMaterial* M = 0;
+ if(pS != "" && tS != ""){
+ press = (Double_t)gROOT->ProcessLineFast( Form("%s*1.e+12", pS.Data()) );
+ press/=1.e+12;
+ thick = (Double_t)gROOT->ProcessLineFast( Form("%s*1.e+12", tS.Data()) );
+ thick/=1.e+12;
+ M = new KVMaterial(mat.Data(), thick, press);
+ }
+ else if(tS != ""){
+ thick = (Double_t)gROOT->ProcessLineFast( Form("%s*1.e+12", tS.Data()) );
+ thick/=1.e+12;
+ M = new KVMaterial(mat.Data(), thick);
+ }
+ else if(dS != ""){
+ dens = (Double_t)gROOT->ProcessLineFast( Form("%s*1.e+12", dS.Data()) );
+ dens/=1.e+12;
+ M = new KVMaterial(dens, mat.Data());
+ }
+ if(M){
+ AddAbsorber(M);
+ if(fEnvFile.GetValue(Form("%s.Active",layer.Data()),kFALSE)) SetActiveLayer(M);
+ }
+ }
+}
=== modified file 'KVMultiDet/detectors/KVDetector.h'
--- KVMultiDet/detectors/KVDetector.h 2010-12-03 09:16:52 +0000
+++ KVMultiDet/detectors/KVDetector.h 2011-03-14 15:58:00 +0000
@@ -27,12 +27,6 @@
#define KVD_NORECPRC_CNXN 0
#endif
-
-#define KVDETECTOR_UNKNOWN_MATERIAL "Constructor called with unknown material"
-#define KVDETECTOR_UNKNOWN_DETECTOR "Constructor called with unknown detector prototype"
-#define KVDETECTOR_NOT_IN_TELESCOPE "Detector not associated to any telescope: position undefined"
-#define KVDETECTOR_ADD_TO_UNKNOWN_TELESCOPE "Pointer to telescope is null."
-
//for energies less than this (MeV) particles are considered to be stopped
#define KVDETECTOR_MINIMUM_E 0.001
@@ -51,9 +45,6 @@
class TGeoVolume;
class TTree;
-Double_t ELossActive(Double_t * x, Double_t * par);
-Double_t EResDet(Double_t * x, Double_t * par);
-
class KVDetector:public KVMaterial {
friend class KVDetectorBrowser;
@@ -78,10 +69,6 @@
Int_t fUnidentP; //! temporary counters, determine state of identified/unidentified particle flags
protected:
-Int_t npar_loss;//!number of params for eloss function
-Int_t npar_res;//!number of params for eres function
-Double_t *par_loss;//!array of params for eloss function
-Double_t *par_res;//!array of params for eres function
TString fFName; //!dynamically generated full name of detector
KVList *fModules; //references to connected electronic modules (not implemented yet)
@@ -98,6 +85,14 @@
Binary8_t fFiredMask;//bitmask used by Fired to determine which parameters to take into account
+ Double_t ELossActive(Double_t * x, Double_t * par);
+ Double_t EResDet(Double_t * x, Double_t * par);
+
+ TF1* fELossF; //! parametric function dE in active layer vs. incident energy
+ TF1* fEResF; //! parametric function Eres residual energy after all layers of detector
+
+ Double_t fEResforEinc;//! used by GetIncidentEnergy & GetCorrectedEnergy
+
public:
KVDetector();
KVDetector(const Char_t * type, const Float_t thick = 0.0);
@@ -129,14 +124,12 @@
Double_t GetTotalThicknessInCM()
{
- // Calculate and return the total thickness of ALL absorbers making up the detector,
- // not just the active layer (as for GetThickness()).
- //
- // As different materials can have different default units for thickness, we convert
- // everything into centimetres and return the total thickness with these units.
+ // Calculate and return the total thickness in centimetres of ALL absorbers making up the detector,
+ // not just the active layer (value returned by GetThickness()).
+
fTotThickness=0;
TIter next(fAbsorbers); KVMaterial* mat;
- while( (mat = (KVMaterial*)next()) ) fTotThickness += mat->GetThicknessInCM();
+ while( (mat = (KVMaterial*)next()) ) fTotThickness += mat->GetThickness();
return fTotThickness;
};
@@ -171,7 +164,7 @@
};
virtual Double_t GetCorrectedEnergy(UInt_t z, UInt_t a, Double_t e =
-1., Bool_t transmission=kTRUE);
- virtual UInt_t FindZmin(Double_t ELOSS = -1., Char_t mass_formula = -1);
+ virtual Int_t FindZmin(Double_t ELOSS = -1., Char_t mass_formula = -1);
void AddACQParam(KVACQParam*);
virtual KVACQParam *GetACQParam(const Char_t*/*name*/);
@@ -264,9 +257,6 @@
return TestBit(kIsBeingDeleted);
};
- virtual void SetEResParams(Int_t Z, Int_t A);
- virtual void SetELossParams(Int_t Z, Int_t A);
-
static KVDetector *MakeDetector(const Char_t * name, Float_t thick);
const TVector3& GetNormal();
@@ -287,6 +277,31 @@
// detector implementations: this version just returns -1.
return -1;
};
+ virtual Double_t GetEIncOfMaxDeltaE(Int_t Z, Int_t A);
+ virtual Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc);
+ virtual Double_t GetTotalDeltaE(Int_t Z, Int_t A, Double_t Einc);
+ virtual Double_t GetERes(Int_t Z, Int_t A, Double_t Einc);
+ virtual Double_t GetIncidentEnergy(Int_t Z, Int_t A, Double_t delta_e =
+ -1.0, enum KVIonRangeTable::SolType type = KVIonRangeTable::kEmax);
+ /*virtual Double_t GetEResFromDeltaE(...) - DON'T IMPLEMENT, CALLS GETINCIDENTENERGY*/
+ virtual Double_t GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres);
+ virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres);
+
+ virtual TF1* GetEResFunction(Int_t Z, Int_t A);
+ virtual TF1* GetELossFunction(Int_t Z, Int_t A);
+
+ virtual Double_t GetSmallestEmaxValid(Int_t Z, Int_t A);
+
+ virtual void SetEResAfterDetector(Double_t e)
+ {
+ fEResforEinc=e;
+ };
+ virtual Double_t GetEResAfterDetector() const
+ {
+ return fEResforEinc;
+ };
+
+ virtual void ReadDefinitionFromFile(const Char_t*);
ClassDef(KVDetector, 8) //Base class for the description of detectors in multidetector arrays
};
=== modified file 'KVMultiDet/detectors/KVMaterial.cpp'
--- KVMultiDet/detectors/KVMaterial.cpp 2009-11-26 16:48:10 +0000
+++ KVMultiDet/detectors/KVMaterial.cpp 2011-03-14 15:58:00 +0000
@@ -1,5 +1,4 @@
/***************************************************************************
-$Id: KVMaterial.cpp,v 1.55 2009/04/01 09:28:02 franklan Exp $
kvmaterial.cpp - description
-------------------
begin : Thu May 16 2002
@@ -33,65 +32,31 @@
///////////////////////////////////////////////////////////////////////////////
// KVMaterial
//
-//The KVMaterial class encapsulates the routines of R. Dayras et al for calculating
-//the energy lost by charged particles (nuclei) in different absorbers,
-//formerly known as the "vedaloss" routines.
-//
-//To create an absorber, use the ctor specifying a type of material and optionally
-//the thickness of the absorber.
-// KVMaterial mat1("Si",150.0); //150 microns of silicon
-// KVMaterial mat2("Au",0.8); //800 micrograms/cm**2 of gold
-//The available materials are defined in the $KVROOT/KVFiles/kvloss.data file. In order to get
-//a list of the currently defined materials, use KVMaterial::GetListOfMaterials().
-//
-//Depending on the type of material, the default units of "thickness" are different:
-// fType = Si, Myl - thickness in micrometres
-// fType = NE102, CsI - thickness in centimetres
-// fType = C3F8, CF4 - pressure in mbar
-// fType = Au, Sn, U, Nb, Ni, C, Ta - thickness in mg/cm2
-//
-//By default, the naturally-occuring atomic mass is used for the elements. To use
-//some rarer isotope, use the SetMass() method with the appropriate mass (not
-//valid for compounds).
-//
+// Description of materials used for detectors and targets.
///////////////////////////////////////////////////////////////////////////////
-TString KVMaterial::kDataFilePath = "";
-Char_t KVMaterial::kUnits[][10] = {
- "mbar",
- "microns",
- "mg/cm2",
- "cm",
- "Torr"
-};
+KVIonRangeTable* KVMaterial::fIonRangeTable = 0x0;
//___________________________________________________________________________________
void KVMaterial::init()
{
- //Default initialisations.
- //No properties are set for the material.
- fAmasr = 0.;
- fAmat = 0.;
- fDens = 0.;
- fGasThick = 0.;
- fMoleWt = 0.;
- fTemp = 19.;
- fUnits = 10;
- fZmat = 0.;
- if (kDataFilePath == "") {
- //get full path to range tables file from env vars (i.e. .kvrootrc)
- kDataFilePath = gEnv->GetValue("KVMaterial.RangeTables", "");
- gSystem->ExpandPathName( kDataFilePath );
- }
- for (int i = 0; i < 100; i++) {
- fEmin[i] = 0.0;
- fEmax[i] = 500.0;
- }
+ // Default initialisations.
+ // No properties are set for the material (except standard temperature (19°C) and pressure (1 atm))
+ // Default range table is generated if not already done.
+ // By default it is the VEDALOSS table implemented in KVedaLoss.
+ // You can change this by changing the value of environment variable KVMaterial.IonRangeTable.
+
fELoss = 0;
SetName("");
SetTitle("");
- ELoss = ERes = 0;
fNormToMat.SetXYZ(0,0,1);
+ fAmasr = 0;
+ fPressure = 1. * KVUnits::atm;
+ fTemp = 19.0;
+ // create default range table singleton if not already done
+ if(!fIonRangeTable) {
+ fIonRangeTable = KVIonRangeTable::GetRangeTable( gEnv->GetValue("KVMaterial.IonRangeTable", "VEDALOSS") );
+ }
}
//
@@ -102,11 +67,37 @@
}
//__________________________________________________________________________________
-KVMaterial::KVMaterial(const Char_t * type, const Float_t thick)
-{
- //Initialise absorber with given type of material and thickness (default = 0.0)
- init();
- SetMaterial(type);
+KVMaterial::KVMaterial(const Char_t * type, const Double_t thick)
+{
+ // Create material with given type and linear thickness in cm.
+
+ init();
+ SetMaterial(type);
+ SetThickness(thick);
+}
+
+KVMaterial::KVMaterial(Double_t area_density, const Char_t * type)
+{
+ // Create material with given area density in g/cm**2 and given type
+
+ init();
+ SetMaterial(type);
+ SetAreaDensity(area_density);
+}
+
+KVMaterial::KVMaterial(const Char_t * gas, const Double_t thick, const Double_t pressure, const Double_t temperature)
+{
+ // Create gaseous material with given type, linear thickness in cm, pressure in Torr,
+ // and temperature in degrees C (default value 19°C).
+ //
+ // Examples
+ // 15 cm of CF4 gas at 1 atm and 19°C : KVMaterial("CF4", 15., 1.*KVUnits::atm)
+ // 50 mm of C3F8 at 30 mbar and 25°C : KVMaterial("C3F8", 50.*KVUnits::mm, 30.*KVUnits::mbar, 25.)
+
+ init();
+ SetMaterial(gas);
+ fPressure = pressure;
+ fTemp = temperature;
SetThickness(thick);
}
@@ -123,77 +114,14 @@
}
//___________________________________________________________________________________
-KVList *KVMaterial::GetListOfMaterials()
-{
- //Creates and fills a list with all the materials currently described in the
- //$KVROOT/KVFiles/kvloss.data parameters file.
- //To avoid memory leakage, delete the list after use !!
-
- KVList *tmp = new KVList();
-
- Char_t name[25], gtype[25];
- Float_t Amat = 0.;
- Float_t Dens = 0.;
- Float_t GasThick = 0.;
- Float_t MoleWt = 0.;
- Float_t Temp = 19.;
- UInt_t Units = 10;
- Float_t Zmat = 0.;
-
- if (kDataFilePath == "") {
- //get full path to range tables file from env vars (i.e. .kvrootrc)
- kDataFilePath = gEnv->GetValue("KVMaterial.RangeTables", "");
- gSystem->ExpandPathName( kDataFilePath );
- }
-
- FILE *fp;
- if (!(fp = fopen(kDataFilePath.Data(), "r"))) {
- printf("KVMaterial::GetMaterialsList : ");
- printf(KVMATERIAL_INIT_FILE_NOT_FOUND, kDataFilePath.Data());
- return 0;
- } else {
- char line[132];
- while (fgets(line, 132, fp)) { // read lines from file
-
- switch (line[0]) {
-
- case '/': // ignore comment lines
- break;
-
- case '+': // header lines
-
- if (sscanf(line, "+ %s %s %u %f %f %f %f %f %f",
- gtype, name, &Units, &Dens, &Zmat, &Amat,
- &GasThick, &MoleWt, &Temp)
- != 9) {
- cout << "KVMaterial::GetMaterialsList> : ";
- printf(KVMATERIAL_INIT_FILE_HEADER_PROBLEM, kDataFilePath.Data());
- cout << endl;
- fclose(fp);
- return 0;
- }
-//found a new material
- KVMaterial *tmp_mat = new KVMaterial(gtype);
- tmp->Add(tmp_mat);
- break;
- }
- }
- fclose(fp);
- }
- return tmp;
-}
-
-//___________________________________________________________________________________
void KVMaterial::SetMaterial(const Char_t * mat_type)
{
- //Intialise material of a given type.
- //The known types are defined by the contents of file $KVROOT/kvloss.data.
- //For materials which are elements of the periodic table you can specify
- //the isotope such as "64Ni", "13C", "natSn", etc. etc.
+ // Intialise material of a given type.
+ // The material must exist in the currently used range tables (fIonRangeTable).
+ // For materials which are elements of the periodic table you can specify
+ // the isotope such as "64Ni", "13C", "natSn", etc. etc.
- Char_t name[25], gtype[25];
init();
- FILE *fp;
//are we dealing with an isotope ?
Char_t type[10];
Int_t iso_mass = 0;
@@ -202,116 +130,29 @@
strcpy(type, mat_type);
}
}
-
- if (!(fp = fopen(kDataFilePath.Data(), "r"))) {
- Error("SetMaterial", KVMATERIAL_INIT_FILE_NOT_FOUND,
- kDataFilePath.Data());
- } else {
- char line[132];
- while (fgets(line, 132, fp)) { // read lines from file
-
- switch (line[0]) {
-
- case '/': // ignore comment lines
- break;
-
- case '+': // header lines
-
- if (sscanf(line, "+ %s %s %u %lf %lf %lf %lf %lf %lf",
- gtype, name, &fUnits, &fDens, &fZmat, &fAmat,
- &fGasThick, &fMoleWt, &fTemp)
- != 9) {
- Error("SetMaterial", KVMATERIAL_INIT_FILE_HEADER_PROBLEM,
- kDataFilePath.Data());
- goto bad_exit;
- }
- SetName(name);
- SetType(gtype);
- if (!strcmp(GetType(), type)) { // is this what you're looking for ?
- //look for energy limits to calculation validity
- if (!fgets(line, 132, fp)) {
- Warning("SetMaterial", KVMATERIAL_INIT_FILE_DATA_PROBLEM,
- kDataFilePath.Data());
- goto bad_exit;
- } else {
- while (line[0] == 'Z') {
- Int_t z1, z2;
- Float_t e1, e2;
- sscanf(line, "Z = %d,%d %f < E/A < %f MeV", &z1,
- &z2, &e1, &e2);
- for (int i = z1; i <= z2; i++) {
- fEmin[i - 1] = e1;
- fEmax[i - 1] = e2;
- }
- fgets(line, 132, fp);
- }
- }
-
- for (register int count = 0; count < 100; count++) {
-
- if (sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf",
- &fCoeff[count][0], &fCoeff[count][1],
- &fCoeff[count][2], &fCoeff[count][3],
- &fCoeff[count][4], &fCoeff[count][5],
- &fCoeff[count][6], &fCoeff[count][7])
- != 8) {
- Error("SetMaterial",
- KVMATERIAL_INIT_FILE_COEFF_PROBLEM, kDataFilePath.Data(),
- type);
- goto bad_exit;
- }
- if (!fgets(line, 132, fp)) {
- Warning("SetMaterial",
- KVMATERIAL_INIT_FILE_DATA_PROBLEM,
- kDataFilePath.Data());
- goto bad_exit;
- } else {
- if (sscanf(line, "%lf %lf %lf %lf %lf %lf",
- &fCoeff[count][8], &fCoeff[count][9],
- &fCoeff[count][10], &fCoeff[count][11],
- &fCoeff[count][12], &fCoeff[count][13])
- != 6) {
- Error("SetMaterial",
- KVMATERIAL_INIT_FILE_COEFF_PROBLEM,
- kDataFilePath.Data(), type);
- goto bad_exit;
- }
- }
- fgets(line, 132, fp);
- }
- goto normal_exit; // i apologise for the use of "g**o"
- }
- break;
- }
- }
-// only come here if nothing has been found
- Warning("SetMaterial", KVMATERIAL_TYPE_NOT_FOUND, type, kDataFilePath.Data());
- init(); //no properties are set
- return;
- bad_exit:
- Fatal("SetMaterial", "Programme execution impossible");
- normal_exit:
- fclose(fp);
- //set isotope in case call was made with "64Ni" or "48Ca" etc.
- if (iso_mass)
- SetMass(iso_mass);
- }
+ if(iso_mass) SetMass( iso_mass );
+ SetType(type);
+ if(!fIonRangeTable->IsMaterialKnown(type))
+ Warning("SetMaterial",
+ "Called for material %s which is unknown in current range table %s. Energy loss & range calculations impossible.",
+ type, fIonRangeTable->GetName());
+ else {
+ SetType( fIonRangeTable->GetMaterialName(type) );
+ SetName(mat_type);
+ }
}
//___________________________________________________________________________________
KVMaterial::~KVMaterial()
{
//Destructor
- //The TF1 objects "ELoss" and "ERes" are not to be deleted as they can be
- //used by other KVMaterial objects (they are retrieved from gROOT->GetListOfFunctions())
- //and cannot cause a memory leak as they are only ever created if not found in
- //the gROOT list of functions.
}
-void KVMaterial::SetMass(Float_t a)
+void KVMaterial::SetMass(Double_t a)
{
-//Set the atomic mass of the material - use if you want to change the default naturally
-//occuring mass for some rarer isotope.
+ //Set the atomic mass of the material - use if you want to change the default naturally
+ //occuring mass for some rarer isotope.
+
if (GetActiveLayer()) {
GetActiveLayer()->SetMass(a);
return;
@@ -323,9 +164,10 @@
Double_t KVMaterial::GetMass() const
{
//Returns atomic mass of material. Will be isotopic mass if set.
+
if (GetActiveLayer())
return GetActiveLayer()->GetMass();
- return (fAmasr ? fAmasr : fAmat);
+ return (fAmasr ? fAmasr : fIonRangeTable->GetAtomicMass(GetType()));
}
//___________________________________________________________________________________
@@ -353,81 +195,154 @@
}
//___________________________________________________________________________________
+
+Bool_t KVMaterial::IsGas() const
+{
+ // Returns kTRUE for gaseous materials/detectors.
+
+ if (GetActiveLayer())
+ return GetActiveLayer()->IsGas();
+ return fIonRangeTable->IsMaterialGas(GetType());
+}
+
+//___________________________________________________________________________________
+
Double_t KVMaterial::GetZ() const
{
//Returns atomic number of material.
if (GetActiveLayer())
return GetActiveLayer()->GetZ();
- return fZmat;
+ return fIonRangeTable->GetZ(GetType());
}
//___________________________________________________________________________________
+
Double_t KVMaterial::GetDensity() const
{
- //Returns density of material.
- //For solids, the units are g/cm**3.
- //For a gas, density is calculated from molecular weight, pressure
- //and temperature according to ideal gas law
+ // Returns density of material in g/cm**3.
+ // For a gas, density is calculated from current pressure & temperature according to ideal gas law
if (GetActiveLayer())
return GetActiveLayer()->GetDensity();
- if (fUnits == kTORR)
- return (fMoleWt * fThick) / ((fTemp + ZERO_KELVIN) * RTT);
- if (fUnits == kMBAR)
- return (fMoleWt * fThick * 0.75) / ((fTemp + ZERO_KELVIN) * RTT);
- return fDens;
-}
-
-void KVMaterial::SetPressure(Float_t t)
-{
- //Set the pressure of a gas.
- //If the material is not a gas, this has no effect.
- //The units depend on fUnits
-
- if (GetActiveLayer()) {
- GetActiveLayer()->SetPressure(t);
- return;
- }
-
- if (fUnits == kMBAR || fUnits == kTORR)
- fThick = t;
-}
-
-
-//___________________________________________________________________________________
-
-Float_t KVMaterial::GetPressure() const
-{
- //Returns the pressure of a gas.
- //If the material is not a gas, value is zero.
- //The units depend on fUnits
-
+ fIonRangeTable->SetTemperatureAndPressure(GetType(), fTemp, fPressure);
+ return fIonRangeTable->GetDensity(GetType());
+}
+
+//___________________________________________________________________________________
+
+void KVMaterial::SetThickness(Double_t t)
+{
+ // Set the linear thickness of the material in cm or use one of the
+ // Units constants:
+ // SetThickness( 30.*KVUnits::um ); set thickness to 30 microns
+
+ if (GetActiveLayer()) {
+ GetActiveLayer()->SetThickness(t);
+ return;
+ }
+ // recalculate area density
+ fThick = t * GetDensity();
+}
+
+//___________________________________________________________________________________
+
+Double_t KVMaterial::GetThickness() const
+{
+ // Returns the linear thickness of the material in cm.
+ // Use Units to change units:
+ // mat.GetThickness()/KVUnits::um ; in microns
+
+ if (GetActiveLayer())
+ return GetActiveLayer()->GetThickness();
+ return fThick/GetDensity();
+}
+
+//___________________________________________________________________________________
+
+void KVMaterial::SetAreaDensity(Double_t dens /* g/cm**2 */)
+{
+ // Set area density in g/cm**2.
+ //
+ // For solids, area density can only changed by changing linear dimension
+ // (fixed density).
+ // For gases, the density depends on temperature and pressure. This method
+ // leaves temperature and pressure unchanged, therefore for gases also this
+ // method will effectively modify the linear dimension of the gas cell.
+
+ if(GetActiveLayer())
+ GetActiveLayer()->SetAreaDensity(dens);
+ fThick = dens;
+}
+
+//___________________________________________________________________________________
+
+Double_t KVMaterial::GetAreaDensity() const
+{
+ // Return area density of material in g/cm**2
+
+ if(GetActiveLayer()) return GetActiveLayer()->GetAreaDensity();
+ return fThick;
+}
+
+//___________________________________________________________________________________
+
+void KVMaterial::SetPressure(Double_t p)
+{
+ // Set the pressure of a gaseous material (in torr)
+ // As this changes the density of the gas, it also changes
+ // the area density of the absorber (for fixed linear dimension)
+
+ if(!IsGas()) return;
+ if (GetActiveLayer()) {
+ GetActiveLayer()->SetPressure(p);
+ return;
+ }
+ // get current linear dimension of absorber
+ Double_t e = GetThickness();
+ fPressure = p;
+ // change area density to keep linear dimension constant
+ SetThickness(e);
+}
+
+
+//___________________________________________________________________________________
+
+Double_t KVMaterial::GetPressure() const
+{
+ // Returns the pressure of a gas (in torr).
+ // If the material is not a gas, value is zero.
+
+ if(!IsGas()) return 0.0;
if (GetActiveLayer())
return GetActiveLayer()->GetPressure();
- if (fUnits == kMBAR || fUnits == kTORR)
- return fThick;
- return 0.0;
+ return fPressure;
}
//___________________________________________________________________________________
-void KVMaterial::SetTemperature(Float_t t)
+void KVMaterial::SetTemperature(Double_t t)
{
- //Set temperature of material.
- //The units are: degrees celsius
+ // Set temperature of material.
+ // The units are: degrees celsius
+ // As this changes the density of the gas, it also changes
+ // the area density of the absorber (for fixed linear dimension)
+ if(!IsGas()) return;
if (GetActiveLayer()) {
GetActiveLayer()->SetTemperature(t);
return;
}
-
+ // get current linear dimension of absorber
+ Double_t e = GetThickness();
fTemp = t;
+ // change area density to keep linear dimension constant
+ SetThickness(e);
}
//___________________________________________________________________________________
-Float_t KVMaterial::GetTemperature() const
+Double_t KVMaterial::GetTemperature() const
{
//Returns temperature of material.
//The units are: degrees celsius
@@ -439,105 +354,11 @@
//___________________________________________________________________________________
-void KVMaterial::SetUnits(UInt_t u)
-{
- //Set units for 'thickness' of material.
- //WARNING: changing the default units will alter how the 'thickness'
- //is used in energy loss calculations!
- //WARNING2: we do not perform a conversion of any existing value
- //for the 'thickness' of the material, the existing value will be used
- //with the new units
-
- if (GetActiveLayer()) {
- GetActiveLayer()->SetUnits(u);
- return;
- }
-
- fUnits = u;
-}
-
-
-//___________________________________________________________________________________
-
-UInt_t KVMaterial::GetUnits() const
-{
- //Returns units for 'thickness' of material.
- //Can be one of KVMaterial::kMBAR, KVMaterial::kMGCM2, KVMaterial::kTORR,
- //KVMaterial::kMICRON, KVMaterial::kCM.
-
- if (GetActiveLayer())
- return GetActiveLayer()->GetUnits();
- return fUnits;
-}
-
-//___________________________________________________________________________________
-
-void KVMaterial::SetThickness(Float_t t)
-{
- //Set the thickness of the material.
- //
- //The meaning and units of "thickness" depend on the material.
- //For a gas it is the depth of the gas cell in millimetres.
- //For silicon and mylar it is the thickness in micrometres.
- //For CsI and plastic scintillators it is the length/thickness in centimetres.
- //For metallic elements (such as for targets) it is the areal density
- //in milligrams per cm^2.
-
- if (GetActiveLayer()) {
- GetActiveLayer()->SetThickness(t);
- return;
- }
-
- if (fUnits == kMBAR || fUnits == kTORR)
- fGasThick = t; //thickness of gas cell in cm
- else
- fThick = t;
-}
-
-//___________________________________________________________________________________
-
-Float_t KVMaterial::GetThickness() const
-{
- //Returns the "thickness" of the material - units depend on the material type
- //For a gas it is the depth of the gas cell in millimetres.
- //For silicon and mylar it is the thickness in micrometres.
- //For CsI and plastic scintillators it is the length/thickness in centimetres.
- //For metallic elements (such as for targets) it is the areal density
- //in milligrams per cm^2.
-
- if (GetActiveLayer())
- return GetActiveLayer()->GetThickness();
- if (fUnits == kMBAR || fUnits == kTORR)
- return fGasThick;
- return fThick;
-}
-
-//___________________________________________________________________________________
-
-Double_t KVMaterial::GetThicknessInCM() const
-{
- //Returns the thickness of the material in CENTIMETRES
-
- if (GetActiveLayer())
- return GetActiveLayer()->GetThicknessInCM();
- Double_t t = (Double_t)fGasThick;
- if (fUnits == kMBAR || fUnits == kTORR)
- return (t/10.);
- t = (Double_t)fThick;
- if(fUnits == kMICRONS)
- return (t/10000.);
- else if(fUnits == kMGCM2)
- return (t/fDens);
- return fThick;
-}
-
-//___________________________________________________________________________________
-
Double_t KVMaterial::GetEffectiveThickness(TVector3 & norm,
TVector3 & direction)
{
- //Calculate effective thickness of absorber as 'seen' in 'direction', taking into
- //account the arbitrary orientation of the 'norm' normal to the material's surface
+ // Calculate effective linear thickness of absorber (in cm) as 'seen' in 'direction', taking into
+ // account the arbitrary orientation of the 'norm' normal to the material's surface
TVector3 n = norm.Unit();
TVector3 d = direction.Unit();
@@ -547,248 +368,57 @@
}
//___________________________________________________________________________________
+
+Double_t KVMaterial::GetEffectiveAreaDensity(TVector3 & norm,
+ TVector3 & direction)
+{
+ // Calculate effective area density of absorber (in g/cm**2) as 'seen' in 'direction', taking into
+ // account the arbitrary orientation of the 'norm' normal to the material's surface
+
+ TVector3 n = norm.Unit();
+ TVector3 d = direction.Unit();
+ //absolute value of scalar product, in case direction is opposite to normal
+ Double_t prod = TMath::Abs(n * d);
+ return GetAreaDensity() / TMath::Max(prod, 1.e-03);
+}
+
+//___________________________________________________________________________________
void KVMaterial::Print(Option_t * option) const
{
//Show information on this material
cout << "KVMaterial: " << GetName() << " (" << GetType() << ")" << endl;
- if (fUnits == kMBAR || fUnits == kTORR)
- cout << " Thickness " << KVMaterial::
- GetThickness() << " mm, pressure " << GetPressure() << " " <<
- GetThicknessUnits() << endl;
- else
- cout << " Thickness " << KVMaterial::
- GetThickness() << " " << GetThicknessUnits() << endl;
+ if (fIonRangeTable->IsMaterialGas(GetType()))
+ cout << " Pressure " << GetPressure() << " torr" << endl;
+ cout << " Thickness " << KVMaterial::GetThickness() << " cm" << endl;
+ cout << " Area density " << KVMaterial::GetAreaDensity() << " g/cm**2" << endl;
cout << "-----------------------------------------------" << endl;
cout << " Z = " << GetZ() << " atomic mass = " << GetMass() << endl;
- cout << " Density = " << GetDensity() << endl;
- cout << " Validity of calculation:" << endl;
- cout << " Z = 1,2 -- " << GetEminVedaloss(1) << " AMeV < E < " <<
- GetEmaxVedaloss(1) << " AMeV" << endl;
- cout << " Z >= 3 -- " << GetEminVedaloss(3) << " AMeV < E < " <<
- GetEmaxVedaloss(3) << " AMeV" << endl;
+ cout << " Density = " << GetDensity() << " g/cm**3" << endl;
cout << "-----------------------------------------------" << endl;
}
-//_______________________________________________________________________________________
-Double_t ELossSaclay(Double_t * x, Double_t * par)
-{
- //Calculates energy loss (DE) as a function of incident energy x[0]
- //Parameters:
- // par[0] - par[14] : Saclay range tables parameters
- // par[0] = Z of nucleus
- // par[15] = A of nucleus
- // par[16] = minimum incident energy in MeV for valid calculation
- // par[17] = maximum incident energy in MeV for valid calculation
- // par[18] = ratio of isotopic to natural mass of material, log(fAmasr/fAmat)
-
- //energy loss = incident energy - residual energy
- return x[0] - EResSaclay(x, par);
-}
-
-//_______________________________________________________________________________________
-Double_t EResSaclay(Double_t * x, Double_t * par)
-{
- //Calculates residual energy after passage through material
- //as a function of incident energy x[0]
- //Parameters:
- // par[0] - par[14] : Saclay range tables parameters
- // par[0] = Z of nucleus
- // par[15] = A of nucleus
- // par[16] = minimum incident energy in MeV for valid calculation
- // par[17] = maximum incident energy in MeV for valid calculation
- // par[18] = ratio of isotopic to natural mass of material, log(fAmasr/fAmat)
-
- //check incident energy is valid
- //incident energy less than minimum valid energy - residual energy=0 (particle stops)
- //if (x[0] < par[16])
- // return 0.0;
- //incident energy greater than maximum valid energy - residual E = incident E
- //if (x[0] > par[17])
- // return x[0];
-
- // set up polynomial
- Double_t x1 = TMath::Log(0.1);
- Double_t x2 = TMath::Log(0.2);
- Double_t ran = 0.0;
- for (register int j = 2; j < 7; j++)
- ran += par[j + 1] * TMath::Power(x2, (Double_t) (j - 1));
- ran += par[2];
- Double_t y2 = ran;
- ran = 0.0;
- for (register int jj = 2; jj < 7; jj++)
- ran += par[jj + 1] * TMath::Power(x1, (Double_t) (jj - 1));
- ran += par[2];
- Double_t y1 = ran;
- Double_t adm = (y2 - y1) / (x2 - x1);
- Double_t adn = (y1 - adm * x1);
- Double_t arm = y1;
- // calculate energy loss
- Double_t eps = x[0] / par[15]; //energy in MeV/nucleon
- Double_t dleps = TMath::Log(eps);
- Double_t riso = TMath::Log(par[15] / par[1]) + par[18];
-
- if (eps < 0.1)
- ran = adm * dleps + adn;
- else {
- ran = 0.0;
- for (register int j = 2; j < 7; j++)
- ran += par[j + 1] * TMath::Power(dleps, (Double_t) (j - 1));
- ran += par[2];
- }
- ran += riso;
-
- Double_t range = TMath::Exp(ran);
- range -= par[14];
- if (range <= 0.005) { // particle stopped in material, gives up all energy
- return 0.0; //residual energy = 0
- }
-
- Double_t ranx = TMath::Log(range);
- Double_t ranx1 = ranx - riso;
- Double_t depsx;
- if (ranx1 < arm)
- depsx = (ranx1 - adn) / adm;
- else {
- depsx = 0.0;
- for (register int j = 2; j < 7; j++)
- depsx += par[j + 7] * TMath::Power(ranx1, (Double_t) (j - 1));
- depsx += par[8];
- }
-
- Double_t eps1 = depsx + TMath::Log(1 - PERC);
- Double_t eps2 = depsx + TMath::Log(1 + PERC);
- Double_t rap = TMath::Log((1 + PERC) / (1 - PERC));
-
- Double_t rn1 = 0.0;
- if (TMath::Exp(eps1) < 0.1)
- rn1 = adm * eps1 + adn;
- else {
- for (register int j = 1; j < 7; j++)
- rn1 += par[j + 1] * TMath::Power(eps1, (Double_t) (j - 1));
- }
- Double_t rn2 = 0.0;
- if (TMath::Exp(eps2) < 0.1)
- rn2 = adm * eps2 + adn;
- else {
- for (register int j = 1; j < 7; j++)
- rn2 += par[j + 1] * TMath::Power(eps2, (Double_t) (j - 1));
- }
-
- Double_t epres = eps1 + (rap / (rn2 - rn1)) * (ranx1 - rn1);
- epres = TMath::Exp(epres);
- Double_t eres = par[15] * epres;
- //make sure residual energy is <= incident energy
- //following original code, the minimum energy loss is 0.005 MeV
-
- Double_t eloss = x[0] - eres;
- if (eloss < 0.005 && eres > eloss)
- eres = x[0];
- return eres;
-}
-
-//_______________________________________________________________________________________//
-
-void KVMaterial::GetELossParams(Int_t Z, Int_t A, Double_t * par)
-{
- // get coefficients associated with this nucleus Z
- if(Z<1 || Z>ZMAX_VEDALOSS) return;
-
- for (int i = 0; i < 14; i++) {
-
- par[i] = fCoeff[(Z - 1)][i];
-
- }
- fAmasr = (fAmasr ? fAmasr : fAmat);
- // calculate "thickness"
- //for isotopic materials, the density used in the conversion
- //from microns or cm to mg/cm2 is modified according to the
- //chosen isotopic mass, fAmasr
- switch (fUnits) {
- case kMICRONS:
- par[14] = 0.1 * fThick * fDens * (fAmasr / fAmat);
- break;
- case kMGCM2:
- par[14] = fThick;
- break;
- case kCM:
- par[14] = fThick * fDens * 1000. * (fAmasr / fAmat);
- break;
- //gases: calculate density*thickness of cell
- case kMBAR:
- case kTORR:
- par[14] = fGasThick * GetDensity();
- break;
- }
- par[15] = A;
- par[16] = GetEminVedaloss(Z) * A;
- par[17] = GetEmaxVedaloss(Z) * A;
- if( fAmasr == fAmat ) par[18] = 0.;
- else par[18] = TMath::Log(fAmasr / fAmat);
-}
-
-//______________________________________________________________________________________________//
-void KVMaterial::SetELossParams(Int_t Z, Int_t A)
-{
- //Initialise energy loss coefficients for this material and a given incident nucleus (Z,A)
- static Double_t par[19];
- GetELossParams(Z, A, par);
- if (!ELoss) {
- //search in list of functions for one corresponding to this material
- //the name of the required function is ELoss
- ELoss = (TF1 *) gROOT->GetListOfFunctions()->FindObject("ELoss");
- if (!ELoss)
- ELoss = new TF1("ELoss", ELossSaclay, 0.1, 5000., 19);
- }
- ELoss->SetParameters(par);
-}
-
-//______________________________________________________________________________________________//
-void KVMaterial::SetEResParams(Int_t Z, Int_t A)
-{
- //Initialise coefficients for residual energy function for this material and a given incident nucleus (Z,A)
-
- static Double_t par[19];
- GetELossParams(Z, A, par);
- if (!ERes) {
- //search in list of functions for one corresponding to this material
- //the name of the required function is ERes
- ERes = (TF1 *) gROOT->GetListOfFunctions()->FindObject("ERes");
- if (!ERes)
- ERes = new TF1("ERes", EResSaclay, 0.1, 5000., 19);
- }
- ERes->SetParameters(par);
-}
-
//______________________________________________________________________________________//
Double_t KVMaterial::GetELostByParticle(KVNucleus * kvn, TVector3 * norm)
{
- //*** Saclay VEDALOSS library: translation of functions PARAM, GET_PARAM and ELOSS.
- //
- //Method to simulate passage of a charged particle (ion) through a given thickness of
- //material. The energy loss of the particle in the material is returned by the method.
- //The thickness is given in cm (for CsI crystals, NE102), in mbar (for C3F8), in micrometres
- //(for Silicon, Mylar), or mg/cm2 (all others).
- //
- //If the optional argument 'norm' is given, it is supposed to be a vector
- //normal to the material, oriented from the origin towards the material.
- //In this case the effective thickness of the material 'seen' by the particle
- //depending on its direction of motion is used for the calculation.
-
-
+ // Method to simulate passage of an ion through a given thickness of material.
+ // The energy loss of the particle (in MeV) in the material is returned by the method.
+ //
+ // If the optional argument 'norm' is given, it is supposed to be a vector
+ // normal to the material, oriented from the origin towards the material.
+ // In this case the effective thickness of the material 'seen' by the particle
+ // depending on its direction of motion is used for the calculation.
+
+ Double_t thickness;
if (norm) {
- Double_t thick = GetThickness();
TVector3 p = kvn->GetMomentum();
- Double_t e = GetEffectiveThickness((*norm), p);
-#ifdef DBG_TRGT
- cout << "Thickness used in energy loss calculation=" << e << endl;
-#endif
- SetThickness(e);
- Double_t E_loss = GetDeltaE(kvn->GetZ(), kvn->GetA(), kvn->GetKE());
- SetThickness(thick);
- return E_loss;
+ thickness = GetEffectiveThickness((*norm), p);
}
- Double_t E_loss = GetDeltaE(kvn->GetZ(), kvn->GetA(), kvn->GetKE());
+ else
+ thickness = GetThickness();
+ Double_t E_loss =
+ fIonRangeTable->GetLinearDeltaEOfIon(GetType(),kvn->GetZ(), kvn->GetA(), kvn->GetKE(),
+ thickness, fAmasr,fTemp,fPressure);
return E_loss;
}
@@ -804,16 +434,16 @@
//In this case the effective thickness of the material 'seen' by the particle
//depending on its direction of motion is used for the calculation.
+ Double_t thickness;
if (norm) {
- Double_t thick = GetThickness();
TVector3 p = kvn->GetMomentum();
- Double_t e = GetEffectiveThickness((*norm), p);
- SetThickness(e);
- Double_t E_inc = GetIncidentEnergyFromERes(kvn->GetZ(), kvn->GetA(), kvn->GetKE());
- SetThickness(thick);
- return E_inc;
+ thickness = GetEffectiveThickness((*norm), p);
}
- Double_t E_inc = GetIncidentEnergyFromERes(kvn->GetZ(), kvn->GetA(), kvn->GetKE());
+ else
+ thickness = GetThickness();
+ Double_t E_inc = fIonRangeTable->
+ GetLinearEIncFromEResOfIon(GetType(),kvn->GetZ(), kvn->GetA(), kvn->GetKE(),
+ thickness, fAmasr, fTemp, fPressure);
return E_inc;
}
@@ -823,14 +453,10 @@
{
// Calculate energy loss in absorber for incident nucleus (Z,A)
// with kinetic energy Einc (MeV)
- // For a KVDetector, the energy loss of the ACTIVE layer only is returned.
-
- if(Z<1 || Z>ZMAX_VEDALOSS) return 0.;
-
- SetELossParams(Z, A);
-
- Double_t E_loss = GetELossFunction()->Eval(Einc);
-
+
+ if(Z<1) return 0.;
+ Double_t E_loss =
+ fIonRangeTable->GetLinearDeltaEOfIon(GetType(), Z, A, Einc, GetThickness(), fAmasr, fTemp, fPressure);
return E_loss;
}
@@ -840,27 +466,17 @@
{
// Calculate energy loss in absorber for nucleus (Z,A)
// having a residual kinetic energy Eres (MeV) after the absorber
- // For a KVDetector, the energy loss of the ACTIVE layer only is returned.
-
- if(Z<1 || Z>ZMAX_VEDALOSS) return 0.;
-
- Double_t EINC = -1.;
- SetEResParams(Z, A);
- EINC = GetEResFunction()->GetX(Eres, GetEminVedaloss(Z) * A,
- GetEmaxVedaloss(Z) * A);
-
- // Calculate energy loss in absorber for incident nucleus (Z,A)
- // with kinetic energy Einc (MeV)
- SetELossParams(Z, A);
- Double_t E_loss = GetELossFunction()->Eval(EINC);
-
+
+ if(Z<1) return 0.;
+ Double_t E_loss = fIonRangeTable->
+ GetLinearDeltaEFromEResOfIon(
+ GetType(),Z,A,Eres,GetThickness(),fAmasr,fTemp,fPressure);
return E_loss;
}
//______________________________________________________________________________________//
-Double_t KVMaterial::GetEResFromDeltaE(Int_t Z, Int_t A, Double_t dE,
- enum SolType type)
+Double_t KVMaterial::GetEResFromDeltaE(Int_t Z, Int_t A, Double_t dE, enum KVIonRangeTable::SolType type)
{
// Calculate residual kinetic energy Eres (MeV) after the absorber from
// energy loss in absorber for nucleus (Z,A). If dE is not given, the energy
@@ -880,54 +496,29 @@
//maximum dE.
Double_t EINC = GetIncidentEnergy(Z,A,dE,type);
- SetEResParams(Z, A);
- return GetEResFunction()->Eval(EINC);
+ return EINC-dE;
}
//__________________________________________________________________________________________
-Double_t KVMaterial::GetIncidentEnergy(Int_t Z, Int_t A, Double_t delta_e,
- enum SolType type)
+Double_t KVMaterial::GetIncidentEnergy(Int_t Z, Int_t A, Double_t delta_e, enum KVIonRangeTable::SolType type)
{
//Calculate incident energy of nucleus (Z,A) corresponding to the energy loss
//in this absorber. If delta_e is not given, the energy loss in this absorber is used.
//
//By default the solution corresponding to the highest incident energy is returned
//This is the solution found for Einc greater than the maximum of the dE(Einc) curve.
- //If you want the low energy solution (i.e. below Bragg peak for gas detector)
- //set SolType = KVMaterial::kEmin.
+ //If you want the low energy solution set SolType = KVIonRangeTable::kEmin.
//
//If the given energy loss in the absorber is greater than the maximum theoretical dE
- //(dE > GetBraggDE) then we return the incident energy corresponding to the maximum,
- //GetBraggE.
+ //(dE > GetMaxDeltaE(Z,A)) then we return the incident energy corresponding to the maximum,
+ //GetEIncOfMaxDeltaE(Z,A)
- if(Z<1 || Z>ZMAX_VEDALOSS) return 0.;
+ if(Z<1) return 0.;
- Double_t EINC = -1.;
Double_t DE = (delta_e > 0 ? delta_e : GetEnergyLoss());
- SetELossParams(Z, A);
- //energy loss in the absorber is greater than the maximum theoretical dE ?
- Double_t braggDE = GetELossFunction()->GetMaximum(GetEminVedaloss(Z) * A,
- GetEmaxVedaloss(Z) * A);
- if (DE > braggDE)
- return GetELossFunction()->GetMaximumX(GetEminVedaloss(Z) * A,
- GetEmaxVedaloss(Z) * A);
-
- // Emax = GetBraggE(Z,A)
- Double_t Emax = GetELossFunction()->GetMaximumX(GetEminVedaloss(Z) * A,
- GetEmaxVedaloss(Z) * A);
- switch (type) {
- case kEmin:
- EINC = GetELossFunction()->GetX(DE, GetEminVedaloss(Z) * A, Emax);
- break;
-
- case kEmax:
- EINC = GetELossFunction()->GetX(DE, Emax, GetEmaxVedaloss(Z) * A);
- break;
- }
-
- return EINC;
+ return fIonRangeTable->GetLinearEIncFromDeltaEOfIon(GetType(),Z,A,DE,GetThickness(),type,fAmasr,fTemp,fPressure);
}
//______________________________________________________________________________________//
@@ -937,11 +528,10 @@
// Calculate residual energy after absorber for incident nucleus (Z,A)
// with kinetic energy Einc (MeV)
- if(Z<1 || Z>ZMAX_VEDALOSS) return 0.;
+ if(Z<1) return 0.;
- SetEResParams(Z, A);
-
- Double_t E_res = GetEResFunction()->Eval(Einc);
+ Double_t E_res =
+ fIonRangeTable->GetEResOfIon(GetType(), Z, A, Einc, fThick, fAmasr, fTemp, fPressure);
return E_res;
}
@@ -985,20 +575,6 @@
fELoss = 0.0;
}
-//__________________________________________________________________________________________
-
-const Char_t *KVMaterial::GetThicknessUnits() const
-{
- //Returns a string with the name of the units used to measure "thickness"
- //for this material type
- if (GetActiveLayer())
- return GetActiveLayer()->GetThicknessUnits();
- if (fUnits < 10)
- return kUnits[GetUnits()];
- else
- return "(undefined)";
-}
-
#if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
void KVMaterial::Copy(TObject & obj) const
#else
@@ -1009,9 +585,9 @@
KVBase::Copy(obj);
((KVMaterial &) obj).SetMaterial(GetType());
((KVMaterial &) obj).SetMass(GetMass());
- ((KVMaterial &) obj).SetThickness(GetThickness());
((KVMaterial &) obj).SetPressure(GetPressure());
((KVMaterial &) obj).SetTemperature(GetTemperature());
+ ((KVMaterial &) obj).SetThickness(GetThickness());
}
//__________________________________________________________________________________________
@@ -1020,39 +596,36 @@
Double_t Eres)
{
//Get incident energy from residual energy
- if(Z<1 || Z>ZMAX_VEDALOSS) return 0.;
+ if(Z<1) return 0.;
- Double_t EINC = -1.;
- SetEResParams(Z, A);
- EINC =
- GetEResFunction()->GetX(Eres, GetEminVedaloss(Z) * A,
- GetEmaxVedaloss(Z) * A);
- return EINC;
+ return fIonRangeTable->
+ GetLinearEIncFromEResOfIon(GetType(),Z,A,Eres,GetThickness(),fAmasr,fTemp,fPressure);
}
//__________________________________________________________________________________________
-Double_t KVMaterial::GetBraggE(Int_t Z, Int_t A)
+Double_t KVMaterial::GetEIncOfMaxDeltaE(Int_t Z, Int_t A)
{
//Incident energy for which the DE(E) curve has a maximum
- if(Z<1 || Z>ZMAX_VEDALOSS) return 0.;
+ if(Z<1) return 0.;
- SetELossParams(Z, A);
- return GetELossFunction()->GetMaximumX(GetEminVedaloss(Z) * A,
- GetEmaxVedaloss(Z) * A);
+ return fIonRangeTable->
+ GetLinearEIncOfMaxDeltaEOfIon(GetType(),Z,A,GetThickness(),fAmasr,fTemp,fPressure);
}
//__________________________________________________________________________________________
-Double_t KVMaterial::GetBraggDE(Int_t Z, Int_t A)
+Double_t KVMaterial::GetMaxDeltaE(Int_t Z, Int_t A)
{
- //The maximum energy loss of this particle
- //(corresponding to incident energy GetBraggE(Z,A))
- if(Z<1 || Z>ZMAX_VEDALOSS) return 0.;
-
- SetELossParams(Z, A);
- return GetELossFunction()->GetMaximum(GetEminVedaloss(Z) * A,
- GetEmaxVedaloss(Z) * A);
+ // The maximum energy loss of this particle (corresponding to incident energy GetEIncOfMaxDeltaE(Z,A))
+ // For detectors, this is the maximum energy loss in the active layer.
+
+ if(GetActiveLayer()) return GetActiveLayer()->GetMaxDeltaE(Z,A);
+
+ if(Z<1) return 0.;
+
+ return fIonRangeTable->
+ GetLinearMaxDeltaEOfIon(GetType(),Z,A,GetThickness(),fAmasr,fTemp,fPressure);
}
//__________________________________________________________________________________________
@@ -1108,30 +681,12 @@
return gmed;
}
-
-//______________________________________________________________________________
-
-void KVMaterial::Streamer(TBuffer &R__b)
+Double_t KVMaterial::GetEmaxValid(Int_t Z, Int_t A)
{
- // Stream an object of class KVMaterial.
+ // Return maximum incident energy for which range tables are valid
+ // for this material and ion (Z,A).
+ // For detectors, return max energy for active layer.
+ if(GetActiveLayer()) return GetActiveLayer()->GetEmaxValid(Z,A);
+ return fIonRangeTable->GetEmaxValid(GetType(), Z, A);
+}
- UInt_t R__s, R__c;
- if (R__b.IsReading()) {
- Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
- R__b.ReadClassBuffer(KVMaterial::Class(),this,R__v,R__s,R__c);
- if (R__v < 5){
- // correct densities of solids written with class version < 5
- // this is to fix launchpad bug#446163
- // it affects materials with fUnits = kMICRONS or kCM
- // if the density we read is less than that we find
- // for a new instanciation of the same type of material,
- // we use the current value.
- if(fUnits==kMICRONS || fUnits==kCM){
- KVMaterial tmp(GetType());
- if(GetDensity() < tmp.GetDensity()) SetDensity(tmp.GetDensity());
- }
- }
- } else {
- R__b.WriteClassBuffer(KVMaterial::Class(),this);
- }
-}
=== modified file 'KVMultiDet/detectors/KVMaterial.h'
--- KVMultiDet/detectors/KVMaterial.h 2009-11-26 16:48:10 +0000
+++ KVMultiDet/detectors/KVMaterial.h 2011-03-14 15:58:00 +0000
@@ -1,5 +1,4 @@
/***************************************************************************
-$Id: KVMaterial.h,v 1.31 2008/12/17 13:01:26 franklan Exp $
kvmaterial.h - description
-------------------
begin : Thu May 16 2002
@@ -22,115 +21,52 @@
#define KVMATERIAL_H
#include "RVersion.h"
-#include "TRef.h"
#include "KVBase.h"
#include "KVList.h"
#include "TF1.h"
#include "TVector3.h"
#include "Riostream.h"
-
-// warning messages
-#define KVMATERIAL_INIT_FILE_NOT_FOUND "Initialisation file %s not found. Cannot create detectors"
-#define KVMATERIAL_INIT_FILE_HEADER_PROBLEM "Problem reading initialisation file %s. Check format of header"
-#define KVMATERIAL_INIT_FILE_COEFF_PROBLEM "Problem reading initialisation file %s. Check format of coefficients for %s"
-#define KVMATERIAL_INIT_FILE_DATA_PROBLEM "Problem reading initialisation file %s. Check format of data"
-#define KVMATERIAL_TYPE_NOT_FOUND "Unknown material type %s. Check file %s for known types"
-
-#define RTT 623.61040
-#define ZERO_KELVIN 273.15
-#define PERC 0.02
-
-// maximum atomic number included in range tables
-#define ZMAX_VEDALOSS 100
+#include "KVIonRangeTable.h"
class KVNucleus;
class KVTelescope;
class TGeoMedium;
-Double_t ELossSaclay(Double_t * x, Double_t * par);
-Double_t EResSaclay(Double_t * x, Double_t * par);
-
class KVMaterial:public KVBase {
protected:
- TF1 * ELoss; //!function calculating energy loss in material from incident energy
- TF1 *ERes; //!function calculating residual energy from incident energy
+ static KVIonRangeTable* fIonRangeTable; // pointer to class used to calculate charged particle ranges & energy losses
+
TVector3 fNormToMat;//!dummy vector for calculating normal to absorber
public:
- TF1 * GetELossFunction() {
- return ELoss;
- };
- TF1 *GetEResFunction() {
- return ERes;
- };
- virtual void SetELossParams(Int_t Z, Int_t A);
- void GetELossParams(Int_t Z, Int_t A, Double_t * par);
- enum SolType {
- kEmax,
- kEmin
- };
- virtual void SetEResParams(Int_t Z, Int_t A);
-
- virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A,
- Double_t Eres);
-
- enum { //constants defined for units
- kMBAR,
- kMICRONS,
- kMGCM2,
- kCM,
- kTORR
- };
private:
- Double_t fAmat; //atomic mass of material
- Double_t fZmat; //atomic number of material
- Double_t fDens; //density of material
- UInt_t fUnits; //used to determine how to calculate effective thickness
- Double_t fGasThick; //only used for gases
- Double_t fMoleWt; //only used for gases
- Double_t fTemp; //only used for gases
- Double_t fCoeff[ZMAX_VEDALOSS][15]; //[ZMAX_VEDALOSS][15] parameters for range tables
- Float_t fAmasr; //isotopic mass for material; if not set will use default value
- static TString kDataFilePath; //! full path to file containing energy loss parameters
- Float_t fEmax[ZMAX_VEDALOSS]; //[ZMAX_VEDALOSS] Z-dependent maximum energy/nucleon for calculation to be valid
- Float_t fEmin[ZMAX_VEDALOSS]; //[ZMAX_VEDALOSS] Z-dependent minimum energy/nucleon for calculation to be valid
- Float_t fThick; //thickness of absorber
+ Int_t fAmasr; // isotopic mass of element
+ Double_t fThick; // area density of absorber in g/cm**2
+ Double_t fPressure; // gas pressure in torr
+ Double_t fTemp; // gas temperature in degrees celsius
Double_t fELoss; //total of energy lost by all particles traversing absorber
- static Char_t kUnits[5][10]; //!strings for names of units for thickness
public:
KVMaterial();
- KVMaterial(const Char_t * type, const Float_t thick = 0.0);
+ KVMaterial(const Char_t * type, const Double_t thick = 0.0);
+ KVMaterial(const Char_t * gas, const Double_t thick, const Double_t pressure, const Double_t temperature = 19.0);
+ KVMaterial(Double_t area_density, const Char_t * type);
KVMaterial(const KVMaterial &);
void init();
virtual ~ KVMaterial();
- static KVList *GetListOfMaterials();
- void SetMass(Float_t a);
+ void SetMass(Double_t a);
virtual void SetMaterial(const Char_t * type);
Double_t GetMass() const;
Double_t GetZ() const;
Double_t GetDensity() const;
- void SetDensity(Double_t d)
- {
- // Set density of material. Units are g/cm**3
- fDens = d;
- }
- Float_t GetEmaxVedaloss(UInt_t Z) const {
- if (GetActiveLayer())
- return GetActiveLayer()->GetEmaxVedaloss(Z);
- return ((Z <= ZMAX_VEDALOSS && Z > 0) ? fEmax[Z - 1] : 0.0);
- };
- Float_t GetEminVedaloss(UInt_t Z) const {
- if (GetActiveLayer())
- return GetActiveLayer()->GetEminVedaloss(Z);
- return ((Z <= ZMAX_VEDALOSS && Z > 0) ? fEmin[Z - 1] : 0.0);
- };
- void SetThickness(Float_t thick);
- Float_t GetThickness() const;
- Double_t GetThicknessInCM() const;
+ void SetAreaDensity(Double_t dens /* g/cm**2 */);
+ Double_t GetAreaDensity() const;
+ virtual void SetThickness(Double_t thick /* cm */);
+ virtual Double_t GetThickness() const;
Double_t GetEffectiveThickness(TVector3 & norm, TVector3 & direction);
+ Double_t GetEffectiveAreaDensity(TVector3 & norm, TVector3 & direction);
virtual void DetectParticle(KVNucleus *, TVector3 * norm = 0);
virtual Double_t GetELostByParticle(KVNucleus *, TVector3 * norm = 0);
@@ -151,33 +87,33 @@
#endif
virtual void Clear(Option_t * opt = "");
- const Char_t *GetThicknessUnits() const;
- virtual UInt_t GetUnits() const;
- void SetUnits(UInt_t);
-
- Double_t GetIncidentEnergy(Int_t Z, Int_t A, Double_t delta_e =
- -1.0, enum SolType type = kEmax);
- Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc);
- Double_t GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres);
- Double_t GetERes(Int_t Z, Int_t A, Double_t Einc);
- Double_t GetEResFromDeltaE(Int_t Z, Int_t A, Double_t dE =
- -1.0, enum SolType type = kEmax);
- Double_t GetBraggE(Int_t Z, Int_t A);
- Double_t GetBraggDE(Int_t Z, Int_t A);
+ virtual Double_t GetEmaxValid(Int_t Z, Int_t A);
+ virtual Double_t GetIncidentEnergy(Int_t Z, Int_t A, Double_t delta_e =
+ -1.0, enum KVIonRangeTable::SolType type = KVIonRangeTable::kEmax);
+ virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres);
+ virtual Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc);
+ virtual Double_t GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres);
+ virtual Double_t GetERes(Int_t Z, Int_t A, Double_t Einc);
+ virtual Double_t GetEResFromDeltaE(Int_t Z, Int_t A, Double_t dE =
+ -1.0, enum KVIonRangeTable::SolType type = KVIonRangeTable::kEmax);
+ virtual Double_t GetEIncOfMaxDeltaE(Int_t Z, Int_t A);
+ virtual Double_t GetMaxDeltaE(Int_t Z, Int_t A);
virtual KVMaterial *GetActiveLayer() const {
return 0;
}; //to facilitate polymorphism with KVDetector class
- virtual void SetPressure(Float_t);
- virtual void SetTemperature(Float_t t);
+ virtual void SetPressure(Double_t);
+ virtual void SetTemperature(Double_t);
- Float_t GetPressure() const;
- Float_t GetTemperature() const;
+ virtual Double_t GetPressure() const;
+ virtual Double_t GetTemperature() const;
Bool_t IsIsotopic() const;
Bool_t IsNat() const;
+ Bool_t IsGas() const;
+
virtual const TVector3& GetNormal() {
// Return vector normal to surface of absorber. For a KVMaterial, this is (0,0,1) as
// a basic absorber has no orientation. Rederived in child classes KVTarget and KVDetector.
@@ -185,8 +121,10 @@
};
virtual TGeoMedium* GetGeoMedium(const Char_t* /*med_name*/="");
+
+ virtual KVIonRangeTable* GetRangeTable() const { return fIonRangeTable; };
- ClassDef(KVMaterial, 5) //Interface to VEDALOSS description of slowing-down of ions in absorbers
+ ClassDef(KVMaterial, 6) // Class describing physical materials used to construct detectors & targets
};
#endif
=== modified file 'KVMultiDet/detectors/KVTarget.cpp'
--- KVMultiDet/detectors/KVTarget.cpp 2009-11-29 18:21:06 +0000
+++ KVMultiDet/detectors/KVTarget.cpp 2011-03-14 15:58:00 +0000
@@ -28,6 +28,9 @@
KVTarget targ("Ta", 8.3); // first layer 8.3mg/cm2 Ta
targ.AddLayer("C", 20.0); // second layer 20mg/cm2 C
</pre>
+
+Note that all "thicknesses" for targets and target layers are in mg/cm**2.
+
<h4>ORIENTATION OF TARGET</h4>
The target can be oriented in an arbitrary way, by defining the vector normal to its
@@ -139,10 +142,11 @@
//________________________________________________________________________
-KVTarget::KVTarget(const Char_t * material,
- const Double_t thick):KVMaterial(), fNormal(0, 0, 1)
+KVTarget::KVTarget(const Char_t * material, const Double_t thick):KVMaterial(), fNormal(0, 0, 1)
{
- //Just give the type & thickness of material for target
+ // Just give the type & "thickness" of material for target
+ // The "thickness" is the area density of the target in mg/cm**2.
+
init();
AddLayer(material, thick);
}
@@ -176,19 +180,19 @@
TIter next(GetLayers());
KVMaterial *mat = 0;
while ((mat = (KVMaterial *) next())) {
- ((KVTarget &) obj).AddLayer(mat->GetType(),mat->GetThickness());
+ ((KVTarget &) obj).AddLayer(mat->GetType(), mat->GetAreaDensity()/KVUnits::mg);
}
}
//________________________________________________________________________
void KVTarget::AddLayer(const Char_t * material, Double_t thick)
{
- //Add a layer to a target
- //Sets/updates name of target with name of material.
- //In case of multi-layer target the name is
+ // Add a layer to a target, with 'thickness' in mg/cm**2 (area density).
+ // Sets/updates name of target with name of material.
+ // In case of multi-layer target the name is
// material1/material2/material3/...
- fTargets->Add(new KVMaterial(material, thick));
+ fTargets->Add(new KVMaterial(thick*KVUnits::mg, material));
fNLayers++;
if (fNLayers == 1) {
SetName(material);
@@ -204,21 +208,25 @@
Double_t KVTarget::GetTotalThickness()
{
- //return sum of thicknesses of all layers in target
+ // return sum of 'thicknesses' (area densities in mg/cm**2)
+ // of all layers in target
+
Float_t thick = 0.;
TIter next(fTargets);
KVMaterial *mat = 0;
while ((mat = (KVMaterial *) next())) {
- thick += mat->GetThickness();
+ thick += mat->GetAreaDensity();
}
- return thick;
+ return thick/KVUnits::mg;
}
//________________________________________________________________________
Double_t KVTarget::GetTotalThickness(Int_t lay1, Int_t lay2)
{
- //return sum of thicknesses of layers lay1 to lay2 in target
+ //return sum of 'thicknesses' (area densities in mg/cm**2)
+ // of layers lay1 to lay2 in target
+
Double_t thick = 0.;
for (register int i = lay1; i <= lay2; i++) {
thick += GetThickness(i);
@@ -250,7 +258,7 @@
Double_t KVTarget::GetEffectiveThickness(KVParticle * part, Int_t ilayer)
{
- //Return effective thickness of layer ilayer (ilayer=1, 2, ...)
+ //Return effective 'thickness' (in mg/cm**2) of layer ilayer (ilayer=1, 2, ...)
//By default ilayer=1 (i.e. for single layer target)
//The effective thickness depends on the angle of the target (rotation about
//x-axis => theta wrt z- (beam)-axis).
@@ -273,7 +281,7 @@
Double_t KVTarget::GetEffectiveThickness(TVector3 & direction,
Int_t ilayer)
{
- //Return effective thickness of layer ilayer (ilayer=1, 2, ...)
+ //Return effective 'thickness' (in mg/cm**2) of layer ilayer (ilayer=1, 2, ...)
//By default ilayer=1 (i.e. for single layer target)
//The effective thickness depends on the orientation of the target (given by
//the direction of the normal to its surface) and on the direction (e.g. direction of a particle)
@@ -284,8 +292,7 @@
ilayer, NumberOfLayers());
return 0.0;
}
- return GetLayerByIndex(ilayer)->GetEffectiveThickness(fNormal,
- direction);
+ return GetLayerByIndex(ilayer)->GetEffectiveAreaDensity(fNormal, direction)/KVUnits::mg;
}
//________________________________________________________________________
@@ -294,7 +301,7 @@
{
//Returns absorber corresponding to 'depth' inside target, starting from the 'entrance'
//layer and following the direction of 'depth'. Note: 'depth' is measured in the same
- //'thickness' units as the thickness of the different layers of the target (mg/cm2, um, etc.)
+ //'thickness' units as the thickness of the different layers of the target (mg/cm2)
//WARNING : returns 0 if no layer is found (depth is outside of target)
return GetLayerByIndex(GetLayerIndex(depth));
@@ -306,7 +313,7 @@
{
//Returns absorber index corresponding to 'depth' inside target, starting from the 'entrance'
//layer and following the direction of 'depth'. Note: 'depth' is measured in the same
- //'thickness' units as the thickness of the different layers of the target (mg/cm2, um, etc.)
+ //'thickness' units as the thickness of the different layers of the target (mg/cm2)
//WARNING : user should check returned index is >0
//If not, this means that the given depth does not correspond to a layer inside the target
@@ -357,9 +364,9 @@
Double_t KVTarget::GetThickness(Int_t ilayer) const
{
- //Thickness of layer 'ilayer' in target
+ //'Thickness' in mg/cm**2 of layer 'ilayer' in target
KVMaterial *lay = GetLayerByIndex(ilayer);
- return (lay ? lay->GetThickness() : 0.0);
+ return (lay ? lay->GetAreaDensity()/KVUnits::mg : 0.0);
}
//________________________________________________________________________
@@ -368,7 +375,7 @@
{
//Returns absorber index corresponding to 'depth' inside target, starting from the 'entrance'
//layer and following the normal direction. Note: 'depth' is measured in the same
- //'thickness' units as the thickness of the different layers of the target (mg/cm2, um, etc.)
+ //'thickness' units as the thickness of the different layers of the target (mg/cm2)
//WARNING : user should check returned index is >0
//If not, this means that the given depth does not correspond to a layer inside the target
@@ -387,7 +394,7 @@
Double_t KVTarget::GetTotalEffectiveThickness(KVParticle * part)
{
- //return sum of effective thicknesses of all layers in target
+ //return sum of effective 'thicknesses' (mg/cm**2) of all layers in target
//taking into account the angle of the target to the beam
//and the direction of motion of the incident particle.
//If no particle is given, effective thicknesses are calculated as for
@@ -402,7 +409,7 @@
Double_t KVTarget::GetTotalEffectiveThickness(TVector3 & dir, Int_t ilay1,
Int_t ilay2)
{
- //return sum of effective thicknesses of layers ilay1 to ilay2 in target
+ //return sum of effective 'thicknesses' (mg/cm**2) of layers ilay1 to ilay2 in target
//taking into account the angle of the target to the beam
//and the given direction.
//
@@ -484,18 +491,18 @@
iplay_index) -
GetInteractionPoint() * GetNormal();
e_thick_iplay =
- (IsIncoming()? iplay->GetThickness() -
+ (IsIncoming()? iplay->GetAreaDensity()/KVUnits::mg -
e_thick_iplay : e_thick_iplay);
if (backwards)
- e_thick_iplay = iplay->GetThickness() - e_thick_iplay;
+ e_thick_iplay = iplay->GetAreaDensity()/KVUnits::mg - e_thick_iplay;
#ifdef DBG_TRGT
cout << "Effective thickness of IP layer is " << e_thick_iplay <<
- " (real:" << iplay->GetThickness() << ")" << endl;
+ " (real:" << iplay->GetAreaDensity()/KVUnits::mg << ")" << endl;
#endif
//modify effective physical thickness of layer
- Double_t thick_iplay = iplay->GetThickness();
- iplay->SetThickness(e_thick_iplay);
+ Double_t thick_iplay = iplay->GetAreaDensity();// in g/cm**2
+ iplay->SetAreaDensity(e_thick_iplay*KVUnits::mg);
//first and last indices of layers to pass through
Int_t ilay1 =
@@ -516,7 +523,7 @@
}
//reset original thickness of IP layer
- iplay->SetThickness(thick_iplay);
+ iplay->SetAreaDensity(thick_iplay);
} else {
Error("DetectParticle", "Interaction point is outside of target");
@@ -586,18 +593,18 @@
iplay_index) -
GetInteractionPoint() * GetNormal();
e_thick_iplay =
- (IsIncoming()? iplay->GetThickness() -
+ (IsIncoming()? iplay->GetAreaDensity()/KVUnits::mg -
e_thick_iplay : e_thick_iplay);
if (backwards)
- e_thick_iplay = iplay->GetThickness() - e_thick_iplay;
+ e_thick_iplay = iplay->GetAreaDensity()/KVUnits::mg - e_thick_iplay;
#ifdef DBG_TRGT
cout << "Effective thickness of IP layer is " << e_thick_iplay <<
- " (real:" << iplay->GetThickness() << ")" << endl;
+ " (real:" << iplay->GetAreaDensity()/KVUnits::mg << ")" << endl;
#endif
//modify effective physical thickness of layer
- Double_t thick_iplay = iplay->GetThickness();
- iplay->SetThickness(e_thick_iplay);
+ Double_t thick_iplay = iplay->GetAreaDensity(); // g/cm**2
+ iplay->SetAreaDensity(e_thick_iplay*KVUnits::mg);
//first and last indices of layers to pass through
Int_t ilay1 =
@@ -626,7 +633,7 @@
}
//reset original thickness of IP layer
- iplay->SetThickness(thick_iplay);
+ iplay->SetAreaDensity(thick_iplay);
} else {
Error("DetectParticle", "Interaction point is outside of target");
@@ -776,18 +783,18 @@
void KVTarget::SetMaterial(const Char_t * type)
{
- //Set material of first layer
+ // Set material of first layer
if (GetLayerByIndex(1))
GetLayerByIndex(1)->SetMaterial(type);
}
//______________________________________________________________________________________________________
-void KVTarget::SetThickness(Float_t thick, Int_t ilayer)
+void KVTarget::SetLayerThickness(Float_t thick, Int_t ilayer)
{
- //Setthickness of a layer, by default this is the first layer
+ // Set 'thickness' in mg/cm**2 of a layer, by default this is the first layer
if (GetLayerByIndex(ilayer))
- GetLayerByIndex(ilayer)->SetThickness(thick);
+ GetLayerByIndex(ilayer)->SetAreaDensity(thick*KVUnits::mg);
}
//______________________________________________________________________________________________________
@@ -795,7 +802,7 @@
Double_t KVTarget::GetAtomsPerCM2() const
{
//Calculates total number of atoms per square centimetre of the target.
- //For a multilayer target, the areal densities for each layer are summed up.
+ //For a multilayer target, the area densities for each layer are summed up.
Double_t atom_cib = 0;
for (register int i = 1; i <= NumberOfLayers(); i++) {
//N_atoms = N_Avogadro * target_thickness (mg/cm**2) * 1.e-3 / atomic_mass_of_target
@@ -860,14 +867,14 @@
iplay_index) -
GetInteractionPoint() * GetNormal();
e_thick_iplay =
- (IsIncoming()? iplay->GetThickness() -
+ (IsIncoming()? iplay->GetAreaDensity()/KVUnits::mg -
e_thick_iplay : e_thick_iplay);
if (backwards)
- e_thick_iplay = iplay->GetThickness() - e_thick_iplay;
+ e_thick_iplay = iplay->GetAreaDensity()/KVUnits::mg - e_thick_iplay;
//modify effective physical thickness of layer
Double_t thick_iplay = iplay->GetThickness();
- iplay->SetThickness(e_thick_iplay);
+ iplay->SetAreaDensity(e_thick_iplay);
//first and last indices of layers to pass through
Int_t ilay1 =
@@ -901,7 +908,7 @@
}
//reset original thickness of IP layer
- iplay->SetThickness(thick_iplay);
+ iplay->SetAreaDensity(thick_iplay);
} else {
Error("GetParticleEIncFromERes", "Interaction point is outside of target");
@@ -940,20 +947,3 @@
return GetParticleEIncFromERes(&dummy);
}
-//___________________________________________________________________________________
-
-UInt_t KVTarget::GetUnits() const
-{
- // Returns units for 'thickness' of target.
- // We actually only look at the 1st layer of the target, and assume all layers have
- // the same units.
- // If you want, you can examine individual layers with GetLayer(i)->GetUnits().
- // Returned value can be one of:
- // KVMaterial::kMBAR, KVMaterial::kMGCM2, KVMaterial::kTORR,
- // KVMaterial::kMICRON, KVMaterial::kCM.
-
- KVMaterial * lay = const_cast<KVTarget*>(this)->GetLayerByIndex(1);
- if (lay) return lay->GetUnits();
- return 10; // no layers - undefined
-}
-
=== modified file 'KVMultiDet/detectors/KVTarget.h'
--- KVMultiDet/detectors/KVTarget.h 2009-11-26 16:48:10 +0000
+++ KVMultiDet/detectors/KVTarget.h 2011-03-14 15:58:00 +0000
@@ -49,7 +49,7 @@
Double_t GetAngleToBeam();
virtual void SetMaterial(const Char_t * type);
- void SetThickness(Float_t thick, Int_t ilayer = 1);
+ void SetLayerThickness(Float_t thick, Int_t ilayer = 1);
void AddLayer(const Char_t * material, Double_t thick);
Int_t NumberOfLayers() const {
@@ -73,9 +73,8 @@
Double_t GetTotalThickness();
Double_t GetTotalThickness(Int_t lay1, Int_t lay2);
- Float_t GetThickness() const {
- return (Float_t) const_cast <
- KVTarget * >(this)->GetTotalThickness();
+ Double_t GetThickness() const {
+ return const_cast <KVTarget * >(this)->GetTotalThickness();
};
Double_t GetTotalEffectiveThickness(KVParticle * part = 0);
Double_t GetTotalEffectiveThickness(TVector3 &, Int_t lay1 =
@@ -149,7 +148,7 @@
#else
virtual void Copy(TObject & obj);
#endif
- virtual UInt_t GetUnits() const;
+ // virtual UInt_t GetUnits() const;
Double_t GetAtomsPerCM2() const;
=== modified file 'KVMultiDet/events/KVElasticScatterEvent.cpp'
--- KVMultiDet/events/KVElasticScatterEvent.cpp 2011-02-17 07:50:39 +0000
+++ KVMultiDet/events/KVElasticScatterEvent.cpp 2011-03-14 15:58:00 +0000
@@ -401,10 +401,9 @@
);
printf("# Propagation dans une cible de:\n");
for (Int_t nn=0;nn<GetTarget().GetLayers()->GetEntries();nn+=1){
- printf("# type:%s epaisseur:%1.2lf (%s)\n",
+ printf("# type:%s epaisseur:%1.2lf (mg/cm**2)\n",
GetTarget().GetLayerByIndex(nn+1)->GetType(),
- GetTarget().GetLayerByIndex(nn+1)->GetThickness(),
- GetTarget().GetLayerByIndex(nn+1)->GetThicknessUnits()
+ GetTarget().GetLayerByIndex(nn+1)->GetAreaDensity()/(KVUnits::mg/pow(KVUnits::cm, 2.))
);
}
printf("#####################\n");
=== modified file 'KVMultiDet/gui/KVDBSystemDialog.cpp'
--- KVMultiDet/gui/KVDBSystemDialog.cpp 2010-01-07 14:25:47 +0000
+++ KVMultiDet/gui/KVDBSystemDialog.cpp 2011-03-14 15:58:00 +0000
@@ -435,12 +435,12 @@
return;
}
fLayer = (KVMaterial*)fTarget->GetLayers()->At(ind);
- //update thickness
- fNumberEntry1526->SetNumber(fLayer->GetThickness());
+ //update thickness - actually area density in mg/cm2
+ fNumberEntry1526->SetNumber(fLayer->GetAreaDensity()/(KVUnits::mg/pow(KVUnits::cm,2)));
//update atomic mass
fNumberEntry1537->SetNumber(fLayer->GetMass());
//update thickness units
- fLabel1530->SetText(fLayer->GetThicknessUnits());
+ fLabel1530->SetText("mg/cm2");
//enable button to remove layer
fTextButton1554->SetEnabled(kTRUE);
}
@@ -505,10 +505,11 @@
void KVDBSystemDialog::TargetLayerThicknessChanged(Long_t)
{
- //Called when target layer thickness is changed
+ // Called when target layer "thickness" is changed
+ // Note that this is in fact the area density in mg/cm**2
Double_t t = fNumberEntry1526->GetNumber();
- fLayer->SetThickness(t);
+ fLayer->SetAreaDensity(t*KVUnits::mg/pow(KVUnits::cm,2.));
SetNeedSave(1);
}
@@ -538,7 +539,9 @@
//The new layer will be added after any existing layers in the target.
//get selected material
- KVMaterial* mat = (KVMaterial*)fMaterialsList->At( fComboBox1542->GetSelected() );
+ TNamed* mat = (TNamed*)fMaterialsList->At( fComboBox1542->GetSelected() );
+ KVMaterial bidon;
+ KVIonRangeTable* RT = bidon.GetRangeTable();
//add to target of current system
//if no target is defined, we create a new one
if( !fTarget ){
@@ -546,16 +549,16 @@
if(fSystem){
fSystem->SetTarget( fTarget );
cout << "Created target for system : " << fSystem->GetName() << endl;
- fSystem->SetZtarget((UInt_t)mat->GetZ()); fSystem->SetAtarget((UInt_t)mat->GetMass());
+ fSystem->SetZtarget((UInt_t)RT->GetZ(mat->GetName())); fSystem->SetAtarget((UInt_t)RT->GetAtomicMass(mat->GetName()));
}
}
- //add layer with default thickness 0.1 mg/cm2
- fTarget->AddLayer( mat->GetType() , 0.1 );
+ //add layer with default area density 0.1 mg/cm2
+ fTarget->AddLayer( mat->GetTitle() , 0.1*KVUnits::mg/pow(KVUnits::cm,2.) );
//update list of layers in target
Int_t nlay = fComboBox1515->GetNumberOfEntries();
fComboBox1515->AddEntry( mat->GetName(), nlay );
fComboBox1515->Select( nlay+1 );
- cout << "Added layer " << mat->GetType() << " to target" << endl;
+ cout << "Added layer " << mat->GetTitle() << " to target" << endl;
SetNeedSave(1);
}
@@ -575,7 +578,7 @@
TIter next(fTarget->GetLayers()); KVMaterial* mat;
while ( (mat = (KVMaterial*)next()) ) {
if( mat != fLayer ){
- new_target->AddLayer( mat->GetType(), mat->GetThickness() );
+ new_target->AddLayer( mat->GetType(), mat->GetAreaDensity() );
}
}
new_target->SetAngleToBeam( fTarget->GetAngleToBeam() );
@@ -799,7 +802,8 @@
fComboBox1542 = new TGComboBox(fGroupFrame1541,-1,kHorizontalFrame | kSunkenFrame | kDoubleBorder | kOwnBackground);
fComboBox1542->Resize(80,22);
//fill list of all available materials
- fMaterialsList = KVMaterial::GetListOfMaterials();
+ KVMaterial bidon;
+ fMaterialsList = bidon.GetRangeTable()->GetListOfMaterials();
TIter it_mat(fMaterialsList); TObject* obj; Int_t ind = 0;
while( (obj = it_mat()) ){
fComboBox1542->AddEntry(obj->GetName(), ind++);
=== modified file 'KVMultiDet/gui/KVDBSystemDialog.h'
--- KVMultiDet/gui/KVDBSystemDialog.h 2009-01-22 15:03:32 +0000
+++ KVMultiDet/gui/KVDBSystemDialog.h 2011-03-14 15:58:00 +0000
@@ -57,7 +57,7 @@
KVMaterial *fLayer;//current target layer
KVNumberList fRuns;//runs selected by user
- KVList* fMaterialsList;//list of all available materials
+ TObjArray* fMaterialsList;//list of all available materials
KVDatedFileManager* fUndo;//allows to undo changes to Systems.dat
KVString fCurrentSystemsFile;//name (including timestamp) of currently used Systems.dat
=== modified file 'KVMultiDet/gui/KVDetectorBrowser.cpp'
--- KVMultiDet/gui/KVDetectorBrowser.cpp 2009-01-22 15:03:32 +0000
+++ KVMultiDet/gui/KVDetectorBrowser.cpp 2011-03-14 15:58:00 +0000
@@ -29,11 +29,11 @@
widg->SetWidget(fCombo);
AddToWidgetList(widg);
// fill list with all available materials
- KVList *mat_list = fDet->GetListOfMaterials();
+ TObjArray *mat_list = fDet->GetRangeTable()->GetListOfMaterials();
TIter next_mat(mat_list);
- KVMaterial *mat;
+ TNamed *mat;
Int_t i = 0, iselect = -1;
- while ((mat = (KVMaterial *) next_mat())) {
+ while ((mat = (TNamed *) next_mat())) {
if (!strcmp(mat->GetName(), fDet->GetMaterialName()))
iselect = i;
fCombo->AddEntry(mat->GetName(), i++);
=== modified file 'KVMultiDet/idmaps/KVIDZAGrid.cpp'
--- KVMultiDet/idmaps/KVIDZAGrid.cpp 2011-02-23 16:30:57 +0000
+++ KVMultiDet/idmaps/KVIDZAGrid.cpp 2011-03-14 15:58:00 +0000
@@ -1464,8 +1464,8 @@
Double_t E1, E2;
//find E1
- //go from 0.1 MeV to dE->GetBraggE(part.GetZ(),part.GetA()))
- Double_t E1min = 0.1, E1max = dEDet->GetBraggE(part.GetZ(),part.GetA());
+ //go from 0.1 MeV to dE->GetEIncOfMaxDeltaE(part.GetZ(),part.GetA()))
+ Double_t E1min = 0.1, E1max = dEDet->GetEIncOfMaxDeltaE(part.GetZ(),part.GetA());
E1 = (E1min + E1max) / 2.;
while ((E1max - E1min) > 0.1)
@@ -1515,6 +1515,7 @@
E2 = (E2max + E2min) / 2.;
}
}
+<<<<<<< TREE
Info("MakeEDeltaEZGrid","Z= %d, E2=%lf",z,E2);
@@ -1527,6 +1528,9 @@
E2 = dEDet->GetEmaxVedaloss(z)*part.GetA();
}
+=======
+
+>>>>>>> MERGE-SOURCE
KVIDentifier *line = NewLine("ID");
Add("ID", line);
line->SetZ(z);
=== modified file 'KVMultiDet/idtelescopes/KVIDTelescope.cpp'
--- KVMultiDet/idtelescopes/KVIDTelescope.cpp 2011-01-20 13:05:37 +0000
+++ KVMultiDet/idtelescopes/KVIDTelescope.cpp 2011-03-14 15:58:00 +0000
@@ -674,6 +674,7 @@
if( e1< 0.0 ) e1 = 0.0;
else{
d1->SetEnergyLoss(e1);
+ d1->SetEResAfterDetector(e2);
e1 = d1->GetCorrectedEnergy(z,a);
//status code
fCalibStatus = kCalibStatus_Calculated;
@@ -706,7 +707,9 @@
else if(d2){//2nd detector is calibrated too: get corrected energy loss
e2 = d2->GetCorrectedEnergy(z, a, -1, kFALSE);//N.B.: transmission=kFALSE because particle assumed to stop in d2
-
+ // recalculate corrected energy in first stage using info on Eres
+ d1->SetEResAfterDetector(e2);
+ e1 = d1->GetCorrectedEnergy(z, a);
}
//incident energy of particle (before 1st member of telescope)
@@ -736,6 +739,7 @@
//significantly larger, there may be a second particle.
e1 = det->GetDeltaEFromERes(z,a,einc);
if( e1< 0.0 ) e1 = 0.0;
+ det->SetEResAfterDetector(einc);
dE = det->GetCorrectedEnergy(z,a);
einc += dE;
}
@@ -763,6 +767,7 @@
//status code
fCalibStatus = kCalibStatus_Calculated;
}
+ det->SetEResAfterDetector(einc);
e1 = det->GetCorrectedEnergy(z,a,e1);
einc += e1;
}
@@ -840,8 +845,8 @@
Double_t E1, E2;
//find E1
- //go from 0.1 MeV to chio->GetBraggE(part.GetZ(),part.GetA()))
- Double_t E1min = 0.1, E1max = det_de->GetBraggE(zzz,aaa);
+ //go from 0.1 MeV to chio->GetEIncOfMaxDeltaE(part.GetZ(),part.GetA()))
+ Double_t E1min = 0.1, E1max = det_de->GetEIncOfMaxDeltaE(zzz,aaa);
E1 = (E1min + E1max) / 2.;
while ((E1max - E1min) > 0.1) {
@@ -864,8 +869,8 @@
}
//add point to Bragg line
- Double_t dE_B = det_de->GetBraggDE(zzz, aaa);
- Double_t E_B = det_de->GetBraggE(zzz, aaa);
+ Double_t dE_B = det_de->GetMaxDeltaE(zzz, aaa);
+ Double_t E_B = det_de->GetEIncOfMaxDeltaE(zzz, aaa);
Double_t Eres_B = det_de->GetERes(zzz, aaa, E_B);
B_line->SetPoint(npoi_bragg++, Eres_B, dE_B);
=== added directory 'KVMultiDet/stopping'
=== added file 'KVMultiDet/stopping/KVIonRangeTable.cpp'
--- KVMultiDet/stopping/KVIonRangeTable.cpp 1970-01-01 00:00:00 +0000
+++ KVMultiDet/stopping/KVIonRangeTable.cpp 2011-03-14 15:58:00 +0000
@@ -0,0 +1,41 @@
+//Created by KVClassFactory on Thu Feb 3 10:04:41 2011
+//Author: frankland,,,,
+
+#include "KVIonRangeTable.h"
+#include <TPluginManager.h>
+#include <TError.h>
+
+ClassImp(KVIonRangeTable)
+
+////////////////////////////////////////////////////////////////////////////////
+// BEGIN_HTML <!--
+/* -->
+<h2>KVIonRangeTable</h2>
+<h4>Abstract base class for calculation of range & energy loss of charged particles in matter</h4>
+<!-- */
+// --> END_HTML
+////////////////////////////////////////////////////////////////////////////////
+
+KVIonRangeTable::KVIonRangeTable()
+{
+ // Default constructor
+}
+
+KVIonRangeTable::~KVIonRangeTable()
+{
+ // Destructor
+}
+
+KVIonRangeTable* KVIonRangeTable::GetRangeTable(const Char_t* name)
+{
+ // Generates an instance of the KVIonRangeTable plugin class corresponding to given name.
+
+ TPluginHandler *ph;
+ //check and load plugin library
+ if (!(ph = LoadPlugin("KVIonRangeTable", name))) {
+ ::Error("KVIonRangeTable::GetRangeTable", "No plugin for KVIonRangeTable with name=%s found in .kvrootrc", name);
+ return 0;
+ }
+ KVIonRangeTable *irt = (KVIonRangeTable *) ph->ExecPlugin(0);
+ return irt;
+}
=== added file 'KVMultiDet/stopping/KVIonRangeTable.h'
--- KVMultiDet/stopping/KVIonRangeTable.h 1970-01-01 00:00:00 +0000
+++ KVMultiDet/stopping/KVIonRangeTable.h 2011-03-14 15:58:00 +0000
@@ -0,0 +1,102 @@
+//Created by KVClassFactory on Thu Feb 3 10:04:41 2011
+//Author: frankland,,,,
+
+#ifndef KVIONRANGETABLE_H
+#define KVIONRANGETABLE_H
+
+#include "KVBase.h"
+#include "KVUnits.h"
+
+class KVIonRangeTable : public KVBase {
+
+public:
+ enum SolType {
+ kEmax,
+ kEmin
+ };
+
+ KVIonRangeTable();
+ virtual ~KVIonRangeTable();
+
+ static KVIonRangeTable* GetRangeTable(const Char_t* name);
+
+ // Create and fill a list of all materials for which range tables exist.
+ // Each entry is a TNamed with the name and type (title) of the material.
+ virtual TObjArray* GetListOfMaterials() = 0;
+
+ // Return maximum incident energy (in MeV) for which range table is valid for given
+ // material and (Z,A) of incident ion
+ virtual Double_t GetEmaxValid(const Char_t* material, Int_t Z, Int_t A) = 0;
+
+ // Returns density (g/cm**3) of a material in the range tables
+ virtual Double_t GetDensity(const Char_t*) = 0;
+
+ // Set temperature (in degrees celsius) and pressure (in torr) for a given material.
+ // This usually has no effect except for gaseous materials, for which T & P determine the density (in g/cm**3).
+ virtual void SetTemperatureAndPressure(const Char_t*, Double_t temperature, Double_t pressure) = 0;
+
+ // Returns atomic number of a material in the range tables
+ virtual Double_t GetZ(const Char_t*) = 0;
+
+ // Returns atomic mass of a material in the range tables
+ virtual Double_t GetAtomicMass(const Char_t*) = 0;
+
+ // Return kTRUE if material is in range tables
+ virtual Bool_t IsMaterialKnown(const Char_t*) = 0;
+
+ // Return kTRUE if material is gaseous
+ virtual Bool_t IsMaterialGas(const Char_t*) = 0;
+
+ // Return name of material of given type or name if it is in range tables
+ virtual const Char_t* GetMaterialName(const Char_t*) = 0;
+
+ // Returns range (in mg/cm**2) of ion (Z,A) with energy E (MeV) in material.
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ virtual Double_t GetRangeOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.) = 0;
+
+ // Returns linear range (in cm) of ion (Z,A) with energy E (MeV) in material.
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ virtual Double_t GetLinearRangeOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.) = 0;
+
+ // Returns energy lost (in MeV) by ion (Z,A) with energy E (MeV) after thickness r (in mg/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ virtual Double_t GetDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t r,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.) = 0;
+
+ // Returns energy lost (in MeV) by ion (Z,A) with energy E (MeV) after thickness d (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ virtual Double_t GetLinearDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t d,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.) = 0;
+
+ virtual Double_t GetEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t r,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.)=0;
+ virtual Double_t GetLinearEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t d,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.)=0;
+
+ virtual Double_t GetEIncFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.)=0;
+ virtual Double_t GetLinearEIncFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.)=0;
+
+ virtual Double_t GetEIncFromDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t DeltaE, Double_t e, enum SolType type = kEmax, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.)=0;
+ virtual Double_t GetLinearEIncFromDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t DeltaE, Double_t e, enum SolType type = kEmax, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.)=0;
+
+ virtual Double_t GetDeltaEFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t ERes, Double_t e, Double_t isoAmat = 0., Double_t T=-1., Double_t P=-1.)=0;
+ virtual Double_t GetLinearDeltaEFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t ERes, Double_t e, Double_t isoAmat = 0., Double_t T=-1., Double_t P=-1.)=0;
+
+ virtual Double_t GetPunchThroughEnergy(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.) =0;
+ virtual Double_t GetLinearPunchThroughEnergy(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.)=0 ;
+
+ virtual Double_t GetMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.) =0;
+ virtual Double_t GetEIncOfMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.) =0;
+ virtual Double_t GetLinearMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.) =0;
+ virtual Double_t GetLinearEIncOfMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.) =0;
+
+ ClassDef(KVIonRangeTable, 1) //Abstract base class for calculation of range & energy loss of charged particles in matter
+};
+
+#endif
=== added file 'KVMultiDet/stopping/KVUnits.cpp'
--- KVMultiDet/stopping/KVUnits.cpp 1970-01-01 00:00:00 +0000
+++ KVMultiDet/stopping/KVUnits.cpp 2011-03-14 15:58:00 +0000
@@ -0,0 +1,63 @@
+#include "KVUnits.h"
+
+NamespaceImp(KVUnits)
+
+////////////////////////////////////////////////////////////////////////////////
+// BEGIN_HTML <!--
+/* -->
+<h2>KVUnits</h2>
+<h4>Standard units of length, mass, and pressure, and their conversion factors</h4>
+<pre><span class="keyword"></span>namespace KVUnits {<br> // lengths<br>const Double_t cm = 1.0;<br>const Double_t um = 1.e-4;<br>const Double_t mm = 1.e-1;<br>const Double_t m = 1.e+2;<br> // masses<br>const Double_t g = 1.0;<br>const Double_t kg = 1.e+3;<br>const Double_t mg = 1.e-3;<br>const Double_t ug = 1.e-6;<br> // pressures<br>const Double_t torr = 1.0;<br>const Double_t atm = 760.;<br>const Double_t Pa = atm/101325.;<br>const Double_t mbar = 100.*Pa;<br>};<br><br></pre>
+This is a set of numerical constants used to define and convert units
+of length, mass, and pressure. The standard unit defined for each
+quantity is as follows:<br>
+<br>
+<div style="margin-left: 40px;">standard mass unit : grammes
+(KVUnits::g)<br>
+standard length unit : centimetres (KVUnits::cm)<br>
+standard pressure unit : torr (KVUnits::torr)<br>
+</div>
+<br>
+The value of the corresponding numerical constant for each of the
+standard units is 1. The other available units <br>
+are:<br>
+<br>
+<div style="margin-left: 40px;">mass units: microgramme (KVUnits::ug),
+milligramme (KVUnits::mg), kilogramme (KVUnits::kg)<br>
+length units: micron/micrometre (KVUnits::um), millimetre
+(KVUnits::mm), metre (KVUnits::m)<br>
+pressure units: millibar (KVUnits::mbar), pascal (KVUnits::Pa),
+atmosphere (KVUnits::atm)<br>
+</div>
+<h4>Unit conversion</h4>
+If x is a quantity expressed in terms of one of the standard units, the
+corresponding quantity in terms of a different unit is obtained by
+dividing x by the appropriate numerical constant:<br>
+<br>
+<div style="margin-left: 40px;">x = pressure in torr:
+(x/KVUnits::mbar) is pressure in millibar;<br>
+x = mass in grammes: (x/KVUnits::mg) is mass in milligrammes;<br>
+x = length in centimetres: (x/KVUnits::um) is length in
+microns/micrometres.<br>
+</div>
+<br>
+On the other hand, if x is a quantity expressed in arbitrary units,
+then in order to express it in terms of standard units multiply x by
+the appropriate numerical constant:<br>
+<br>
+<div style="margin-left: 40px;">x = pressure in atmospheres:
+(x*KVUnits::atm) is pressure in torr;<br>
+x = mass in microgrammes: (x*KVUnits::ug) is mass in grammes;<br>
+x = length in millimetres: (x*KVUnits::mm) is length in centimetres.<br>
+</div>
+<h4>Composite units</h4>
+Similar conversions can be achieved by combinations of numerical
+constants. For example, if x is a density expressed in kilogrammes per
+cubic metre, the corresponding density in standard units (g/cm**3) is<br>
+<br>
+<div style="margin-left: 40px;">x*KVUnits::kg/pow(KVUnits::m, 3)<br>
+</div><!-- */
+// --> END_HTML
+////////////////////////////////////////////////////////////////////////////////
+
+
=== added file 'KVMultiDet/stopping/KVUnits.h'
--- KVMultiDet/stopping/KVUnits.h 1970-01-01 00:00:00 +0000
+++ KVMultiDet/stopping/KVUnits.h 2011-03-14 15:58:00 +0000
@@ -0,0 +1,29 @@
+#ifndef KVUNITS__H
+#define KVUNITS__H
+
+#include <Rtypes.h>
+
+namespace KVUnits {
+ // UNITS
+ // Standard units are:
+ // [L] cm
+ // [M] g
+ // [P] Torr
+ // lengths
+const long double cm = 1.0l;
+const long double um = 1.e-4l;
+const long double mm = 1.e-1l;
+const long double m = 1.e+2l;
+ // masses
+const long double g = 1.0l;
+const long double kg = 1.e+3l;
+const long double mg = 1.e-3l;
+const long double ug = 1.e-6l;
+ // pressures
+const long double torr = 1.0l;
+const long double atm = 760.l;
+const long double Pa = atm/101325.l;
+const long double mbar = 100.l*Pa;
+};
+
+#endif
=== added file 'KVMultiDet/stopping/KVedaLoss.cpp'
--- KVMultiDet/stopping/KVedaLoss.cpp 1970-01-01 00:00:00 +0000
+++ KVMultiDet/stopping/KVedaLoss.cpp 2011-03-14 15:58:00 +0000
@@ -0,0 +1,434 @@
+//Created by KVClassFactory on Wed Feb 2 15:49:27 2011
+//Author: frankland,,,,
+
+#include "KVedaLoss.h"
+#include "KVedaLossMaterial.h"
+#include <TString.h>
+#include <TSystem.h>
+#include <TEnv.h>
+
+#define FIND_MAT_AND_EXEC(method,defval) \
+ KVedaLossMaterial* M = GetMaterial(mat); \
+ if(M) return M->method; \
+ return defval
+
+ClassImp(KVedaLoss)
+
+////////////////////////////////////////////////////////////////////////////////
+// BEGIN_HTML <!--
+/* -->
+<h2>KVedaLoss</h2>
+<h4>C++ implementation of VEDALOSS stopping power calculation</h4>
+<h3>Credits</h3>
+From the original documentation of vedaloss.f:<br>
+<pre>
+ vedaloss.doc MAJ 5/9/97
+ -------------
+ Routines ecrites par E. de Filippo
+ Mise a jour : 19/12/96 par O. LOPEZ pour UNIX sur ANASTASIE.
+ Mise a jour : 22/05/97 par J-L. Charvet (voir routine DELTA)
+ Mise a jour : 27/10/97 par R. Dayras
+ Mise a jour : 23/03/00 par R. Dayras (ajout Nobium)
+</pre>
+<!-- */
+// --> END_HTML
+////////////////////////////////////////////////////////////////////////////////
+
+KVHashList* KVedaLoss::fMaterials = 0x0;
+
+KVedaLoss::KVedaLoss()
+{
+ // Default constructor
+ SetName("VEDALOSS");
+ SetTitle("Calculation of range and energy loss of charged particles in matter using VEDALOSS range tables");
+ if (!CheckMaterialsList()) {
+ Error("KVedaLoss", "Problem reading range tables. Do not use.");
+ }
+}
+
+KVedaLoss::~KVedaLoss()
+{
+ // Destructor
+}
+
+Bool_t KVedaLoss::init_materials() const
+{
+ // PRIVATE method - called to initialize fMaterials list of all known materials
+ // properties, read from file given by TEnv variable KVedaLoss.RangeTables
+
+ Info("init_materials", "Initialising KVedaLoss...");
+ printf("\n");
+ printf("\t*************************************************************************\n");
+ printf("\t* VEDALOSS STOPPING POWER & RANGE TABLES *\n");
+ printf("\t* *\n");
+ int mat_count = 0;
+ fMaterials = new KVHashList;
+ fMaterials->SetName("VEDALOSS materials list");
+ fMaterials->SetOwner();
+
+ TString DataFilePath = gEnv->GetValue("KVedaLoss.RangeTables", "");
+ gSystem->ExpandPathName(DataFilePath);
+
+ Char_t name[25], gtype[25], state[10];
+ Float_t Amat = 0.;
+ Float_t Dens = 0.;
+ Float_t MoleWt = 0.;
+ Float_t Temp = 19.;
+ Float_t Zmat = 0.;
+
+ FILE *fp;
+ if (!(fp = fopen(DataFilePath.Data(), "r"))) {
+ Error("init_materials()", "Range tables file %s cannot be opened", DataFilePath.Data());
+ return kFALSE;
+ } else {
+ char line[132];
+ while (fgets(line, 132, fp)) { // read lines from file
+
+ switch (line[0]) {
+
+ case '/': // ignore comment lines
+ break;
+
+ case '+': // header lines
+
+ if (sscanf(line, "+ %s %s %s %f %f %f %f %f",
+ gtype, name, state, &Dens, &Zmat, &Amat,
+ &MoleWt, &Temp)
+ != 8) {
+ Error("init_materials()", "Problem reading file %s", DataFilePath.Data());
+ fclose(fp);
+ return kFALSE;
+ }
+//found a new material
+ KVedaLossMaterial *tmp_mat = new KVedaLossMaterial(name, gtype, state, Dens,
+ Zmat, Amat, MoleWt);
+ fMaterials->Add(tmp_mat);
+ if (!tmp_mat->ReadRangeTable(fp)) return kFALSE;
+ ++mat_count;
+ Double_t rho = 0.;
+ if(tmp_mat->IsGas()) tmp_mat->SetTemperatureAndPressure(19., 1.*KVUnits::atm);
+ rho = tmp_mat->GetDensity();
+ printf("\t* %2d. %-7s %-18s Z=%2d A=%5.1f rho=%6.3f g/cm**3 *\n",
+ mat_count, tmp_mat->GetType(), tmp_mat->GetName(),
+ (int)tmp_mat->GetZ(), tmp_mat->GetMass(),
+ rho);
+ break;
+ }
+ }
+ fclose(fp);
+ }
+ printf("\t* *\n");
+ printf("\t* TF1::Range::Npx = %4d TF1::EnergyLoss::Npx = %4d *\n",
+ gEnv->GetValue("KVedaLoss.Range.Npx",100), gEnv->GetValue("KVedaLoss.EnergyLoss.Npx",100));
+ printf("\t* TF1::ResidualEnergy::Npx = %4d *\n",
+ gEnv->GetValue("KVedaLoss.ResidualEnergy.Npx",100));
+ printf("\t* *\n");
+ printf("\t* INITALISATION COMPLETE *\n");
+ printf("\t*************************************************************************\n");
+ return kTRUE;
+}
+
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetAtomicMass(const Char_t* material)
+{
+ // Return atomic mass of a material in the range table.
+ // "material" can be either the type or the name of the material.
+ // Prints a warning and returns 0 if material is unknown.
+
+ KVedaLossMaterial* M = GetMaterial(material);
+ if (!M) {
+ Warning("GetAtomicMass", "Material %s is unknown. Returned mass = 0.", material);
+ return 0.0;
+ }
+ return M->GetMass();
+}
+
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetZ(const Char_t* material)
+{
+ // Return atomic number of a material in the range table.
+ // "material" can be either the type or the name of the material.
+ // Prints a warning and returns 0 if material is unknown.
+
+ KVedaLossMaterial* M = GetMaterial(material);
+ if (!M) {
+ Warning("GetZ", "Material %s is unknown. Returned Z = 0.", material);
+ return 0.0;
+ }
+ return M->GetZ();
+}
+
+//________________________________________________________________________________//
+
+Bool_t KVedaLoss::IsMaterialKnown(const Char_t* material)
+{
+ // Returns kTRUE if material of given name or type is in range table.
+ KVedaLossMaterial* M = GetMaterial(material);
+ return (M != 0x0);
+}
+
+//________________________________________________________________________________//
+
+Bool_t KVedaLoss::IsMaterialGas(const Char_t* mat)
+{
+ // Returns kTRUE if material of given name or type is gaseous.
+ FIND_MAT_AND_EXEC(IsGas(),kFALSE);
+}
+
+//________________________________________________________________________________//
+
+KVedaLossMaterial* KVedaLoss::GetMaterial(const Char_t* material)
+{
+ // Returns pointer to material of given name or type.
+ KVedaLossMaterial* M = (KVedaLossMaterial*)fMaterials->FindObject(material);
+ if (!M) {
+ M = (KVedaLossMaterial*)fMaterials->FindObjectByType(material);
+ }
+ return M;
+}
+
+//________________________________________________________________________________//
+
+const Char_t* KVedaLoss::GetMaterialName(const Char_t* mat)
+{
+ // Return name of material of given type or name if it is in range tables
+ FIND_MAT_AND_EXEC(GetName(),"");
+}
+
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetDensity(const Char_t* mat)
+{
+ // Return density of material (g/cm**3) of given type or name if it is in range tables
+ FIND_MAT_AND_EXEC(GetDensity(),0.0);
+}
+
+//________________________________________________________________________________//
+
+void KVedaLoss::SetTemperatureAndPressure(const Char_t*material, Double_t temperature, Double_t pressure)
+{
+ // Set temperature (in degrees celsius) and pressure (in torr) for a given
+ // material. This has no effect except for gaseous materials, for which T & P
+ // determine the density (in g/cm**3).
+
+ KVedaLossMaterial* M = GetMaterial(material);
+ if (M) M->SetTemperatureAndPressure(temperature, pressure);
+}
+
+//________________________________________________________________________________//
+
+void KVedaLoss::Print(Option_t*) const
+{
+ printf("KVedaLoss::%s\n%s\n", GetName(), GetTitle());
+ printf("\nEnergy loss & range tables loaded for %d materials:\n\n", fMaterials->GetEntries());
+ fMaterials->ls();
+}
+
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetRangeOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E,
+ Double_t Amat, Double_t , Double_t)
+{
+ // Returns range (in g/cm**2) of ion (Z,A) with energy E (MeV) in material.
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ FIND_MAT_AND_EXEC(GetRangeOfIon(Z, A, E, Amat),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetLinearRangeOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E,
+ Double_t Amat, Double_t T, Double_t P)
+{
+ // Returns linear range (in cm) of ion (Z,A) with energy E (MeV) in material.
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ FIND_MAT_AND_EXEC(GetLinearRangeOfIon(Z, A, E, Amat, T, P),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t r,
+ Double_t Amat, Double_t , Double_t )
+{
+ // Returns energy lost (in MeV) by ion (Z,A) with energy E (MeV) after thickness r (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ FIND_MAT_AND_EXEC(GetDeltaEOfIon(Z, A, E, r, Amat),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetLinearDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t d,
+ Double_t Amat, Double_t T, Double_t P)
+{
+ // Returns energy lost (in MeV) by ion (Z,A) with energy E (MeV) after thickness d (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ FIND_MAT_AND_EXEC(GetLinearDeltaEOfIon(Z, A, E, d, Amat, T, P),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t r,
+ Double_t Amat, Double_t , Double_t )
+{
+ // Returns residual energy (in MeV) of ion (Z,A) with incident energy E (MeV) after thickness r (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ FIND_MAT_AND_EXEC(GetEResOfIon(Z, A, E, r, Amat),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetLinearEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t d,
+ Double_t Amat, Double_t T, Double_t P)
+{
+ // Returns residual energy (in MeV) of ion (Z,A) with incident energy E (MeV) after thickness d (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ FIND_MAT_AND_EXEC(GetLinearEResOfIon(Z, A, E, d, Amat, T, P),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetEIncFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat, Double_t , Double_t )
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) with residual energy Eres (MeV) after thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ FIND_MAT_AND_EXEC(GetEIncFromEResOfIon(Z, A, Eres, e, isoAmat),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetLinearEIncFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t Eres, Double_t e,
+ Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) with residual energy Eres (MeV) after thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ FIND_MAT_AND_EXEC(GetLinearEIncFromEResOfIon(Z, A, Eres, e, isoAmat, T, P),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetEIncFromDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t DeltaE, Double_t e, enum KVIonRangeTable::SolType type, Double_t isoAmat, Double_t , Double_t )
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) from energy loss DeltaE (MeV) in thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ FIND_MAT_AND_EXEC(GetEIncFromDeltaEOfIon(Z, A, DeltaE, e, type, isoAmat),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetLinearEIncFromDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t deltaE, Double_t e, enum KVIonRangeTable::SolType type,
+ Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) from energy loss DeltaE (MeV) in thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ FIND_MAT_AND_EXEC(GetLinearEIncFromDeltaEOfIon(Z, A, deltaE, e, type, isoAmat,T,P),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetDeltaEFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat, Double_t , Double_t )
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) from energy loss DeltaE (MeV) in thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ FIND_MAT_AND_EXEC(GetDeltaEFromEResOfIon(Z, A, Eres, e, isoAmat),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetLinearDeltaEFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) from energy loss DeltaE (MeV) in thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ FIND_MAT_AND_EXEC(GetLinearDeltaEFromEResOfIon(Z, A, Eres, e, isoAmat,T,P),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetPunchThroughEnergy(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat, Double_t , Double_t )
+{
+ // Calculate incident energy (in MeV) for ion (Z,A) for which the range is equal to the
+ // given thickness e (in g/cm**2). At this energy the residual energy of the ion is (just) zero,
+ // for all energies above this energy the residual energy is > 0.
+ // Give Amat to change default (isotopic) mass of material.
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ FIND_MAT_AND_EXEC(GetPunchThroughEnergy(Z, A, e, isoAmat),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetLinearPunchThroughEnergy(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculate incident energy (in MeV) for ion (Z,A) for which the range is equal to the
+ // given thickness e (in cm). At this energy the residual energy of the ion is (just) zero,
+ // for all energies above this energy the residual energy is > 0.
+ // Give Amat to change default (isotopic) mass of material.
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ FIND_MAT_AND_EXEC(GetLinearPunchThroughEnergy(Z, A, e, isoAmat,T, P),0.0);
+}
+//________________________________________________________________________________//
+
+Double_t KVedaLoss::GetMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat, Double_t , Double_t )
+{
+ // Calculate maximum energy loss (in MeV) of ion (Z,A) in given thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material.
+ FIND_MAT_AND_EXEC(GetMaxDeltaEOfIon(Z, A, e, isoAmat),0.0);
+}
+
+Double_t KVedaLoss::GetEIncOfMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat, Double_t , Double_t )
+{
+ // Calculate incident energy (in MeV) corresponding to maximum energy loss of ion (Z,A)
+ // in given thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material.
+
+ FIND_MAT_AND_EXEC(GetEIncOfMaxDeltaEOfIon(Z, A, e, isoAmat),0.0);
+}
+
+Double_t KVedaLoss::GetLinearMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculate maximum energy loss (in MeV) of ion (Z,A) in given thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material.
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ FIND_MAT_AND_EXEC(GetLinearMaxDeltaEOfIon(Z, A, e, isoAmat, T, P),0.0);
+}
+
+Double_t KVedaLoss::GetLinearEIncOfMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculate incident energy (in MeV) corresponding to maximum energy loss of ion (Z,A)
+ // in given thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material.
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ FIND_MAT_AND_EXEC(GetLinearEIncOfMaxDeltaEOfIon(Z, A, e, isoAmat, T, P),0.0);
+}
+
+Double_t KVedaLoss::GetEmaxValid(const Char_t* mat, Int_t Z, Int_t A)
+{
+ // Returns maximum energy (in MeV) for which range table is valid
+ // for given material and incident ion (Z,A)
+
+ FIND_MAT_AND_EXEC(GetEmaxValid(Z, A),0.0);
+}
+
+//______________________________________________________________________________________//
+
+TObjArray* KVedaLoss::GetListOfMaterials()
+{
+ // Create and fill a list of all materials for which range tables exist.
+ // Each entry is a TNamed with the name and type (title) of the material.
+ // User's responsibility to delete list after use (it owns its objects).
+
+ if(CheckMaterialsList()){
+ TObjArray* list = new TObjArray(fMaterials->GetEntries());
+ list->SetOwner(kTRUE);
+ TIter next(fMaterials);
+ KVedaLossMaterial* mat;
+ while( (mat = (KVedaLossMaterial*)next()) ){
+ list->Add(new TNamed(mat->GetName(), mat->GetType()));
+ }
+ return list;
+ }
+ return 0;
+}
=== added file 'KVMultiDet/stopping/KVedaLoss.h'
--- KVMultiDet/stopping/KVedaLoss.h 1970-01-01 00:00:00 +0000
+++ KVMultiDet/stopping/KVedaLoss.h 2011-03-14 15:58:00 +0000
@@ -0,0 +1,76 @@
+//Created by KVClassFactory on Wed Feb 2 15:49:27 2011
+//Author: frankland,,,,
+
+#ifndef __KVEDALOSS_H
+#define __KVEDALOSS_H
+
+#include "KVIonRangeTable.h"
+#include "KVHashList.h"
+
+class KVedaLossMaterial;
+
+class KVedaLoss : public KVIonRangeTable {
+ static KVHashList* fMaterials;// static list of all known materials
+
+ Bool_t init_materials() const;
+ Bool_t CheckMaterialsList() const {
+ if (!fMaterials) return init_materials();
+ return kTRUE;
+ };
+
+public:
+ KVedaLoss();
+ virtual ~KVedaLoss();
+
+ Bool_t IsMaterialKnown(const Char_t* material);
+ Bool_t IsMaterialGas(const Char_t* material);
+
+ KVedaLossMaterial* GetMaterial(const Char_t* material);
+ const Char_t* GetMaterialName(const Char_t* material);
+
+ virtual Double_t GetEmaxValid(const Char_t* material, Int_t Z, Int_t A);
+
+ Double_t GetDensity(const Char_t* material);
+ void SetTemperatureAndPressure(const Char_t*material, Double_t temperature, Double_t pressure);
+ Double_t GetZ(const Char_t* material);
+ Double_t GetAtomicMass(const Char_t* material);
+
+ void Print(Option_t* = "") const;
+ TObjArray* GetListOfMaterials();
+
+ virtual Double_t GetRangeOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.);
+ virtual Double_t GetLinearRangeOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.);
+
+ virtual Double_t GetDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t r,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.);
+ virtual Double_t GetLinearDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t d,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.);
+
+ virtual Double_t GetEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t r,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.);
+ virtual Double_t GetLinearEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t E, Double_t d,
+ Double_t Amat=0., Double_t T=-1., Double_t P=-1.);
+
+ virtual Double_t GetEIncFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.);
+ virtual Double_t GetLinearEIncFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.);
+
+ virtual Double_t GetEIncFromDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t DeltaE, Double_t e, enum KVIonRangeTable::SolType type = KVIonRangeTable::kEmax, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.);
+ virtual Double_t GetLinearEIncFromDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t DeltaE, Double_t e, enum KVIonRangeTable::SolType type = KVIonRangeTable::kEmax, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.);
+
+ virtual Double_t GetDeltaEFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t ERes, Double_t e, Double_t isoAmat = 0., Double_t T=-1., Double_t P=-1.);
+ virtual Double_t GetLinearDeltaEFromEResOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t ERes, Double_t e, Double_t isoAmat = 0., Double_t T=-1., Double_t P=-1.);
+
+ virtual Double_t GetPunchThroughEnergy(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.) ;
+ virtual Double_t GetLinearPunchThroughEnergy(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.) ;
+
+ virtual Double_t GetMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.);
+ virtual Double_t GetEIncOfMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.);
+ virtual Double_t GetLinearMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.);
+ virtual Double_t GetLinearEIncOfMaxDeltaEOfIon(const Char_t* mat, Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.);
+
+ ClassDef(KVedaLoss, 1) //C++ implementation of VEDALOSS stopping power calculation
+};
+
+#endif
=== added file 'KVMultiDet/stopping/KVedaLossMaterial.cpp'
--- KVMultiDet/stopping/KVedaLossMaterial.cpp 1970-01-01 00:00:00 +0000
+++ KVMultiDet/stopping/KVedaLossMaterial.cpp 2011-03-14 15:58:00 +0000
@@ -0,0 +1,538 @@
+//Created by KVClassFactory on Wed Feb 2 16:13:08 2011
+//Author: frankland,,,,
+
+#include "KVedaLossMaterial.h"
+#include <TMath.h>
+#include "KVIonRangeTable.h"
+#include <TEnv.h>
+
+ClassImp(KVedaLossMaterial)
+
+////////////////////////////////////////////////////////////////////////////////
+// BEGIN_HTML <!--
+/* -->
+<h2>KVedaLossMaterial</h2>
+<h4>Description of material properties used by KVedaLoss range calculation</h4>
+<!-- */
+// --> END_HTML
+////////////////////////////////////////////////////////////////////////////////
+
+KVedaLossMaterial::KVedaLossMaterial()
+ : fState("unknown"),
+ fDens(0.),
+ fZmat(0),
+ fAmat(0),
+ fMoleWt(0),
+ fRange(0)
+{
+ // Default constructor
+ for (int i = 0; i < 100; i++) {
+ fEmin[i] = 0.0;
+ fEmax[i] = 500.0;
+ }
+}
+
+KVedaLossMaterial::KVedaLossMaterial(const Char_t* name, const Char_t* type, const Char_t* state,
+ Double_t density, Double_t Z, Double_t A, Double_t MoleWt)
+ : fState(state),
+ fDens(density),
+ fZmat(Z),
+ fAmat(A),
+ fMoleWt(MoleWt),
+ fRange(0)
+{
+ // create new material
+ SetName(name);
+ SetType(type);
+ for (int i = 0; i < 100; i++) {
+ fEmin[i] = 0.0;
+ fEmax[i] = 500.0;
+ }
+}
+
+KVedaLossMaterial::~KVedaLossMaterial()
+{
+ // Destructor
+}
+
+Bool_t KVedaLossMaterial::ReadRangeTable(FILE* fp)
+{
+ // Read Z- & A-dependent range parameters for material
+ //
+ // For each material we create 3 TF1 objects:
+ // KVedaLossMaterial:[type]:Range - gives range in g/cm**2 as a function of particle energy
+ // KVedaLossMaterial:[type]:EnergyLoss - gives dE as a function of particle energy
+ // KVedaLossMaterial:[type]:ResidualEnergy - gives energy after material (0 if particle stops)
+ //
+ // The TF1::fNpx parameter for these functions is defined by the environment variables
+ //
+ // KVedaLoss.Range.Npx: 20
+ // KVedaLoss.EnergyLoss.Npx: 50
+ // KVedaLoss.ResidualEnergy.Npx: 20
+ //
+
+ char line[132];
+
+ //look for energy limits to calculation validity
+ if (!fgets(line, 132, fp)) {
+ Warning("ReadRangeTable", "Problem reading energy limits in range table file for %s (%s)",
+ GetName(), GetType());
+ return kFALSE;
+ } else {
+ while (line[0] == 'Z') {
+ Int_t z1, z2;
+ Float_t e1, e2;
+ sscanf(line, "Z = %d,%d %f < E/A < %f MeV", &z1,
+ &z2, &e1, &e2);
+ char* tmp;
+ tmp = fgets(line, 132, fp);
+ for (int i = z1; i <= z2; i++) {
+ fEmin[i - 1] = e1;
+ fEmax[i - 1] = e2;
+ }
+ }
+ }
+
+ for (register int count = 0; count < ZMAX_VEDALOSS; count++) {
+
+ if (sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf",
+ &fCoeff[count][0], &fCoeff[count][1],
+ &fCoeff[count][2], &fCoeff[count][3],
+ &fCoeff[count][4], &fCoeff[count][5],
+ &fCoeff[count][6], &fCoeff[count][7])
+ != 8) {
+ Error("ReadRangeTable", "problem reading coeffs 0-7 in range table for %s (%s)", GetName(), GetType());
+ return kFALSE;
+ }
+ if (!fgets(line, 132, fp)) {
+ Warning("ReadRangeTable", "file too short ??? %s (%s)", GetName(), GetType());
+ return kFALSE;
+ } else {
+ if (sscanf(line, "%lf %lf %lf %lf %lf %lf",
+ &fCoeff[count][8], &fCoeff[count][9],
+ &fCoeff[count][10], &fCoeff[count][11],
+ &fCoeff[count][12], &fCoeff[count][13])
+ != 6) {
+ Error("ReadRangeTable", "problem reading coeffs 8-13 in range table for %s (%s)", GetName(), GetType());
+ return kFALSE;
+ }
+ }
+ char* tmp;
+ tmp = fgets(line, 132, fp);
+ }
+
+ // get require Npx value from (user-defined) environment variables
+ Int_t my_npx = gEnv->GetValue("KVedaLoss.Range.Npx", 100);
+
+ fRange = new TF1(Form("KVedaLossMaterial:%s:Range", GetType()), this, &KVedaLossMaterial::RangeFunc,
+ 0., 1.e+03, 3, "KVedaLossMaterial", "RangeFunc");
+ fRange->SetNpx(my_npx);
+
+ my_npx = gEnv->GetValue("KVedaLoss.EnergyLoss.Npx", 100);
+ fDeltaE = new TF1(Form("KVedaLossMaterial:%s:EnergyLoss", GetType()), this, &KVedaLossMaterial::DeltaEFunc,
+ 0., 1.e+03, 4, "KVedaLossMaterial", "DeltaEFunc");
+ fDeltaE->SetNpx(my_npx);
+
+ my_npx = gEnv->GetValue("KVedaLoss.ResidualEnergy.Npx", 100);
+ fEres = new TF1(Form("KVedaLossMaterial:%s:ResidualEnergy", GetType()), this, &KVedaLossMaterial::EResFunc,
+ 0., 1.e+03, 4, "KVedaLossMaterial", "EResFunc");
+ fEres->SetNpx(my_npx);
+
+ return kTRUE;
+}
+
+void KVedaLossMaterial::ls(Option_t*) const
+{
+ printf("KVedaLossMaterial::%s Material type : %s State : %s\n", GetName(), GetType(), fState.Data());
+ printf("\tZ=%f A=%f ", fZmat, fAmat);
+ if (IsGas()) printf(" Mole Weight = %f g.", fMoleWt);
+ if (fDens > 0) printf(" Density = %f g/cm**3", fDens);
+ printf("\n\n");
+}
+
+Double_t KVedaLossMaterial::DeltaEFunc(Double_t* E, Double_t* Mypar)
+{
+ // Function parameterising the energy loss of charged particles in this material.
+ // The incident energy E[0] is given in MeV.
+ // The energy loss is calculated in MeV.
+ //
+ //Parameters:
+ // Mypar[0] = thickness of material in g/cm**2
+ // Mypar[1] = Z of charged particle
+ // Mypar[2] = A of charged particle
+ // Mypar[3] = isotope of material element (0 if material is isotopically pure)
+
+ // if range < thickness, particle stops: dE = E0
+ Double_t R0 = RangeFunc(E, &Mypar[1]);
+ if (R0 < Mypar[0]) {
+ return E[0];
+ }
+
+ // calculate energy loss - invert range function to find E corresponding to (R0 - thickness)
+ R0 -= Mypar[0];
+
+ // invert range function to get energy after absorber
+ Double_t dE = E[0] - fRange->GetX(R0);
+ return dE;
+ /*
+ // VEDALOSS inversion of R(E)
+ // range in mg/cm**2 for VEDALOSS
+ R0 /= (KVUnits::mg / pow(KVUnits::cm,2));
+ // get parameters for this Z
+ Int_t Z = (Int_t)Mypar[1];
+ Double_t A = Mypar[2];
+ Double_t *par = fCoeff[Z - 1];
+ Double_t ranx = TMath::Log(R0);
+ Double_t ranx1 = ranx - riso;
+ Double_t depsx;
+ if (ranx1 < arm)
+ depsx = (ranx1 - adn) / adm;
+ else {
+ depsx = 0.0;
+ for (register int j = 2; j < 7; j++)
+ depsx += par[j + 7] * TMath::Power(ranx1, (Double_t) (j - 1));
+ depsx += par[8];
+ }
+
+ const Double_t PERC = 0.02;
+
+ Double_t eps1 = depsx + TMath::Log(1 - PERC);
+ Double_t eps2 = depsx + TMath::Log(1 + PERC);
+ Double_t rap = TMath::Log((1 + PERC) / (1 - PERC));
+
+ Double_t rn1 = 0.0;
+ if (TMath::Exp(eps1) < 0.1)
+ rn1 = adm * eps1 + adn;
+ else {
+ for (register int j = 1; j < 7; j++)
+ rn1 += par[j + 1] * TMath::Power(eps1, (Double_t) (j - 1));
+ }
+ Double_t rn2 = 0.0;
+ if (TMath::Exp(eps2) < 0.1)
+ rn2 = adm * eps2 + adn;
+ else {
+ for (register int j = 1; j < 7; j++)
+ rn2 += par[j + 1] * TMath::Power(eps2, (Double_t) (j - 1));
+ }
+
+ Double_t epres = eps1 + (rap / (rn2 - rn1)) * (ranx1 - rn1);
+ epres = TMath::Exp(epres);
+ Double_t eres = A * epres;
+
+ // garde-fou - calculated energy after absorber > incident energy ?!!
+ //if(eres > E[0]) return 0.0;
+ return E[0] - eres;
+ */
+}
+
+Double_t KVedaLossMaterial::EResFunc(Double_t* E, Double_t* Mypar)
+{
+ // Function parameterising the residual energy of charged particles in this material.
+ // The incident energy E[0] is given in MeV.
+ // The residual energy is calculated in MeV.
+ //
+ //Parameters:
+ // Mypar[0] = thickness of material in g/cm**2
+ // Mypar[1] = Z of charged particle
+ // Mypar[2] = A of charged particle
+ // Mypar[3] = isotope of material element (0 if material is isotopically pure)
+
+ // if range < thickness, particle stops: Eres=0
+ Double_t R0 = RangeFunc(E, &Mypar[1]);
+ if (R0 < Mypar[0]) {
+ return 0.0;
+ }
+
+ // calculate energy after absorber - invert range function to find Eres corresponding to (R0 - thickness)
+ R0 -= Mypar[0];
+
+ // invert range function to get energy after absorber
+ return fRange->GetX(R0);
+}
+
+Double_t KVedaLossMaterial::RangeFunc(Double_t* E, Double_t* Mypar)
+{
+ // Function parameterising the range of charged particles in this material.
+ // The energy E[0] is given in MeV.
+ // The range is calculated in units of g/cm**2
+ //
+ //Parameters:
+ // Mypar[0] = Z of charged particle
+ // Mypar[1] = A of charged particle
+ // Mypar[2] = isotope of material element (0 if material is not isotopically pure)
+
+ Int_t Z = (Int_t)Mypar[0];
+ Double_t A = Mypar[1];
+ // get parameters for this Z
+ Double_t *par = fCoeff[Z - 1];
+
+ // set up polynomial
+ Double_t x1 = TMath::Log(0.1);
+ Double_t x2 = TMath::Log(0.2);
+ Double_t ran = 0.0;
+ for (register int j = 2; j < 7; j++)
+ ran += par[j + 1] * TMath::Power(x2, (Double_t)(j - 1));
+ ran += par[2];
+ Double_t y2 = ran;
+ ran = 0.0;
+ for (register int jj = 2; jj < 7; jj++)
+ ran += par[jj + 1] * TMath::Power(x1, (Double_t)(jj - 1));
+ ran += par[2];
+ Double_t y1 = ran;
+ Double_t adm = (y2 - y1) / (x2 - x1);
+ Double_t adn = (y1 - adm * x1);
+ // calculate energy loss
+ Double_t eps = E[0] / A; //energy in MeV/nucleon
+ Double_t dleps = TMath::Log(eps);
+ Double_t MatIsoR = 0.;
+ if (Mypar[2] > 0.0) MatIsoR = TMath::Log(Mypar[2] / fAmat);
+ Double_t riso = TMath::Log(A / par[1]) + MatIsoR;
+
+ if (eps < 0.1)
+ ran = adm * dleps + adn;
+ else {
+ ran = 0.0;
+ for (register int j = 2; j < 7; j++)
+ ran += par[j + 1] * TMath::Power(dleps, (Double_t)(j - 1));
+ ran += par[2];
+ }
+ ran += riso;
+
+ // range in g/cm**2
+ Double_t range = TMath::Exp(ran) * KVUnits::mg / pow(KVUnits::cm, 2);
+ return range;
+}
+
+TF1* KVedaLossMaterial::GetRangeFunction(Int_t Z, Int_t A, Double_t isoAmat)
+{
+ // Return function giving range (in centimetres) as a function of energy (in MeV) for
+ // charged particles (Z,A) in this material.
+ // If required, the isotopic mass of the material can be given.
+
+ fRange->SetParameters(Z, A, isoAmat);
+ fRange->SetRange(0., GetEmaxValid(Z,A));
+ return fRange;
+}
+
+TF1* KVedaLossMaterial::GetDeltaEFunction(Double_t e, Int_t Z, Int_t A, Double_t isoAmat)
+{
+ // Return function giving energy loss (in MeV) as a function of incident energy (in MeV) for
+ // charged particles (Z,A) traversing (or not) the thickness e (in g/cm**2) of this material.
+ // If required, the isotopic mass of the material can be given.
+
+ GetRangeFunction(Z, A, isoAmat);
+ fDeltaE->SetParameters(e, Z, A, isoAmat);
+ fDeltaE->SetRange(0., GetEmaxValid(Z,A));
+ return fDeltaE;
+}
+
+TF1* KVedaLossMaterial::GetEResFunction(Double_t e, Int_t Z, Int_t A, Double_t isoAmat)
+{
+ // Return function giving residual energy (in MeV) as a function of incident energy (in MeV) for
+ // charged particles (Z,A) traversing (or not) the thickness e (in g/cm**2) of this material.
+ // If required, the isotopic mass of the material can be given.
+
+ GetRangeFunction(Z, A, isoAmat);
+ fEres->SetParameters(e, Z, A, isoAmat);
+ fEres->SetRange(0., GetEmaxValid(Z,A));
+ return fEres;
+}
+
+void KVedaLossMaterial::PrintRangeTable(Int_t Z, Int_t A, Double_t isoAmat, Double_t units, Double_t T, Double_t P)
+{
+ // Print range of element (in g/cm**2) as a function of incident energy (in MeV).
+ // For solid elements, print also the linear range (in cm). To change the default units,
+ // set optional argument units (e.g. to have linear range in microns, call with units = KVUnits::um).
+ // For gaseous elements, give the temperature (in degrees) and the pressure (in torr)
+ // in order to print the range in terms of length units.
+
+ fRange->SetParameters(Z, A, isoAmat);
+ printf(" **** VEDALOSS Range Table ****\n\n");
+ ls();
+ printf(" Element: Z=%d A=%d\n\n", Z, A);
+ printf("\tENERGY (MeV)\t\tRANGE (g/cm**2)");
+ if (!IsGas() || (IsGas() && T > 0 && P > 0)) printf("\t\tLIN. RANGE");
+ SetTemperatureAndPressure(T, P);
+ printf("\n\n");
+ for (Double_t e = 0.1; e <= 1.e+4; e *= 10) {
+ printf("\t%10.5g\t\t%10.5g", e, fRange->Eval(e));
+ if (!IsGas() || (IsGas() && T > 0 && P > 0)) printf("\t\t\t%10.5g", fRange->Eval(e) / GetDensity() / units);
+ printf("\n");
+ }
+}
+
+Double_t KVedaLossMaterial::GetRangeOfIon(Int_t Z, Int_t A, Double_t E, Double_t isoAmat)
+{
+ // Returns range (in g/cm**2) of ion (Z,A) with energy E (MeV) in material.
+ // Give Amat to change default (isotopic) mass of material,
+ TF1* f = GetRangeFunction(Z, A, isoAmat);
+ return f->Eval(E);
+}
+
+Double_t KVedaLossMaterial::GetLinearRangeOfIon(Int_t Z, Int_t A, Double_t E, Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Returns range (in cm) of ion (Z,A) with energy E (MeV) in material.
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ SetTemperatureAndPressure(T, P);
+ if (fDens > 0) return GetRangeOfIon(Z, A, E, isoAmat) / GetDensity();
+ else return 0.;
+}
+
+Double_t KVedaLossMaterial::GetDeltaEOfIon(Int_t Z, Int_t A, Double_t E, Double_t e, Double_t isoAmat)
+{
+ // Returns energy lost (in MeV) by ion (Z,A) with energy E (MeV) after thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+
+ TF1* f = GetDeltaEFunction(e, Z, A, isoAmat);
+ return f->Eval(E);
+}
+
+Double_t KVedaLossMaterial::GetLinearDeltaEOfIon(Int_t Z, Int_t A, Double_t E, Double_t e,
+ Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Returns energy lost (in MeV) by ion (Z,A) with energy E (MeV) after thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ SetTemperatureAndPressure(T, P);
+ e *= GetDensity();
+ return GetDeltaEOfIon(Z, A, E, e, isoAmat);
+}
+
+Double_t KVedaLossMaterial::GetEResOfIon(Int_t Z, Int_t A, Double_t E, Double_t e,
+ Double_t isoAmat)
+{
+ // Returns energy lost (in MeV) by ion (Z,A) with energy E (MeV) after thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ TF1* f = GetEResFunction(e, Z, A, isoAmat);
+ return f->Eval(E);
+}
+
+Double_t KVedaLossMaterial::GetLinearEResOfIon(Int_t Z, Int_t A, Double_t E, Double_t e,
+ Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Returns energy lost (in MeV) by ion (Z,A) with energy E (MeV) after thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ SetTemperatureAndPressure(T, P);
+ e *= GetDensity();
+ return GetEResOfIon(Z, A, E, e, isoAmat);
+}
+
+Double_t KVedaLossMaterial::GetEIncFromEResOfIon(Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat)
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) with residual energy Eres (MeV) after thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ GetRangeFunction(Z, A, isoAmat);
+ Double_t R0 = fRange->Eval(Eres) + e;
+ return fRange->GetX(R0);
+}
+
+Double_t KVedaLossMaterial::GetLinearEIncFromEResOfIon(Int_t Z, Int_t A, Double_t Eres, Double_t e,
+ Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) with residual energy Eres (MeV) after thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ SetTemperatureAndPressure(T, P);
+ e *= GetDensity();
+ return GetEIncFromEResOfIon(Z, A, Eres, e, isoAmat);
+}
+
+Double_t KVedaLossMaterial::GetEIncFromDeltaEOfIon(Int_t Z, Int_t A, Double_t DeltaE, Double_t e, enum KVIonRangeTable::SolType type, Double_t isoAmat)
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) from energy loss DeltaE (MeV) in thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ GetDeltaEFunction(e, Z, A, isoAmat);
+ Double_t e1,e2;
+ fDeltaE->GetRange(e1,e2);
+ switch(type){
+ case KVIonRangeTable::kEmin:
+ e2=GetEIncOfMaxDeltaEOfIon(Z,A,e,isoAmat);
+ break;
+ case KVIonRangeTable::kEmax:
+ e1=GetEIncOfMaxDeltaEOfIon(Z,A,e,isoAmat);
+ break;
+ }
+ return fDeltaE->GetX(DeltaE,e1,e2);
+}
+
+Double_t KVedaLossMaterial::GetLinearEIncFromDeltaEOfIon(Int_t Z, Int_t A, Double_t deltaE, Double_t e, enum KVIonRangeTable::SolType type,
+ Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculates incident energy (in MeV) of an ion (Z,A) from energy loss DeltaE (MeV) in thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ SetTemperatureAndPressure(T, P);
+ e *= GetDensity();
+ return GetEIncFromDeltaEOfIon(Z, A, deltaE, e, type, isoAmat);
+}
+
+Double_t KVedaLossMaterial::GetPunchThroughEnergy(Int_t Z, Int_t A, Double_t e, Double_t isoAmat)
+{
+ // Calculate incident energy (in MeV) for ion (Z,A) for which the range is equal to the
+ // given thickness e (in g/cm**2). At this energy the residual energy of the ion is (just) zero,
+ // for all energies above this energy the residual energy is > 0.
+ // Give Amat to change default (isotopic) mass of material.
+
+ return GetRangeFunction(Z,A,isoAmat)->GetX(e);
+}
+
+Double_t KVedaLossMaterial::GetLinearPunchThroughEnergy(Int_t Z, Int_t A, Double_t e, Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculate incident energy (in MeV) for ion (Z,A) for which the range is equal to the
+ // given thickness e (in cm). At this energy the residual energy of the ion is (just) zero,
+ // for all energies above this energy the residual energy is > 0.
+ // Give Amat to change default (isotopic) mass of material.
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ SetTemperatureAndPressure(T, P);
+ e *= GetDensity();
+ return GetPunchThroughEnergy(Z,A,e,isoAmat);
+}
+
+Double_t KVedaLossMaterial::GetMaxDeltaEOfIon(Int_t Z, Int_t A, Double_t e, Double_t isoAmat)
+{
+ // Calculate maximum energy loss (in MeV) of ion (Z,A) in given thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material.
+
+ return GetDeltaEFunction(e,Z,A,isoAmat)->GetMaximum();
+}
+
+Double_t KVedaLossMaterial::GetEIncOfMaxDeltaEOfIon(Int_t Z, Int_t A, Double_t e, Double_t isoAmat)
+{
+ // Calculate incident energy (in MeV) corresponding to maximum energy loss of ion (Z,A)
+ // in given thickness e (in g/cm**2).
+ // Give Amat to change default (isotopic) mass of material.
+
+ return GetDeltaEFunction(e,Z,A,isoAmat)->GetMaximumX();
+}
+
+Double_t KVedaLossMaterial::GetLinearMaxDeltaEOfIon(Int_t Z, Int_t A, Double_t e, Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculate maximum energy loss (in MeV) of ion (Z,A) in given thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material.
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ SetTemperatureAndPressure(T, P);
+ e *= GetDensity();
+ return GetMaxDeltaEOfIon(Z,A,e,isoAmat);
+}
+
+Double_t KVedaLossMaterial::GetLinearEIncOfMaxDeltaEOfIon(Int_t Z, Int_t A, Double_t e, Double_t isoAmat, Double_t T, Double_t P)
+{
+ // Calculate incident energy (in MeV) corresponding to maximum energy loss of ion (Z,A)
+ // in given thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material.
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+
+ SetTemperatureAndPressure(T, P);
+ e *= GetDensity();
+ return GetEIncOfMaxDeltaEOfIon(Z,A,e,isoAmat);
+}
+
=== added file 'KVMultiDet/stopping/KVedaLossMaterial.h'
--- KVMultiDet/stopping/KVedaLossMaterial.h 1970-01-01 00:00:00 +0000
+++ KVMultiDet/stopping/KVedaLossMaterial.h 2011-03-14 15:58:00 +0000
@@ -0,0 +1,125 @@
+//Created by KVClassFactory on Wed Feb 2 16:13:08 2011
+//Author: frankland,,,,
+
+#ifndef __KVEDALOSSMATERIAL_H
+#define __KVEDALOSSMATERIAL_H
+
+#include "KVBase.h"
+#include <TString.h>
+#include <Riostream.h>
+#include <TF1.h>
+#include "KVIonRangeTable.h"
+
+// maximum atomic number included in range tables
+#define ZMAX_VEDALOSS 100
+#define RTT 62.36367e+03 // cm^3.Torr.K^-1.mol^-1
+#define ZERO_KELVIN 273.15
+
+class KVedaLossMaterial : public KVBase {
+
+protected:
+ TString fState; // state of material = "solid", "liquid", "gas", "unknown"
+ Double_t fDens; // density of material in g/cm**3
+ Double_t fZmat; // atomic number of material
+ Double_t fAmat; // atomic mass of material
+ Double_t fMoleWt; // only used for gases - mass of one mole of gas in grammes
+ Double_t fEmax[ZMAX_VEDALOSS]; //[ZMAX_VEDALOSS] Z-dependent maximum energy/nucleon for calculation to be valid
+ Double_t fEmin[ZMAX_VEDALOSS]; //[ZMAX_VEDALOSS] Z-dependent minimum energy/nucleon for calculation to be valid
+ Double_t fCoeff[ZMAX_VEDALOSS][14]; //[ZMAX_VEDALOSS][14] parameters for range tables
+
+ TF1* fDeltaE; // function parameterising energy loss in material
+ TF1* fEres; // function parameterising residual energy after crossing material
+ TF1* fRange; // function parameterising range of charged particles in material
+
+ Double_t DeltaEFunc(Double_t*, Double_t*);
+ Double_t EResFunc(Double_t*, Double_t*);
+ Double_t RangeFunc(Double_t*, Double_t*);
+
+public:
+ KVedaLossMaterial();
+ KVedaLossMaterial(const Char_t* name, const Char_t* type, const Char_t* state,
+ Double_t density, Double_t Z, Double_t A, Double_t MoleWt = 0.0);
+ virtual ~KVedaLossMaterial();
+
+ Bool_t ReadRangeTable(FILE* fp);
+ Float_t GetEmaxValid(Int_t Z, Int_t A) const {
+ return ((Z <= ZMAX_VEDALOSS && Z > 0) ? A*fEmax[Z - 1] : 0.0);
+ };
+ Float_t GetEminValid(Int_t Z, Int_t A) const {
+ return ((Z <= ZMAX_VEDALOSS && Z > 0) ? A*fEmin[Z - 1] : 0.0);
+ };
+ Double_t GetMass() const {
+ return fAmat;
+ };
+ Double_t GetZ() const {
+ return fZmat;
+ };
+ Double_t GetDensity() const {
+ // return density of material in g/cm**3.
+ // for gaseous materials, you must call SetGasDensity(T,P) first in order
+ // to define the temperature and pressure of the gas.
+ return fDens;
+ };
+ void SetTemperatureAndPressure(Double_t T, Double_t P) {
+ // for a gaseous material, calculate density in g/cm**3 according to given
+ // conditions of temperature (T, in degrees celsius) and pressure (P, in Torr)
+ if (IsGas() && T > 0 && P > 0) fDens = (fMoleWt * P) / ((T + ZERO_KELVIN) * RTT);
+ };
+
+ Bool_t IsGas() const {
+ // returns kTRUE if material is in gaseous state
+ return (fState == "gas");
+ };
+
+ void ls(Option_t* = "") const;
+ void Print(Option_t* = "") const {
+ ls();
+ };
+
+ TF1* GetRangeFunction(Int_t Z, Int_t A, Double_t isoAmat = 0);
+ TF1* GetDeltaEFunction(Double_t e, Int_t Z, Int_t A, Double_t isoAmat = 0);
+ TF1* GetEResFunction(Double_t e, Int_t Z, Int_t A, Double_t isoAmat = 0);
+
+ void PrintRangeTable(Int_t Z, Int_t A, Double_t isoAmat = 0, Double_t units = KVUnits::cm, Double_t T = -1, Double_t P = -1);
+
+ virtual Double_t GetRangeOfIon(Int_t Z, Int_t A, Double_t E, Double_t isoAmat = 0.);
+ virtual Double_t GetLinearRangeOfIon(Int_t Z, Int_t A, Double_t E, Double_t isoAmat = 0, Double_t T = -1., Double_t P = -1.);
+
+ virtual Double_t GetDeltaEOfIon(Int_t Z, Int_t A, Double_t E, Double_t e, Double_t isoAmat = 0.);
+ virtual Double_t GetLinearDeltaEOfIon(Int_t Z, Int_t A, Double_t E, Double_t e, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.);
+
+ virtual Double_t GetEResOfIon(Int_t Z, Int_t A, Double_t E, Double_t e, Double_t isoAmat = 0.);
+ virtual Double_t GetLinearEResOfIon(Int_t Z, Int_t A, Double_t E, Double_t e, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.);
+
+ virtual Double_t GetEIncFromEResOfIon(Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat = 0.);
+ virtual Double_t GetLinearEIncFromEResOfIon(Int_t Z, Int_t A, Double_t Eres, Double_t e, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.);
+
+ virtual Double_t GetEIncFromDeltaEOfIon(Int_t Z, Int_t A, Double_t DeltaE, Double_t e, enum KVIonRangeTable::SolType type = KVIonRangeTable::kEmax, Double_t isoAmat = 0.);
+ virtual Double_t GetLinearEIncFromDeltaEOfIon(Int_t Z, Int_t A, Double_t DeltaE, Double_t e, enum KVIonRangeTable::SolType type = KVIonRangeTable::kEmax, Double_t isoAmat = 0., Double_t T = -1., Double_t P = -1.);
+
+ virtual Double_t GetDeltaEFromEResOfIon(Int_t Z, Int_t A, Double_t ERes, Double_t e, Double_t isoAmat = 0.) {
+ // Calculates energy loss (in MeV) of an ion (Z,A) from residual energy ERes (MeV) after thickness e (in mg/cm**2).
+ // Give Amat to change default (isotopic) mass of material,
+ return GetEIncFromEResOfIon(Z, A, ERes, e, isoAmat) - ERes;
+ }
+
+ virtual Double_t GetLinearDeltaEFromEResOfIon(Int_t Z, Int_t A, Double_t ERes, Double_t e,
+ Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.) {
+ // Calculates energy loss (in MeV) of an ion (Z,A) from residual energy ERes (MeV) after thickness e (in cm).
+ // Give Amat to change default (isotopic) mass of material,
+ // give temperature (degrees C) & pressure (torr) (T,P) for gaseous materials.
+ return GetLinearEIncFromEResOfIon(Z, A, ERes, e, isoAmat, T, P) - ERes;
+ }
+
+ virtual Double_t GetPunchThroughEnergy(Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0.) ;
+ virtual Double_t GetLinearPunchThroughEnergy(Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.) ;
+
+ virtual Double_t GetMaxDeltaEOfIon(Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0.);
+ virtual Double_t GetEIncOfMaxDeltaEOfIon(Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0.);
+ virtual Double_t GetLinearMaxDeltaEOfIon(Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.);
+ virtual Double_t GetLinearEIncOfMaxDeltaEOfIon(Int_t Z, Int_t A, Double_t e, Double_t isoAmat=0., Double_t T=-1., Double_t P=-1.);
+
+ ClassDef(KVedaLossMaterial, 1) //Description of material properties used by KVedaLoss range calculation
+};
+
+#endif
=== modified file 'etc/KaliVeda.rootrc'
--- etc/KaliVeda.rootrc 2011-03-14 08:44:04 +0000
+++ etc/KaliVeda.rootrc 2011-03-14 15:58:00 +0000
@@ -683,6 +683,13 @@
#
#
+# Plugins for calculation of range & energy loss of charge particles in matter.
+# Each class must derive from KVIonRangeTable abstract base class.
+Plugin.KVIonRangeTable: VEDALOSS KVedaLoss KVMultiDet "KVedaLoss()"
+
+# Ion range table used by KVMaterial. You can change this to use a different plugin defined as above.
+KVMaterial.IonRangeTable: VEDALOSS
+
# Default name for TEnv-format file containing real thicknesses of detectors
# in multidetector arrays defined for datasets.
# See KVMultiDetArray::SetDetectorThicknesses for file format.
@@ -690,11 +697,21 @@
# Special names for special datasets:
INDRA_camp5.KVMultiDetArray.DetectorThicknesses: EtalonThicknessCamp5.dat
+# KVPulseHeightDefect TF1::fNpx parameter for TF1 energy loss
+KVPulseHeightDefect.EnergyLoss.Npx: 20
# Z limit for PHD correction for energy in silicon detectors. Correction is applied for Z > ZminForPHDCorrection
KVSilicon.ZminForPHDCorrection: 10
-# File containing range tables for calculation of energy losses in KVMaterial
-KVMaterial.RangeTables: $(KVROOT)/KVFiles/data/kvloss.data
+# File containing range tables for calculation of energy losses in KVedaLoss
+KVedaLoss.RangeTables: $(KVROOT)/KVFiles/data/kvloss.data
+# TF1::fNpx parameter for TF1 range, energy loss, residual energy
+KVedaLoss.Range.Npx: 20
+KVedaLoss.EnergyLoss.Npx: 50
+KVedaLoss.ResidualEnergy.Npx: 20
+
+# KVDetector: TF1::fNpx parameter for TF1 energy loss & residual energy
+KVDetector.EnergyLoss.Npx: 20
+KVDetector.ResidualEnergy.Npx: 50
# LifeTime tables used by KVNDTManager
KVNDTManager.LifeTimeTable: KVLifeTimeTable
=== modified file 'html/ScanClasses.cpp'
--- html/ScanClasses.cpp 2009-10-30 14:59:37 +0000
+++ html/ScanClasses.cpp 2011-03-14 15:58:00 +0000
@@ -103,6 +103,7 @@
fClassTitles->Add( new KVBase("particles", "Particles & Nuclei"));
fClassTitles->Add( new KVBase("events", "Multiparticle Events"));
fClassTitles->Add( new KVBase("detectors", "Absorbers, Targets & Detectors"));
+ fClassTitles->Add( new KVBase("stopping", "Stopping Power & Range Tables for Heavy Ions"));
fClassTitles->Add( new KVBase("geometry", "Multidetector Geometry"));
fClassTitles->Add( new KVBase("indra", "INDRA Multidetector Array"));
fClassTitles->Add( new KVBase("data_management", "Data Management"));
Follow ups