Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4DNAGillespieDirectMethod.cc
Go to the documentation of this file.
1// ********************************************************************
2// * License and Disclaimer *
3// * *
4// * The Geant4 software is copyright of the Copyright Holders of *
5// * the Geant4 Collaboration. It is provided under the terms and *
6// * conditions of the Geant4 Software License, included in the file *
7// * LICENSE and available at http://cern.ch/geant4/license . These *
8// * include a list of copyright holders. *
9// * *
10// * Neither the authors of this software system, nor their employing *
11// * institutes,nor the agencies providing financial support for this *
12// * work make any representation or warranty, express or implied, *
13// * regarding this software system or assume any liability for its *
14// * use. Please see the license in the file LICENSE and URL above *
15// * for the full disclaimer and the limitation of liability. *
16// * *
17// * This code implementation is the result of the scientific and *
18// * technical work of the GEANT4 collaboration. *
19// * By using, copying, modifying or distributing the software (or *
20// * any work based on the software) you agree to acknowledge its *
21// * use in resulting scientific publications, and indicate your *
22// * acceptance of all terms of the Geant4 Software license. *
23// ********************************************************************
24//
25
27#include "Randomize.hh"
29#include <memory>
30#include <tuple>
31#include "G4DNAEventSet.hh"
32#include "G4UnitsTable.hh"
34#include "G4Scheduler.hh"
36
38 : fMolecularReactions(G4DNAMolecularReactionTable::Instance())
39{}
40
42
44{
45 fpEventSet = pEventSet;
46}
47
48//#define DEBUG 1
49
50G4double G4DNAGillespieDirectMethod::VolumeOfNode(const Voxel& voxel)
51{
52 auto box = std::get<1>(voxel);
53 auto LengthY = box.Getyhi() - box.Getylo();
54 auto LengthX = box.Getxhi() - box.Getxlo();
55 auto LengthZ = box.Getzhi() - box.Getzlo();
56 G4double V = LengthY * LengthX * LengthZ;
57 if(V <= 0)
58 {
59 G4ExceptionDescription exceptionDescription;
60 exceptionDescription << "V > 0 !! ";
61 G4Exception("G4DNAGillespieDirectMethod::VolumeOfNode",
62 "G4DNAGillespieDirectMethod03", FatalErrorInArgument,
63 exceptionDescription);
64 }
65 return V;
66}
68 MolType moleType)
69{
70 if(moleType->GetDiffusionCoefficient() == 0)
71 {
72 return 0.;
73 }
74 const auto& node = std::get<2>(voxel);
75 const auto& box = std::get<1>(voxel);
76
77 G4double alpha = 0;
78 auto it = node.find(moleType);
79 if(it != node.end())
80 {
81 auto LengthY = box.Getyhi() - box.Getylo();
82 G4double d = it->first->GetDiffusionCoefficient() / std::pow(LengthY, 2);
83 alpha = d * it->second;
84
85#ifdef DEBUG
86 G4cout << it->first->GetName() << " " << it->second
87 << " D : " << it->first->GetDiffusionCoefficient()
88 << " LengthY : " << LengthY << " PropensityFunction : " << alpha
89 << G4endl;
90#endif
91 }
92 return alpha;
93}
94
96 ReactionData* data)
97{
98 G4double value;
99 auto ConfA = data->GetReactant1();
100 auto ConfB = data->GetReactant2();
101 G4double scavengerNumber = 0;
102 auto typeANumber = FindScavenging(voxel, ConfA, scavengerNumber)
103 ? scavengerNumber
104 : ComputeNumberInNode(voxel, ConfA);
105
106 auto typeBNumber = FindScavenging(voxel, ConfB, scavengerNumber)
107 ? scavengerNumber
108 : ComputeNumberInNode(voxel, ConfB);
109
110 if(typeANumber == 0 || typeBNumber == 0)
111 {
112 return 0;
113 }
114
115 auto k =
116 data->GetObservedReactionRateConstant() / (Avogadro * VolumeOfNode(voxel));
117 if(ConfA == ConfB)
118 {
119 value = typeANumber * (typeBNumber - 1) * k;
120 }
121 else
122 {
123 value = typeANumber * typeBNumber * k;
124 }
125
126 if(value < 0)
127 {
128 G4ExceptionDescription exceptionDescription;
129 exceptionDescription
130 << "G4DNAGillespieDirectMethod::PropensityFunction for : "
131 << ConfA->GetName() << "(" << typeANumber << ") + " << ConfB->GetName()
132 << "(" << typeBNumber << ") : propensity : " << value
133 << " GetObservedReactionRateConstant : "
135 << " GetEffectiveReactionRadius : "
136 << G4BestUnit(data->GetEffectiveReactionRadius(), "Length")
137 << " k : " << k << " volume : " << VolumeOfNode(voxel) << G4endl;
138 G4Exception("G4DNAGillespieDirectMethod::PropensityFunction",
139 "G4DNAGillespieDirectMethod013", FatalErrorInArgument,
140 exceptionDescription);
141 }
142
143#ifdef DEBUG
144 if(value > 0)
145 G4cout << "G4DNAGillespieDirectMethod::PropensityFunction for : "
146 << ConfA->GetName() << "(" << typeANumber << ") + "
147 << ConfB->GetName() << "(" << typeBNumber
148 << ") : propensity : " << value
149 << " Time to Reaction : " << G4BestUnit(timeToReaction, "Time")
150 << " k : " << k << " Index : " << index << G4endl;
151#endif
152
153 return value;
154}
155
157{
158 // for Scavenger
159 fpScavengerMaterial = dynamic_cast<G4DNAScavengerMaterial*>(
161
162 auto begin = fpMesh->begin();
163 auto end = fpMesh->end();
164 for(; begin != end; begin++)
165 {
166 auto index = std::get<0>(*begin);
167#ifdef DEBUG
168 fpMesh->PrintVoxel(index);
169#endif
170 CreateEvent(index);
171 }
172}
173
175{
176 fTimeStep = stepTime;
177}
179{
180 const auto& voxel = fpMesh->GetVoxel(index);
181 if(std::get<2>(voxel).empty())
182 {
183 G4ExceptionDescription exceptionDescription;
184 exceptionDescription << "This voxel : " << index
185 << " is not ready to make event" << G4endl;
186 G4Exception("G4DNAGillespieDirectMethod::CreateEvent",
187 "G4DNAGillespieDirectMethod05", FatalErrorInArgument,
188 exceptionDescription);
189 }
190 G4double r1 = G4UniformRand();
191 G4double r2 = G4UniformRand();
192 G4double dAlpha0 = DiffusiveJumping(voxel);
193 G4double rAlpha0 = Reaction(voxel);
194 G4double alphaTotal = dAlpha0 + rAlpha0;
195
196 if(alphaTotal == 0)
197 {
198 return;
199 }
200 auto timeStep = ((1.0 / (alphaTotal)) * std::log(1.0 / r1)) + fTimeStep;
201
202#ifdef DEBUG
203 G4cout << "r2 : " << r2 << " rAlpha0 : " << rAlpha0
204 << " dAlpha0 : " << dAlpha0 << " rAlpha0 / (dAlpha0 + rAlpha0) : "
205 << rAlpha0 / (dAlpha0 + rAlpha0) << G4endl;
206#endif
207 if(r2 < rAlpha0 / alphaTotal)
208 {
209 if(fVerbose > 1)
210 {
211 G4cout << "=>>>>reaction at : " << timeStep << " timeStep : "
212 << G4BestUnit(((1.0 / alphaTotal) * std::log(1.0 / r1)), "Time")
213 << G4endl;
214 }
215 auto rSelectedIter = fReactionDataMap.upper_bound(r2 * alphaTotal);
216 fpEventSet->CreateEvent(timeStep, index, rSelectedIter->second);
217 }
218 else if(dAlpha0 > 0)
219 {
220 if(fVerbose > 1)
221 {
222 G4cout << "=>>>>jumping at : " << timeStep << " timeStep : "
223 << G4BestUnit(((1.0 / alphaTotal) * std::log(1.0 / r1)), "Time")
224 << G4endl;
225 }
226
227 auto dSelectedIter = fJumpingDataMap.upper_bound(r2 * alphaTotal - rAlpha0);
228 auto pDSelected =
229 std::make_unique<std::pair<MolType, Index>>(dSelectedIter->second);
230 fpEventSet->CreateEvent(timeStep, index, std::move(pDSelected));
231 }
232#ifdef DEBUG
233 G4cout << G4endl;
234#endif
235}
236
237G4double G4DNAGillespieDirectMethod::Reaction(const Voxel& voxel)
238{
239 fReactionDataMap.clear();
240 G4double alpha0 = 0;
241 const auto& dataList =
242 fMolecularReactions->GetVectorOfReactionData(); // shoud make a member
243 if(dataList.empty())
244 {
245 G4ExceptionDescription exceptionDescription;
246 exceptionDescription << "MolecularReactionTable empty" << G4endl;
247 G4Exception("G4DNAGillespieDirectMethod::Reaction",
248 "G4DNAGillespieDirectMethod01", FatalErrorInArgument,
249 exceptionDescription);
250 }
251
252 for(const auto& it : dataList)
253 {
254 auto propensity = PropensityFunction(voxel, it);
255 if(propensity == 0)
256 {
257 continue;
258 }
259 alpha0 += propensity;
260 fReactionDataMap[alpha0] = it;
261 }
262#ifdef DEBUG
263 G4cout << "Reaction :alpha0 : " << alpha0 << G4endl;
264#endif
265 return alpha0;
266}
267
268G4double G4DNAGillespieDirectMethod::DiffusiveJumping(const Voxel& voxel)
269{
270 fJumpingDataMap.clear();
271 G4double alpha0 = 0;
272 auto index = std::get<0>(voxel);
273 auto NeighboringVoxels = fpMesh->FindNeighboringVoxels(index);
274 if(NeighboringVoxels.empty())
275 {
276 return 0;
277 }
279 while(iter())
280 {
281 const auto* conf = iter.value();
282 auto propensity = PropensityFunction(voxel, conf);
283 if(propensity == 0)
284 {
285 continue;
286 }
287 for(const auto& it_Neighbor : NeighboringVoxels)
288 {
289 alpha0 += propensity;
290 fJumpingDataMap[alpha0] = std::make_pair(conf, it_Neighbor);
291#ifdef DEBUG
292 G4cout << "mole : " << conf->GetName()
293 << " number : " << ComputeNumberInNode(index, conf)
294 << " propensity : " << propensity << " alpha0 : " << alpha0
295 << G4endl;
296#endif
297 }
298 }
299#ifdef DEBUG
300 G4cout << "DiffusiveJumping :alpha0 : " << alpha0 << G4endl;
301#endif
302 return alpha0;
303}
304
305G4double G4DNAGillespieDirectMethod::ComputeNumberInNode(
306 const Voxel& voxel, MolType type) // depend node ?
307{
308 if(type->GetDiffusionCoefficient() != 0)
309 {
310 const auto& node = std::get<2>(voxel);
311 const auto& it = node.find(type);
312 return (it != node.end()) ? (it->second) : 0;
313 }
314 else
315 {
316 return 0;
317 }
318}
319
320G4bool G4DNAGillespieDirectMethod::FindScavenging(const Voxel& voxel,
321 MolType moletype,
322 G4double& numberOfScavenger)
323{
324 numberOfScavenger = 0;
325 if(fpScavengerMaterial == nullptr)
326 {
327 return false;
328 }
329 auto volumeOfNode = VolumeOfNode(voxel);
330 if(G4MoleculeTable::Instance()->GetConfiguration("H2O") == moletype)
331 {
332 auto factor = Avogadro * volumeOfNode;
333 numberOfScavenger = factor;
334 return true;
335 }
336
337 G4double totalNumber =
339 moletype);
340 if(totalNumber == 0)
341 {
342 return false;
343 }
344 else
345 {
346 G4double numberInDouble = volumeOfNode * std::floor(totalNumber) /
347 fpMesh->GetBoundingBox().Volume();
348 auto numberInInterg = (int64_t) (std::floor(numberInDouble));
349 G4double change = numberInDouble - numberInInterg;
350 G4UniformRand() > change ? numberOfScavenger = numberInInterg
351 : numberOfScavenger = numberInInterg + 1;
352 return true;
353 }
354}
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
#define G4BestUnit(a, b)
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
G4double Volume() const
void CreateEvent(const G4double &time, const Index &index, Event::ReactionData *pReactionData)
void CreateEvent(const Index &index)
G4double PropensityFunction(const Voxel &voxel, ReactionData *data)
void SetTimeStep(const G4double &stepTime)
void PrintVoxel(const Index &index)
Definition: G4DNAMesh.cc:102
auto begin()
Definition: G4DNAMesh.hh:60
Voxel & GetVoxel(const Index &index)
Definition: G4DNAMesh.cc:36
auto end()
Definition: G4DNAMesh.hh:59
const G4DNABoundingBox & GetBoundingBox() const
Definition: G4DNAMesh.cc:140
std::vector< Index > FindNeighboringVoxels(const Index &index) const
Definition: G4DNAMesh.cc:146
G4double GetNumberMoleculePerVolumeUnitForMaterialConf(MolType) const
static G4MoleculeTable * Instance()
G4ConfigurationIterator GetConfigurationIterator()
static G4Scheduler * Instance()
Definition: G4Scheduler.cc:101
G4VScavengerMaterial * GetScavengerMaterial() const
Definition: G4Scheduler.hh:194