BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSPSCellFluxScaled3D.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSHistBinMapper.hh"
22#include "BDSScorerConversionLoader.hh"
23#include "BDSPSCellFluxScaled3D.hh"
24#include "BDSUtilities.hh"
25
26#include "G4PhysicsVector.hh"
27#include "G4String.hh"
28#include "G4SystemOfUnits.hh"
29#include "G4Types.hh"
30#include "G4VSolid.hh"
31#include "G4VPhysicalVolume.hh"
32#include "G4VPVParameterisation.hh"
33#include "G4UnitsTable.hh"
34
35#include <fstream>
36#include <string>
37
38#ifdef USE_GZSTREAM
39#include "src-external/gzstream/gzstream.h"
40#endif
41
43 const BDSHistBinMapper* mapperIn,
44 const G4String& unitIn,
45 G4int ni,
46 G4int nj,
47 G4int nk,
48 G4int depi,
49 G4int depj,
50 G4int depk):
51 G4VPrimitiveScorer(scorerName),
52 HCID3D(-1),
53 evtMap3D(nullptr),
54 fDepthi(depi),fDepthj(depj),fDepthk(depk),
55 conversionFactor(nullptr),
56 mapper(mapperIn)
57{
59 CheckAndSetUnit(unitIn, "Per Unit Surface");
60 fNi = ni; // set base class members
61 fNj = nj;
62 fNk = nk;
63}
64
66 const BDSHistBinMapper* mapperIn,
67 const G4String& filename,
68 const G4String& unitIn,
69 G4int ni,
70 G4int nj,
71 G4int nk,
72 G4int depi,
73 G4int depj,
74 G4int depk):
75 BDSPSCellFluxScaled3D(scorerName, mapperIn, unitIn, ni, nj, nk, depi, depj, depk)
76{
77 if (filename.empty())
78 {throw BDSException(__METHOD_NAME__, "no conversionFactorFile provided for \"" + scorerName + "\" - required");}
79
80 G4String filePath = BDS::GetFullPath(filename);
81 if (filePath.rfind("gz") != std::string::npos)
82 {
83#ifdef USE_GZSTREAM
85 conversionFactor = loader.Load(filePath);
86#else
87 throw BDSException(__METHOD_NAME__, "Compressed file loading - but BDSIM not compiled with ZLIB.");
88#endif
89 }
90 else
91 {
93 conversionFactor = loader.Load(filePath);
94 }
95}
96
97BDSPSCellFluxScaled3D::~BDSPSCellFluxScaled3D()
98{
99 delete conversionFactor;
100}
101
102G4bool BDSPSCellFluxScaled3D::ProcessHits(G4Step* aStep, G4TouchableHistory*)
103{
104 G4double stepLength = aStep->GetStepLength();
105 G4double radiationQuantity = 0;
106
107 if (!BDS::IsFinite(stepLength))
108 {return false;}
109
110 const G4VTouchable* touchable = aStep->GetPreStepPoint()->GetTouchable();
111 G4VSolid* solid = touchable->GetSolid();
112 G4double cubicVolume = 1;
113 auto search = volumeCache.find(solid);
114 if (search == volumeCache.end())
115 {// cache the volume of the volume to avoid repeated calculation
116 // this is simple for a cube, but expensive for a cuttubs
117 cubicVolume = solid->GetCubicVolume();
118 volumeCache[solid] = cubicVolume;
119 }
120 else
121 {cubicVolume = search->second;}
122
123 G4double cellFlux = stepLength / cubicVolume;
124 cellFlux *= aStep->GetPreStepPoint()->GetWeight();
125
126 G4double kineticEnergy = aStep->GetPreStepPoint()->GetKineticEnergy();
127 G4double factor = GetConversionFactor(aStep->GetTrack()->GetDefinition()->GetPDGEncoding(), kineticEnergy);
128 radiationQuantity = cellFlux * factor;
129 G4int index = GetIndex(aStep);
130
131 evtMap3D->add(index, radiationQuantity);
132 return true;
133}
134
135G4double BDSPSCellFluxScaled3D::GetConversionFactor(G4int /*particleID*/,
136 G4double kineticEnergy) const
137{
138 return conversionFactor ? conversionFactor->Value(kineticEnergy) : 1.0;
139}
140
141void BDSPSCellFluxScaled3D::Initialize(G4HCofThisEvent* HCE)
142{
143 evtMap3D = new G4THitsMap<G4double>(detector->GetName(),
144 GetName());
145 if (HCID3D < 0)
146 {HCID3D = GetCollectionID(0);}
147 HCE->AddHitsCollection(HCID3D, evtMap3D);
148}
149
150void BDSPSCellFluxScaled3D::EndOfEvent(G4HCofThisEvent* /*HEC*/)
151{;}
152
153void BDSPSCellFluxScaled3D::clear()
154{
155 evtMap3D->clear();
156}
157
158G4int BDSPSCellFluxScaled3D::GetIndex(G4Step* aStep)
159{
160 const G4VTouchable* touchable = aStep->GetPreStepPoint()->GetTouchable();
161 G4int i = touchable->GetReplicaNumber(fDepthi);
162 G4int j = touchable->GetReplicaNumber(fDepthj);
163 G4int k = touchable->GetReplicaNumber(fDepthk);
164
165 if (i<0 || j<0 || k<0)
166 {
167 G4ExceptionDescription ED;
168 ED << "GetReplicaNumber is negative" << G4endl
169 << "touchable->GetReplicaNumber(fDepthi) returns i,j,k = "
170 << i << "," << j << "," << k << " for volume "
171 << touchable->GetVolume(fDepthi)->GetName() << ","
172 << touchable->GetVolume(fDepthj)->GetName() << ","
173 << touchable->GetVolume(fDepthk)->GetName() << G4endl;
174 G4Exception("BDSPSCellFluxScaled3D::GetIndex","DetPS0006",JustWarning,ED);
175 }
176
177 G4int globalIndex = mapper->GlobalFromIJKLIndex(i,j,k); // x,y,z
178 //G4int oldResult = i*fNj*fNk+j*fNk+k;
179 return globalIndex;
180}
181
183{
184 new G4UnitDefinition("percentimeter2", "percm2", "Per Unit Surface", (1./CLHEP::cm2));
185 new G4UnitDefinition("permillimeter2", "permm2", "Per Unit Surface", (1./CLHEP::mm2));
186 new G4UnitDefinition("permeter2", "perm2", "Per Unit Surface", (1./CLHEP::m2));
187}
General exception with possible name of object and message.
Definition: BDSException.hh:35
Mapping from axis indices to 1D index.
Primitive scorer for cell flux in a 3D mesh with a conversion factor.
G4THitsMap< G4double > * evtMap3D
Hits map.
const BDSHistBinMapper * mapper
Mapping from coordinate systems in mesh to global replica number.
G4int fDepthk
Depth in replica to look for each dimension.
G4PhysicsVector * conversionFactor
Conversion factor interpolator object.
G4int fDepthi
Depth in replica to look for each dimension.
G4int fDepthj
Depth in replica to look for each dimension.
void DefineUnitAndCategory() const
Define units -> taken from G4PSCellFlux.
G4int HCID3D
Collection ID.
BDSPSCellFluxScaled3D(const G4String &scorerName, const BDSHistBinMapper *mapperIn, const G4String &unitIn="percm2", G4int ni=1, G4int nj=1, G4int nk=1, G4int depi=2, G4int depj=1, G4int depk=0)
Loader for scoring conversion tables as function of energy.
G4PhysicsVector * Load(const G4String &fileName, G4bool silent=false)
Load the file.
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
const char * GetName(int)
Name of element.
Definition: python.cc:38