Geant4 11.2.2
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#include "G4ChemEquilibrium.hh"
37
41
43
45{
46 fpEventSet = pEventSet;
47}
48
49//#define DEBUG 1
50
51G4double G4DNAGillespieDirectMethod::VolumeOfNode(const Voxel& voxel)
52{
53 auto box = std::get<1>(voxel);
54 auto LengthY = box.Getyhi() - box.Getylo();
55 auto LengthX = box.Getxhi() - box.Getxlo();
56 auto LengthZ = box.Getzhi() - box.Getzlo();
57 G4double V = LengthY * LengthX * LengthZ;
58 if(V <= 0)
59 {
60 G4ExceptionDescription exceptionDescription;
61 exceptionDescription << "V > 0 !! ";
62 G4Exception("G4DNAGillespieDirectMethod::VolumeOfNode",
63 "G4DNAGillespieDirectMethod03", FatalErrorInArgument,
64 exceptionDescription);
65 }
66 return V;
67}
69 MolType moleType)
70{
71 if(moleType->GetDiffusionCoefficient() == 0)
72 {
73 return 0.;
74 }
75 const auto& node = std::get<2>(voxel);
76 const auto& box = std::get<1>(voxel);
77
78 G4double alpha = 0;
79 auto it = node.find(moleType);
80 if(it != node.end())
81 {
82 auto LengthY = box.Getyhi() - box.Getylo();
83 G4double d = it->first->GetDiffusionCoefficient() / std::pow(LengthY, 2);
84 alpha = d * it->second;
85
86#ifdef DEBUG
87 G4cout << it->first->GetName() << " " << it->second
88 << " D : " << it->first->GetDiffusionCoefficient()
89 << " LengthY : " << LengthY << " PropensityFunction : " << alpha
90 << G4endl;
91#endif
92 }
93 return alpha;
94}
95
97 ReactionData* data)
98{
99 G4double value;
100 auto ConfA = data->GetReactant1();
101 auto ConfB = data->GetReactant2();
102 G4double scavengerNumber = 0;
103 auto typeANumber = FindScavenging(voxel, ConfA, scavengerNumber)
104 ? scavengerNumber
105 : ComputeNumberInNode(voxel, ConfA);
106
107 auto typeBNumber = FindScavenging(voxel, ConfB, scavengerNumber)
108 ? scavengerNumber
109 : ComputeNumberInNode(voxel, ConfB);
110
111 if(typeANumber == 0 || typeBNumber == 0)
112 {
113 return 0;
114 }
115
116 auto k =
117 data->GetObservedReactionRateConstant() / (Avogadro * VolumeOfNode(voxel));
118 if(ConfA == ConfB)
119 {
120 value = typeANumber * (typeBNumber - 1) * k;
121 }
122 else
123 {
124 value = typeANumber * typeBNumber * k;
125 }
126
127 if(value < 0)
128 {
129 G4ExceptionDescription exceptionDescription;
130 exceptionDescription
131 << "G4DNAGillespieDirectMethod::PropensityFunction for : "
132 << ConfA->GetName() << "(" << typeANumber << ") + " << ConfB->GetName()
133 << "(" << typeBNumber << ") : propensity : " << value
134 << " GetObservedReactionRateConstant : "
136 << " GetEffectiveReactionRadius : "
137 << G4BestUnit(data->GetEffectiveReactionRadius(), "Length")
138 << " k : " << k << " volume : " << VolumeOfNode(voxel) << G4endl;
139 G4Exception("G4DNAGillespieDirectMethod::PropensityFunction",
140 "G4DNAGillespieDirectMethod013", FatalErrorInArgument,
141 exceptionDescription);
142 }
143
144#ifdef DEBUG
145 if(value > 0)
146 G4cout << "G4DNAGillespieDirectMethod::PropensityFunction for : "
147 << ConfA->GetName() << "(" << typeANumber << ") + "
148 << ConfB->GetName() << "(" << typeBNumber
149 << ") : propensity : " << value
150 << " Time to Reaction : " << G4BestUnit(timeToReaction, "Time")
151 << " k : " << k << " Index : " << index << G4endl;
152#endif
153
154 return value;
155}
156
158{
159 // for Scavenger
160 fpScavengerMaterial = dynamic_cast<G4DNAScavengerMaterial*>(
162 fEquilibriumProcesses.emplace(
163 std::make_pair(6, std::make_unique<G4ChemEquilibrium>(6, 10 * CLHEP::us)));//reactionType6 and 10 * us
164 fEquilibriumProcesses.emplace(
165 std::make_pair(7, std::make_unique<G4ChemEquilibrium>(7, 10 * CLHEP::us)));//reactionType6 and 10 * us
166 fEquilibriumProcesses.emplace(
167 std::make_pair(8, std::make_unique<G4ChemEquilibrium>(8, 10 * CLHEP::us)));//reactionType6 and 10 * us
168 for(auto& it : fEquilibriumProcesses)
169 {
170 it.second->Initialize();
171 it.second->SetVerbose(fVerbose);
172 }
173}
174
176{
177 auto begin = fpMesh->begin();
178 auto end = fpMesh->end();
179 for(; begin != end; begin++)
180 {
181 auto index = std::get<0>(*begin);
182#ifdef DEBUG
183 fpMesh->PrintVoxel(index);
184#endif
185 CreateEvent(index);
186 }
187}
188
190{
191 fTimeStep = stepTime;
192}
194{
195 const auto& voxel = fpMesh->GetVoxel(index);
196 if(std::get<2>(voxel).empty())
197 {
198 G4ExceptionDescription exceptionDescription;
199 exceptionDescription << "This voxel : " << index
200 << " is not ready to make event" << G4endl;
201 G4Exception("G4DNAGillespieDirectMethod::CreateEvent",
202 "G4DNAGillespieDirectMethod05", FatalErrorInArgument,
203 exceptionDescription);
204 }
205 G4double r1 = G4UniformRand();
206 G4double r2 = G4UniformRand();
207 G4double dAlpha0 = DiffusiveJumping(voxel);
208 G4double rAlpha0 = Reaction(voxel);
209 G4double alphaTotal = dAlpha0 + rAlpha0;
210
211 if(alphaTotal == 0)
212 {
213 return;
214 }
215 auto timeStep = ((1.0 / (alphaTotal)) * std::log(1.0 / r1)) + fTimeStep;
216
217#ifdef DEBUG
218 G4cout << "r2 : " << r2 << " rAlpha0 : " << rAlpha0
219 << " dAlpha0 : " << dAlpha0 << " rAlpha0 / (dAlpha0 + rAlpha0) : "
220 << rAlpha0 / (dAlpha0 + rAlpha0) << G4endl;
221#endif
222 if(r2 < rAlpha0 / alphaTotal)
223 {
224 if(fVerbose > 1)
225 {
226 G4cout << "=>>>>reaction at : " << timeStep << " timeStep : "
227 << G4BestUnit(((1.0 / alphaTotal) * std::log(1.0 / r1)), "Time")
228 << G4endl;
229 }
230 auto rSelectedIter = fReactionDataMap.upper_bound(r2 * alphaTotal);
231 fpEventSet->CreateEvent(timeStep, index, rSelectedIter->second);
232 }
233 else if(dAlpha0 > 0)
234 {
235 if(fVerbose > 1)
236 {
237 G4cout << "=>>>>jumping at : " << timeStep << " timeStep : "
238 << G4BestUnit(((1.0 / alphaTotal) * std::log(1.0 / r1)), "Time")
239 << G4endl;
240 }
241
242 auto dSelectedIter = fJumpingDataMap.upper_bound(r2 * alphaTotal - rAlpha0);
243 auto pDSelected =
244 std::make_unique<std::pair<MolType, Index>>(dSelectedIter->second);
245 fpEventSet->CreateEvent(timeStep, index, std::move(pDSelected));
246 }
247#ifdef DEBUG
248 G4cout << G4endl;
249#endif
250}
251
252G4double G4DNAGillespieDirectMethod::Reaction(const Voxel& voxel)
253{
254 fReactionDataMap.clear();
255 G4double alpha0 = 0;
256 const auto& dataList =
257 fMolecularReactions->GetVectorOfReactionData(); // shoud make a member
258 if(dataList.empty())
259 {
260 G4ExceptionDescription exceptionDescription;
261 exceptionDescription << "MolecularReactionTable empty" << G4endl;
262 G4Exception("G4DNAGillespieDirectMethod::Reaction",
263 "G4DNAGillespieDirectMethod01", FatalErrorInArgument,
264 exceptionDescription);
265 }
266
267 for(const auto& it : dataList)
268 {
269 if(!IsEquilibrium(it->GetReactionType()))
270 {
271 continue;
272 }
273 auto propensity = PropensityFunction(voxel, it);
274 if(propensity == 0)
275 {
276 continue;
277 }
278 alpha0 += propensity;
279 fReactionDataMap[alpha0] = it;
280 }
281#ifdef DEBUG
282 G4cout << "Reaction :alpha0 : " << alpha0 << G4endl;
283#endif
284 return alpha0;
285}
286
287G4double G4DNAGillespieDirectMethod::DiffusiveJumping(const Voxel& voxel)
288{
289 fJumpingDataMap.clear();
290 G4double alpha0 = 0;
291 auto index = std::get<0>(voxel);
292 auto NeighboringVoxels = fpMesh->FindNeighboringVoxels(index);
293 if(NeighboringVoxels.empty())
294 {
295 return 0;
296 }
298 while(iter())
299 {
300 const auto* conf = iter.value();
301 auto propensity = PropensityFunction(voxel, conf);
302 if(propensity == 0)
303 {
304 continue;
305 }
306 for(const auto& it_Neighbor : NeighboringVoxels)
307 {
308 alpha0 += propensity;
309 fJumpingDataMap[alpha0] = std::make_pair(conf, it_Neighbor);
310#ifdef DEBUG
311 G4cout << "mole : " << conf->GetName()
312 << " number : " << ComputeNumberInNode(index, conf)
313 << " propensity : " << propensity << " alpha0 : " << alpha0
314 << G4endl;
315#endif
316 }
317 }
318#ifdef DEBUG
319 G4cout << "DiffusiveJumping :alpha0 : " << alpha0 << G4endl;
320#endif
321 return alpha0;
322}
323
324G4double G4DNAGillespieDirectMethod::ComputeNumberInNode(
325 const Voxel& voxel, MolType type) // depend node ?
326{
327 if(type->GetDiffusionCoefficient() != 0)
328 {
329 const auto& node = std::get<2>(voxel);
330 const auto& it = node.find(type);
331 return (it != node.end()) ? (it->second) : 0;
332 }
333 return 0;
334}
335
336G4bool G4DNAGillespieDirectMethod::FindScavenging(const Voxel& voxel,
337 MolType moletype,
338 G4double& numberOfScavenger)
339{
340 numberOfScavenger = 0;
341 if(fpScavengerMaterial == nullptr)
342 {
343 return false;
344 }
345 auto volumeOfNode = VolumeOfNode(voxel);
346 if(G4MoleculeTable::Instance()->GetConfiguration("H2O") == moletype)
347 {
348 auto factor = Avogadro * volumeOfNode;
349 numberOfScavenger = factor;
350 return true;
351 }
352
353 G4double totalNumber =
355 moletype);
356 if(totalNumber == 0)
357 {
358 return false;
359 }
360
361 G4double numberInDouble = volumeOfNode * std::floor(totalNumber) /
362 fpMesh->GetBoundingBox().Volume();
363 auto numberInInterg = (int64_t) (std::floor(numberInDouble));
364 G4double change = numberInDouble - numberInInterg;
365 G4UniformRand() > change ? numberOfScavenger = numberInInterg
366 : numberOfScavenger = numberInInterg + 1;
367 return true;
368}
369
370G4bool G4DNAGillespieDirectMethod::IsEquilibrium(const G4int& reactionType) const
371{
372 auto reaction = fEquilibriumProcesses.find(reactionType);
373 if(reaction == fEquilibriumProcesses.end())
374 {
375 return true;
376 }else
377 {
378 return (reaction->second->GetEquilibriumStatus());
379 }
380
381}
382
384{
385 for(auto& it : fEquilibriumProcesses)
386 {
387 it.second->SetGlobalTime(fTimeStep);
388 it.second->SetEquilibrium(pReaction);
389 if(it.second->IsStatusChanged()) return true;
390 }
391 return false;
392}
393
395{
396 for(auto& it : fEquilibriumProcesses)
397 {
398 it.second->Reset();
399 }
400}
401
402
403
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
#define G4BestUnit(a, b)
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
#define G4UniformRand()
Definition Randomize.hh:52
G4double Volume() const
void CreateEvent(const G4double &time, const Index &index, Event::ReactionData *pReactionData)
G4bool SetEquilibrium(const G4DNAMolecularReactionData *pReaction)
G4double PropensityFunction(const Voxel &voxel, ReactionData *data)
void SetTimeStep(const G4double &stepTime)
void PrintVoxel(const Index &index)
Definition G4DNAMesh.cc:100
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:138
std::vector< Index > FindNeighboringVoxels(const Index &index) const
Definition G4DNAMesh.cc:144
G4double GetNumberMoleculePerVolumeUnitForMaterialConf(MolType) const
static G4MoleculeTable * Instance()
G4ConfigurationIterator GetConfigurationIterator()
static G4Scheduler * Instance()
G4VScavengerMaterial * GetScavengerMaterial() const