Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4EnergySplitter.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26#include "G4EnergySplitter.hh"
27
28#include "G4EmCalculator.hh"
30#include "G4PVParameterised.hh"
33#include "G4Step.hh"
34#include "G4UnitsTable.hh"
35#include "G4VSolid.hh"
36
37////////////////////////////////////////////////////////////////////////////////
38// (Description)
39//
40// Created:
41//
42///////////////////////////////////////////////////////////////////////////////
43
45{
46 theElossExt = new G4EnergyLossForExtrapolator(0);
47 thePhantomParam = nullptr;
48 theNIterations = 2;
49}
50
52{
53 delete theElossExt;
54}
55
57{
58 theEnergies.clear();
59
60 if (aStep == nullptr) return false; // it is 0 when called by GmScoringMgr after last event
61
62 G4double edep = aStep->GetTotalEnergyDeposit();
63
64 if( edep == 0. ) {
65 return 0;
66 }
67
68#ifdef VERBOSE_ENERSPLIT
69 G4bool verbose = 1;
70 if (verbose)
71 G4cout << "G4EnergySplitter::SplitEnergyInVolumes totalEdepo " << aStep->GetTotalEnergyDeposit()
72 << " Nsteps " << G4RegularNavigationHelper::Instance()->GetStepLengths().size()
73 << G4endl;
74#endif
75 if (G4RegularNavigationHelper::Instance()->GetStepLengths().empty()
76 || aStep->GetTrack()->GetDefinition()->GetPDGCharge() == 0)
77 { // we are only counting dose deposit
78 return (G4int)theEnergies.size();
79 }
80 if (G4RegularNavigationHelper::Instance()->GetStepLengths().size() == 1) {
81 theEnergies.push_back(edep);
82 return (G4int)theEnergies.size();
83 }
84
85 //----- Get the phantom parameterisation from the G4Step
86 auto preStepPhysVol = aStep->GetPreStepPoint()->GetPhysicalVolume();
87 if (!IsPhantomVolume(preStepPhysVol)) {
88 G4Exception("G4EnergySplitter::SplitEnergyInVolumes", "PhantomParamError", FatalException,
89 "SplitEnergyInVolumes() called for a step not in a phantom volume");
90 }
91 auto phantomVol = static_cast<G4PVParameterised*>(preStepPhysVol);
92 thePhantomParam = static_cast<G4PhantomParameterisation*>(phantomVol->GetParameterisation());
93
94 //----- Distribute energy deposited in voxels
95 std::vector<std::pair<G4int, G4double>> rnsl =
97
98 const G4ParticleDefinition* part = aStep->GetTrack()->GetDefinition();
99 G4double kinEnergyPreOrig = aStep->GetPreStepPoint()->GetKineticEnergy();
100 G4double kinEnergyPre = kinEnergyPreOrig;
101
102 G4double stepLength = aStep->GetStepLength();
103 G4double slSum = 0.;
104 unsigned int ii;
105 for (ii = 0; ii < rnsl.size(); ++ii) {
106 G4double sl = rnsl[ii].second;
107 slSum += sl;
108#ifdef VERBOSE_ENERSPLIT
109 if (verbose)
110 G4cout << "G4EnergySplitter::SplitEnergyInVolumes" << ii << " RN: iter1 step length geom "
111 << sl << G4endl;
112#endif
113 }
114
115#ifdef VERBOSE_ENERSPLIT
116 if (verbose)
117 G4cout << "G4EnergySplitter RN: step length geom TOTAL " << slSum << " true TOTAL "
118 << stepLength << " ratio " << stepLength / slSum << " Energy "
119 << aStep->GetPreStepPoint()->GetKineticEnergy() << " Material "
120 << aStep->GetPreStepPoint()->GetMaterial()->GetName() << " Number of geom steps "
121 << rnsl.size() << G4endl;
122#endif
123 //----- No iterations to correct elost and msc => distribute energy deposited according to
124 // geometrical step length in each voxel
125 if (theNIterations == 0) {
126 for (ii = 0; ii < rnsl.size(); ++ii) {
127 G4double sl = rnsl[ii].second;
128 G4double edepStep = edep * sl / slSum; // divide edep along steps, proportional to step
129 // length
130#ifdef VERBOSE_ENERSPLIT
131 if (verbose)
132 G4cout << "G4EnergySplitter::SplitEnergyInVolumes" << ii << " edep " << edepStep << G4endl;
133#endif
134
135 theEnergies.push_back(edepStep);
136 }
137 }
138 else { // 1 or more iterations demanded
139
140#ifdef VERBOSE_ENERSPLIT
141 // print corrected energy at iteration 0
142 if (verbose) {
143 G4double slSum = 0.;
144 for (ii = 0; ii < rnsl.size(); ++ii) {
145 G4double sl = rnsl[ii].second;
146 slSum += sl;
147 }
148 for (ii = 0; ii < rnsl.size(); ii++) {
149 G4cout << "G4EnergySplitter::SplitEnergyInVolumes " << ii
150 << " RN: iter0 corrected energy lost " << edep * rnsl[ii].second / slSum << G4endl;
151 }
152 }
153#endif
154
155 G4double slRatio = stepLength / slSum;
156#ifdef VERBOSE_ENERSPLIT
157 if (verbose)
158 G4cout << "G4EnergySplitter::SplitEnergyInVolumes RN: iter 0, step ratio " << slRatio
159 << G4endl;
160#endif
161
162 //--- energy at each interaction
163 G4EmCalculator emcalc;
164 G4double totalELost = 0.;
165 std::vector<G4double> stepLengths;
166 for (G4int iiter = 1; iiter <= theNIterations; ++iiter) {
167 //--- iter1: distribute true step length in each voxel: geom SL in each voxel is multiplied by
168 // a constant so that the sum gives the total true step length
169 if (iiter == 1) {
170 for (ii = 0; ii < rnsl.size(); ++ii) {
171 G4double sl = rnsl[ii].second;
172 stepLengths.push_back(sl * slRatio);
173#ifdef VERBOSE_ENERSPLIT
174 if (verbose)
175 G4cout << "G4EnergySplitter::SplitEnergyInVolumes" << ii << " RN: iter" << iiter
176 << " corrected step length " << sl * slRatio << G4endl;
177#endif
178 }
179
180 for (ii = 0; ii < rnsl.size(); ++ii) {
181 const G4Material* mate = thePhantomParam->GetMaterial(rnsl[ii].first);
182 G4double dEdx = 0.;
183 if (kinEnergyPre > 0.) { // t check this
184 dEdx = emcalc.GetDEDX(kinEnergyPre, part, mate);
185 }
186 G4double elost = stepLengths[ii] * dEdx;
187
188#ifdef VERBOSE_ENERSPLIT
189 if (verbose)
190 G4cout << "G4EnergySplitter::SplitEnergyInVolumes" << ii << " RN: iter1 energy lost "
191 << elost << " energy at interaction " << kinEnergyPre << " = stepLength "
192 << stepLengths[ii] << " * dEdx " << dEdx << G4endl;
193#endif
194 kinEnergyPre -= elost;
195 theEnergies.push_back(elost);
196 totalELost += elost;
197 }
198 }
199 else {
200 //------ 2nd and other iterations
201 //----- Get step lengths corrected by changing geom2true correction
202 //-- Get ratios for each energy
203 slSum = 0.;
204 kinEnergyPre = kinEnergyPreOrig;
205 for (ii = 0; ii < rnsl.size(); ++ii) {
206 const G4Material* mate = thePhantomParam->GetMaterial(rnsl[ii].first);
207 stepLengths[ii] = theElossExt->TrueStepLength(kinEnergyPre, rnsl[ii].second, mate, part);
208 kinEnergyPre -= theEnergies[ii];
209
210#ifdef VERBOSE_ENERSPLIT
211 if (verbose)
212 G4cout << "G4EnergySplitter::SplitEnergyInVolumes" << ii << " RN: iter" << iiter
213 << " step length geom " << stepLengths[ii] << " geom2true "
214 << rnsl[ii].second / stepLengths[ii] << G4endl;
215#endif
216
217 slSum += stepLengths[ii];
218 }
219
220 // Correct step lengths so that they sum the total step length
221 G4double slratio = aStep->GetStepLength() / slSum;
222#ifdef VERBOSE_ENERSPLIT
223 if (verbose)
224 G4cout << "G4EnergySplitter::SplitEnergyInVolumes" << ii << " RN: iter" << iiter
225 << " step ratio " << slRatio << G4endl;
226#endif
227 for (ii = 0; ii < rnsl.size(); ++ii) {
228 stepLengths[ii] *= slratio;
229#ifdef VERBOSE_ENERSPLIT
230 if (verbose)
231 G4cout << "G4EnergySplitter::SplitEnergyInVolumes" << ii << " RN: iter" << iiter
232 << " corrected step length " << stepLengths[ii] << G4endl;
233#endif
234 }
235
236 //---- Recalculate energy lost with this new step lengths
237 kinEnergyPre = aStep->GetPreStepPoint()->GetKineticEnergy();
238 totalELost = 0.;
239 for (ii = 0; ii < rnsl.size(); ++ii) {
240 const G4Material* mate = thePhantomParam->GetMaterial(rnsl[ii].first);
241 G4double dEdx = 0.;
242 if (kinEnergyPre > 0.) {
243 dEdx = emcalc.GetDEDX(kinEnergyPre, part, mate);
244 }
245 G4double elost = stepLengths[ii] * dEdx;
246#ifdef VERBOSE_ENERSPLIT
247 if (verbose)
248 G4cout << "G4EnergySplitter::SplitEnergyInVolumes" << ii << " RN: iter" << iiter
249 << " energy lost " << elost << " energy at interaction " << kinEnergyPre
250 << " = stepLength " << stepLengths[ii] << " * dEdx " << dEdx << G4endl;
251#endif
252 kinEnergyPre -= elost;
253 theEnergies[ii] = elost;
254 totalELost += elost;
255 }
256 }
257
258 // correct energies so that they reproduce the real step energy lost
259 G4double enerRatio = (edep / totalELost);
260
261#ifdef VERBOSE_ENERSPLIT
262 if (verbose)
263 G4cout << "G4EnergySplitter::SplitEnergyInVolumes" << ii << " RN: iter" << iiter
264 << " energy ratio " << enerRatio << G4endl;
265#endif
266
267#ifdef VERBOSE_ENERSPLIT
268 G4double elostTot = 0.;
269#endif
270 for (ii = 0; ii < theEnergies.size(); ++ii) {
271 theEnergies[ii] *= enerRatio;
272#ifdef VERBOSE_ENERSPLIT
273 elostTot += theEnergies[ii];
274 if (verbose)
275 G4cout << "G4EnergySplitter::SplitEnergyInVolumes " << ii << " RN: iter" << iiter
276 << " corrected energy lost " << theEnergies[ii] << " orig elost "
277 << theEnergies[ii] / enerRatio << " energy before interaction "
278 << kinEnergyPreOrig - elostTot + theEnergies[ii] << " energy after interaction "
279 << kinEnergyPreOrig - elostTot << G4endl;
280#endif
281 }
282 }
283 }
284
285 return (G4int)theEnergies.size();
286}
287
288//-----------------------------------------------------------------------
289G4bool G4EnergySplitter::IsPhantomVolume(G4VPhysicalVolume* pv)
290{
291 EAxis axis;
292 G4int nReplicas;
293 G4double width, offset;
294 G4bool consuming;
295 pv->GetReplicationData(axis, nReplicas, width, offset, consuming);
296 EVolume type = (consuming) ? kReplica : kParameterised;
297 return type == kParameterised && pv->GetRegularStructureId() == 1;
298}
299
300//-----------------------------------------------------------------------
302{
303 voxelID = (*(G4RegularNavigationHelper::Instance()->GetStepLengths().cbegin())).first;
304}
305
306//-----------------------------------------------------------------------
308{
309 voxelID = (*(G4RegularNavigationHelper::Instance()->GetStepLengths().crbegin())).first;
310}
311
312//-----------------------------------------------------------------------
314{
315 if (stepNo < 0 || stepNo >= G4int(G4RegularNavigationHelper::Instance()->GetStepLengths().size()))
316 {
317 G4Exception("G4EnergySplitter::GetVoxelID",
318 "Invalid stepNo, smaller than 0 or bigger or equal to number of voxels traversed",
320 G4String("stepNo = " + G4UIcommand::ConvertToString(stepNo)
321 + ", number of voxels = "
323 G4int(G4RegularNavigationHelper::Instance()->GetStepLengths().size())))
324 .c_str());
325 }
327 advance(ite, stepNo);
328 voxelID = (*ite).first;
329}
330
331//-----------------------------------------------------------------------
332void G4EnergySplitter::GetStepLength(G4int stepNo, G4double& stepLength)
333{
335 advance(ite, stepNo);
336 stepLength = (*ite).second;
337}
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4ThreadLocal T * G4GeomSplitter< T >::offset
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
G4double GetDEDX(G4double kinEnergy, const G4ParticleDefinition *, const G4Material *, const G4Region *r=nullptr)
virtual ~G4EnergySplitter()
void GetFirstVoxelID(G4int &voxelID)
G4int SplitEnergyInVolumes(const G4Step *aStep)
void GetLastVoxelID(G4int &voxelID)
void GetVoxelID(G4int stepNo, G4int &voxelID)
const G4String & GetName() const
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
G4PVParameterised represents many touchable detector elements differing in their positioning and dime...
G4PhantomParameterisation describes regular parameterisations: a set of boxes of equal dimension in t...
const std::vector< std::pair< G4int, G4double > > & GetStepLengths()
static G4RegularNavigationHelper * Instance()
G4Material * GetMaterial() const
G4VPhysicalVolume * GetPhysicalVolume() const
G4double GetKineticEnergy() const
G4Track * GetTrack() const
G4StepPoint * GetPreStepPoint() const
G4double GetStepLength() const
G4double GetTotalEnergyDeposit() const
G4ParticleDefinition * GetDefinition() const
static G4String ConvertToString(G4bool boolVal)
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
virtual void GetReplicationData(EAxis &axis, G4int &nReplicas, G4double &width, G4double &offset, G4bool &consuming) const =0
virtual G4int GetRegularStructureId() const =0
EAxis
Definition geomdefs.hh:54
EVolume
Definition geomdefs.hh:83
@ kParameterised
Definition geomdefs.hh:86
@ kReplica
Definition geomdefs.hh:85
const axis_t axis_to_type< N >::axis
Definition pugixml.cc:9668