Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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