Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4ChemReboundTransportation.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//
27
29
31#include "G4H3O.hh"
32#include "G4ITNavigator.hh"
33#include "G4ITSafetyHelper.hh" // Not used yet
35#include "G4Molecule.hh"
36#include "G4NistManager.hh"
37#include "G4ParticleTable.hh"
38#include "G4RandomDirection.hh"
39#include "G4SafetyHelper.hh"
40#include "G4SystemOfUnits.hh"
42#include "G4UnitsTable.hh"
44#include "Randomize.hh"
45
46#include <CLHEP/Random/Stat.h>
47using namespace std;
48
49#ifndef State
50# define State(theXInfo) (GetState<G4ITBrownianState>()->theXInfo)
51#endif
52
53static G4double InvErfc(G4double x)
54{
55 return CLHEP::HepStat::inverseErf(1. - x);
56}
57
58#ifndef State
59# define State(theXInfo) (GetState<G4ITTransportationState>()->theXInfo)
60#endif
61//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
62
64 const G4DNABoundingBox* pB,
65 G4int verbosity)
66 : G4ITTransportation(aName, verbosity), fpBoundingBox(pB)
67{
68 fVerboseLevel = 0;
69 fpState = std::make_shared<G4ITBrownianState>();
72 fInternalMinTimeStep = 1 * CLHEP::ps;
73}
74//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
75
81//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
82
84{
85 fpState = std::make_shared<G4ITBrownianState>();
88}
89//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
90
92{
93 fpSafetyHelper->InitialiseHelper();
95
96 if (fpBoundingBox == nullptr) {
98 errMsg << "fpBoundingBox is nullptr";
100 "ChemReboundTransportation::BuildPhysicsTable"
101 "ChemReboundTransportation",
102 "ChemReboundTransportation", FatalErrorInArgument, errMsg);
103 }
104 G4double halfSize =
105 std::min({fpBoundingBox->halfSideLengthInX(), fpBoundingBox->halfSideLengthInY(),
106 fpBoundingBox->halfSideLengthInZ()});
107 fMaximumTimeStep = (halfSize * halfSize) / (60 * G4H3O::Definition()->GetDiffusionCoefficient());
108}
109//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
110
112 const G4double timeStep, G4double& spaceStep)
113{
114 if (GetIT(track)->GetTrackingInfo()->IsLeadingStep()) {
115 G4ExceptionDescription exceptionDescription;
116 exceptionDescription << "ComputeStep is called while the track has"
117 "the minimum interaction time";
118 exceptionDescription << " so it should not recompute a timeStep ";
119 G4Exception("ChemReboundTransportation::ComputeStep", "ChemReboundTransportation0001",
120 FatalErrorInArgument, exceptionDescription);
121 }
122 State(fGeometryLimitedStep) = false;
123 if (timeStep == 0) {
124 State(fTransportEndPosition) = track.GetPosition();
125 spaceStep = 0.;
126 }
127 else {
128 const auto molConf = GetMolecule(track)->GetMolecularConfiguration();
129 spaceStep = calculateDistanceFromTimeStep(molConf, timeStep);
130 }
131 State(fTransportEndPosition) =
132 BouncingAction(track.GetPosition() + spaceStep * G4RandomDirection());
133 State(fEndPointDistance) = (track.GetPosition() - State(fTransportEndPosition)).mag();
134 if (fVerboseLevel > 1)
135 // if(GetMolecule(track)->GetName() == "e_aq^-1")
136 {
137 G4cout << G4endl;
138 G4cout << "ComputeStep: timeStep : " << G4BestUnit(timeStep, "Time")
139 << " State(theInteractionTimeLeft) : " << State(theInteractionTimeLeft)
140 << " State(fEndPointDistance) : " << G4BestUnit(State(fEndPointDistance), "Length")
141 << " trackID : " << track.GetTrackID()
142 << " Molecule name: " << "track.GetPosition() : " << track.GetPosition()
143 << " State(fTransportEndPosition) : " << State(fTransportEndPosition) << " "
144 << GetMolecule(track)->GetName() << " Diffusion length : " << G4endl;
145 }
146 State(fCandidateEndGlobalTime) = step.GetPreStepPoint()->GetGlobalTime() + timeStep;
147 State(fEndGlobalTimeComputed) = true;
148}
149//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
150
152 const G4Step& step)
153{
155
156#ifdef G4VERBOSE
157 // DEBUG
158 if (fVerboseLevel > 1)
159 // if(GetMolecule(track)->GetName() == "e_aq^-1")
160 if (GetIT(track)->GetTrackingInfo()->IsLeadingStep()) {
161 G4cout << "ChemReboundTransportation::PostStepDoIt() :" << " trackID : " << track.GetTrackID()
162 << " Molecule name: " << "prePosition : " << step.GetPreStepPoint()->GetPosition()
163 << " postPostion : " << step.GetPostStepPoint()->GetPosition() << " "
164 << GetMolecule(track)->GetName()
165 << " Diffusion length : " << G4BestUnit(step.GetStepLength(), "Length")
166 << " within time step : " << G4BestUnit(step.GetDeltaTime(), "Time")
167 << "\t Current global time : " << G4BestUnit(track.GetGlobalTime(), "Time")
168 << " track.GetMomentumDirection() : " << track.GetMomentumDirection() << G4endl;
169 }
170#endif
171 return &fParticleChange;
172}
173
175 const G4Track& track, G4double /*previousStepSize*/, G4double /*currentMinimumStep*/,
176 G4double& /*currentSafety*/, G4GPILSelection* /*selection*/)
177{
178 if (!fpBoundingBox->contains(track.GetPosition())) {
180 errMsg << "Point is out of box : " << *fpBoundingBox
181 << " of particle : " << GetIT(track)->GetName() << "(" << track.GetTrackID()
182 << ") : " << track.GetPosition();
184 "ChemReboundTransportation::AlongStepGetPhysicalInteractionLength"
185 "ChemReboundTransportation",
186 "ChemReboundTransportation", FatalErrorInArgument, errMsg);
187 }
188 if (fNistWater != track.GetMaterial()) {
190 errMsg << "This is not water";
192 "ChemReboundTransportation::AlongStepGetPhysicalInteractionLength"
193 "ChemReboundTransportation",
194 "ChemReboundTransportation", FatalErrorInArgument, errMsg);
195 }
196
197 G4double geometryStepLength = DBL_MAX;
198 State(theInteractionTimeLeft) = DBL_MAX;
199
200 auto molConf = GetMolecule(track)->GetMolecularConfiguration();
201 G4ITReactionPerTime& reactionPerTime = fReactionSet->GetReactionsPerTime();
202 auto reaction_i = reactionPerTime.begin();
203 if (reaction_i == reactionPerTime.end()) {
204 State(fGeometryLimitedStep) = false;
205 State(theInteractionTimeLeft) = fMaximumTimeStep;
206 if (fVerboseLevel > 1) {
207 G4cout << "out of reaction " << G4BestUnit(State(theInteractionTimeLeft), "Time") << G4endl;
208 }
209 }
210 else {
211 G4Track* pTrackA = (*reaction_i)->GetReactants().first;
212 G4Track* pTrackB = (*reaction_i)->GetReactant(pTrackA);
213
214 if (&track == pTrackA || &track == pTrackB) {
215 State(theInteractionTimeLeft) = GetTimeToBoundary(track);
216 State(fTimeStepReachedLimit) = false;
217 State(fGeometryLimitedStep) = false;
218
219 if (fVerboseLevel > 1)
220 G4cout << "Molecule A is of type : " << GetMolecule(track)->GetName()
221 << " with trackID : " << track.GetTrackID()
222 << " fMaximumTimeStep : " << G4BestUnit(fMaximumTimeStep, "Time")
223 << " State(theInteractionTimeLeft) : "
224 << G4BestUnit(State(theInteractionTimeLeft), "Time") << G4endl;
225
226 if (State(theInteractionTimeLeft) < fInternalMinTimeStep) {
227 State(fTimeStepReachedLimit) = true;
228 State(theInteractionTimeLeft) = fInternalMinTimeStep;
229 }
230 else if (State(theInteractionTimeLeft) > fMaximumTimeStep) {
231 State(fTimeStepReachedLimit) = true;
232 State(theInteractionTimeLeft) = fMaximumTimeStep;
233 }
234 }
235 else {
236 State(fGeometryLimitedStep) = false;
237 State(theInteractionTimeLeft) = DBL_MAX;
238 }
239 }
240
241 geometryStepLength = calculateDistanceFromTimeStep(molConf, State(theInteractionTimeLeft));
242 State(fTransportEndPosition) =
243 BouncingAction(track.GetPosition() + geometryStepLength * G4RandomDirection());
244
245 State(fTimeStepReachedLimit) = true;
246 State(fCandidateEndGlobalTime) = track.GetGlobalTime() + State(theInteractionTimeLeft);
247 State(fEndGlobalTimeComputed) = true;
248
249#ifdef G4VERBOSE
250 if (fVerboseLevel > 1) {
251 G4cout << "ChemReboundTransportation::AlongStepGetPhysicalInteractionLength = "
252 << G4BestUnit(geometryStepLength, "Length") << " "
253 << G4BestUnit(State(theInteractionTimeLeft), "Time")
254 << " | trackID = " << track.GetTrackID() << G4endl;
255 }
256#endif
257 return geometryStepLength;
258}
259//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
260
262 const G4Step& step)
263{
264 if (GetIT(track)->GetTrackingInfo()->IsLeadingStep()) {
265 // Hoang fixed: - Fixed the state update in AlongStepDoIt (G4ChemReboundTransportation) to
266 // avoid setting incorrect molecule positions (leading tracks)
267 // when the scavenger process is called.
268
269 // G4double spaceStep = DBL_MAX;
270 // const auto molConf = GetMolecule(track)->GetMolecularConfiguration();
271 // spaceStep = calculateDistanceFromTimeStep(molConf, State(theInteractionTimeLeft));
272
273 // State(fGeometryLimitedStep) = false;
274 // State(fTransportEndPosition) =
275 // BouncingAction(track.GetPosition() + spaceStep * G4RandomDirection());
276 // State(fEndPointDistance) = spaceStep;
277 if (fVerboseLevel > 1)
278 //if(GetMolecule(track)->GetName() == "e_aq^-1")
279 {
280 G4cout << "G4DNABrownianTransportation::AlongStepDoIt() : IsLeadingStep " << " trackID : "
281 << track.GetTrackID()
282 << "position : "<<track.GetPosition()
283 << " Molecule name: "
284 << GetMolecule(track)->GetName()<< "State(fTransportEndPosition) : "<<State(fTransportEndPosition) << " State(theInteractionTimeLeft) : "
285 << G4BestUnit(State(theInteractionTimeLeft), "Time")
286 << " Diffusion length : " << G4BestUnit(step.GetStepLength(), "Length")
287 << " within time step : " << G4BestUnit(step.GetDeltaTime(), "Time")
288 << "\t Current global time : " << G4BestUnit(track.GetGlobalTime(), "Time")
289 << " track.GetMomentumDirection() : " << track.GetMomentumDirection()<<" GetIT(track)->GetTrackingInfo()->IsLeadingStep() : "<<GetIT(track)->GetTrackingInfo()->IsLeadingStep() << G4endl;
290 //throw;
291 }
292 }
293
295
296 return &fParticleChange;
297}
298//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
299
301{
302 // from Karamitros, Mathieu et al.2020,arXiv:2006.14225 (2020)
303 // https://doi.org/10.48550/arXiv.2006.14225
304
305 G4ThreeVector output;
306
307 G4double RxM = fpBoundingBox->Getxhi();
308 G4double RyM = fpBoundingBox->Getyhi();
309 G4double RzM = fpBoundingBox->Getzhi();
310 G4double Rxm = fpBoundingBox->Getxlo();
311 G4double Rym = fpBoundingBox->Getylo();
312 G4double Rzm = fpBoundingBox->Getzlo();
313
314 G4double x = calculateNextCoordinate(nextPosition.getX(), RxM, Rxm);
315 G4double y = calculateNextCoordinate(nextPosition.getY(), RyM, Rym);
316 G4double z = calculateNextCoordinate(nextPosition.getZ(), RzM, Rzm);
317 output.set(x, y, z);
318 return output;
319}
320//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
321
323 G4double low)
324{
325 // from Karamitros, Mathieu et al.2020,arXiv:2006.14225 (2020)
326
327 G4double length = high - low;
328 if (std::abs(length) < 1e-10) {
329 return low;
330 }
331
332 G4double relativePos = std::abs(nextPos - low);
333 if (!std::isfinite(relativePos)) {
334 return low; // no crash
335 }
336
337 G4double n = relativePos / length;
338 if (!std::isfinite(n)) {
339 return low;
340 }
341
342 G4double truncVal = std::floor(n);//n is already positive
343 G4double h = truncVal;
344 if(truncVal > 2.0){
345 h = std::fmod(truncVal, 2.0);
346 }
347
348 G4double mod = relativePos;
349
350 if(relativePos > length) {
351 mod = std::fmod(relativePos, length);
352 }
353
354 return low + h * length + (1 - 2 * h) * std::abs(mod);
355}
356//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
357
359{
360 G4double diffuCoeff = mol->GetDiffusionCoefficient();
361 if (mol->GetDiffusionCoefficient() < 0) {
362 G4ExceptionDescription exceptionDescription;
363 exceptionDescription << "GetDiffusionCoefficient is negative";
364 G4Exception("ChemReboundTransportation::calculateDistanceFromTimeStep",
365 "ChemReboundTransportation030", FatalErrorInArgument, exceptionDescription);
366 }
367 G4double sqrt_2Dt = sqrt(2 * diffuCoeff * timeStep);
368 G4double x = G4RandGauss::shoot(0, sqrt_2Dt);
369 G4double y = G4RandGauss::shoot(0, sqrt_2Dt);
370 G4double z = G4RandGauss::shoot(0, sqrt_2Dt);
371 return sqrt(x * x + y * y + z * z);
372}
373//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
374
376{
377 if (!fpBoundingBox->contains(track.GetPosition())) {
379 errMsg << "Point is out of box : " << *fpBoundingBox
380 << " of particle : " << GetIT(track)->GetName() << "(" << track.GetTrackID()
381 << ") : " << track.GetPosition();
383 "BoundedBrownianAction::GetTimeToBoundary"
384 "BoundedBrownianAction",
385 "BoundedBrownianAction", FatalErrorInArgument, errMsg);
386 }
387 auto diffusionCoefficient = GetMolecule(track)->GetDiffusionCoefficient();
388
389 auto dx = std::min(track.GetPosition().getX() - fpBoundingBox->Getxlo(),
390 fpBoundingBox->Getxhi() - track.GetPosition().getX());
391 auto dy = std::min(track.GetPosition().getY() - fpBoundingBox->Getylo(),
392 fpBoundingBox->Getyhi() - track.GetPosition().getY());
393 auto dz = std::min(track.GetPosition().getZ() - fpBoundingBox->Getzlo(),
394 fpBoundingBox->Getzhi() - track.GetPosition().getZ());
395
396 std::vector<G4double> distanceVector{dx, dy, dz};
397 G4double MinTime = DBL_MAX;
398 for (const auto& it : distanceVector) {
399 G4double distance = it;
400 auto random = G4UniformRand();
401 auto minTime = 1 / (4 * diffusionCoefficient) * pow(distance / InvErfc(random), 2);
402
403 if (MinTime > minTime) {
404 MinTime = minTime;
405 }
406 }
407 return MinTime;
408}
409//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4GPILSelection
#define State(X)
std::multiset< G4ITReactionPtr, compReactionPerTime > G4ITReactionPerTime
G4IT * GetIT(const G4Track *track)
Definition G4IT.cc:48
@ fLowEnergyBrownianTransportation
G4Molecule * GetMolecule(const G4Track &track)
Definition G4Molecule.cc:75
G4ThreeVector G4RandomDirection()
#define G4BestUnit(a, b)
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
double getZ() const
void set(double x, double y, double z)
double getX() const
double getY() const
static double inverseErf(double t)
void StartTracking(G4Track *aTrack) override
G4ThreeVector BouncingAction(const G4ThreeVector &nextPosition)
G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &) override
G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &) override
G4double AlongStepGetPhysicalInteractionLength(const G4Track &, G4double, G4double, G4double &, G4GPILSelection *) override
static G4double calculateNextCoordinate(G4double nextPos, G4double high, G4double low)
void ComputeStep(const G4Track &, const G4Step &, G4double, G4double &) override
void BuildPhysicsTable(const G4ParticleDefinition &) override
G4double calculateDistanceFromTimeStep(MolConf mol, G4double timeStep)
G4double GetTimeToBoundary(const G4Track &track)
G4ChemReboundTransportation(const G4String &aName="ChemReboundTransportation", const G4DNABoundingBox *=nullptr, G4int verbosityLevel=0)
static G4H3O * Definition()
Definition G4H3O.cc:46
G4ParticleChangeForTransport fParticleChange
G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &stepData) override
void SetInstantiateProcessState(G4bool flag)
void BuildPhysicsTable(const G4ParticleDefinition &) override
void StartTracking(G4Track *aTrack) override
G4ITSafetyHelper * fpSafetyHelper
G4ITTransportation(const G4String &aName="ITTransportation", G4int verbosityLevel=0)
G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &) override
G4TrackingInformation * GetTrackingInfo()
Definition G4IT.hh:143
virtual const G4String & GetName() const =0
const G4MolecularConfiguration * GetMolecularConfiguration() const
const G4String & GetName() const override
G4double GetDiffusionCoefficient() const
G4Material * FindOrBuildMaterial(const G4String &name, G4bool isotopes=true, G4bool warning=false)
static G4NistManager * Instance()
G4double GetGlobalTime() const
const G4ThreeVector & GetPosition() const
G4double GetDeltaTime() const
G4StepPoint * GetPreStepPoint() const
G4double GetStepLength() const
G4StepPoint * GetPostStepPoint() const
G4int GetTrackID() const
const G4ThreeVector & GetPosition() const
G4double GetGlobalTime() const
G4Material * GetMaterial() const
const G4ThreeVector & GetMomentumDirection() const
G4shared_ptr< G4ProcessState > fpState
void SetProcessSubType(G4int)
#define DBL_MAX
Definition templates.hh:62