Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4DNAScavengerMaterial.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//
28
29#include "G4DNABoundingBox.hh"
33#include "G4Scheduler.hh"
34#include "G4StateManager.hh"
35#include "G4SystemOfUnits.hh"
36#include "G4UnitsTable.hh"
37#include "G4VChemistryWorld.hh"
38
39#include <memory>
40
41using namespace std;
42
43//------------------------------------------------------------------------------
44
46 : fpChemistryInfo(pChemistryInfo), fIsInitialized(false), fCounterAgainstTime(false), fVerbose(0)
47{
48 Initialize();
49}
50
51//------------------------------------------------------------------------------
52
54{
55 if (fIsInitialized) {
56 return;
57 }
58
59 if (fpChemistryInfo->size() == 0) {
60 G4cout << "G4DNAScavengerMaterial existed but empty" << G4endl;
61 }
62 Reset();
63
64 fEquilibriumProcesses.emplace(
65 std::make_pair(6, std::make_unique<G4ChemEquilibrium>(6, 10 * CLHEP::us)));//reactionType6 and 10 * us
66 fEquilibriumProcesses.emplace(
67 std::make_pair(7, std::make_unique<G4ChemEquilibrium>(7, 10 * CLHEP::us)));//reactionType6 and 10 * us
68 fEquilibriumProcesses.emplace(
69 std::make_pair(8, std::make_unique<G4ChemEquilibrium>(8, 10 * CLHEP::us)));//reactionType6 and 10 * us
70 for(auto& it : fEquilibriumProcesses)
71 {
72 it.second->Initialize();
73 it.second->SetVerbose(fVerbose);
74 }
75
76 fIsInitialized = true;
77}
78
81{
82 // no change these molecules
83 if (fH2O == matConf) {
84 return 0;
85 }
86
87 auto iter = fScavengerTable.find(matConf);
88 if (iter == fScavengerTable.end()) {
89 return 0;
90 }
91
92 if (iter->second >= 1) {
93 return (floor)(iter->second);
94 }
95
96 return 0;
97}
98
100 G4double time)
101{
102 // no change these molecules
103 if (fH2O == matConf || fH3Op == matConf || // suppose that pH is not changed during simu
104 fHOm == matConf)
105 {
106 // G4cout<<"moletype : "<<matConf->GetName()<<G4endl;
107 // kobs is already counted these molecule concentrations
108 return;
109 }
110 if (!find(matConf)) // matConf must greater than 0
111 {
112 return;
113 }
114 fScavengerTable[matConf]--;
115 if (fScavengerTable[matConf] < 0) // projection
116 {
117 assert(false);
118 }
119
120 if (fCounterAgainstTime) {
121 RemoveAMoleculeAtTime(matConf, time);
122 }
123}
124
126 G4double time)
127{
128 // no change these molecules
129
130 if (fH2O == matConf || fH3Op == matConf || // pH has no change
131 fHOm == matConf)
132 {
133 // G4cout<<"moletype : "<<matConf->GetName()<<G4endl;
134 // kobs is already counted these molecule concentrations
135 return;
136 }
137
138 auto it = fScavengerTable.find(matConf);
139 if (it == fScavengerTable.end()) // matConf must be in fScavengerTable
140 {
141 return;
142 }
143 fScavengerTable[matConf]++;
144
145 if (fCounterAgainstTime) {
146 AddAMoleculeAtTime(matConf, time);
147 }
148}
149
151{
152 auto pConfinedBox = fpChemistryInfo->GetChemistryBoundary();
153 auto iter = fpChemistryInfo->begin();
154 G4cout << "**************************************************************" << G4endl;
155 for (; iter != fpChemistryInfo->end(); iter++) {
156 auto containedConf = iter->first;
157 // auto concentration = iter->second;
158 auto concentration = fScavengerTable[containedConf] / (Avogadro * pConfinedBox->Volume());
159 G4cout << "Scavenger:" << containedConf->GetName() << " : "
160 << concentration / 1.0e-6 /*mm3 to L*/ << " (M) with : "
161 << fScavengerTable[containedConf] << " (molecules)"
162 << "in: " << pConfinedBox->Volume() / (um * um * um) << " (um3)" << G4endl;
163 if (fScavengerTable[containedConf] < 1) {
164 G4cout << "!!!!!!!!!!!!! this molecule has less one molecule for "
165 "considered volume"
166 << G4endl;
167 // assert(false);
168 }
169 if (fVerbose != 0) {
170 Dump();
171 }
172 }
173 G4cout << "**************************************************************" << G4endl;
174}
175
177{
178 if (fpChemistryInfo == nullptr) {
179 return;
180 }
181
182 if (fpChemistryInfo->size() == 0) {
183 return;
184 }
185
187
188 fScavengerTable.clear();
189 fCounterMap.clear();
190 fpLastSearch.reset(nullptr);
191
192 auto pConfinedBox = fpChemistryInfo->GetChemistryBoundary();
193 auto iter = fpChemistryInfo->begin();
194 for (; iter != fpChemistryInfo->end(); iter++) {
195 auto containedConf = iter->first;
196 auto concentration = iter->second;
197 fScavengerTable[containedConf] = floor(Avogadro * concentration * pConfinedBox->Volume());
198 fCounterMap[containedConf][1 * picosecond] =
199 floor(Avogadro * concentration * pConfinedBox->Volume());
200 }
201 if (fVerbose != 0) {
202 PrintInfo();
203 }
204}
205
206//------------------------------------------------------------------------------
207
209 const G4ThreeVector* /*position*/, int number)
210{
211 if (fVerbose != 0) {
212 G4cout << "G4DNAScavengerMaterial::AddAMoleculeAtTime : " << molecule->GetName()
213 << " at time : " << G4BestUnit(time, "Time") << G4endl;
214 }
215
216 auto counterMap_i = fCounterMap.find(molecule);
217
218 if (counterMap_i == fCounterMap.end()) {
219 fCounterMap[molecule][time] = number;
220 }
221 else if (counterMap_i->second.empty()) {
222 counterMap_i->second[time] = number;
223 }
224 else {
225 auto end = counterMap_i->second.rbegin();
226
227 if (end->first <= time
229 G4double newValue = end->second + number;
230 counterMap_i->second[time] = newValue;
231 if (newValue != (floor)(fScavengerTable[molecule])) // protection
232 {
233 G4String errMsg = "You are trying to add wrong molecule : ";
234 G4cout<< " newValue : "<<newValue<<" " << molecule->GetName()
235 << " at time : " << G4BestUnit(time, "Time")
236 << " with number : " << number
237 <<" (floor)(fScavengerTable[molecule]) : "<<(floor)(fScavengerTable[molecule])
238 << " and the final number is not valid." << G4endl;
239 G4Exception("AddAMoleculeAtTime", "", FatalErrorInArgument, errMsg);
240 }
241 }
242 }
243}
244
245//------------------------------------------------------------------------------
246
248 const G4ThreeVector* /*position*/, int number)
249{
250 NbMoleculeInTime& nbMolPerTime = fCounterMap[pMolecule];
251
252 if (fVerbose != 0) {
253 auto it_ = nbMolPerTime.rbegin();
254 G4cout << "G4DNAScavengerMaterial::RemoveAMoleculeAtTime : " << pMolecule->GetName()
255 << " at time : " << G4BestUnit(time, "Time")
256
257 << " form : " << it_->second << G4endl;
258 }
259
260 if (nbMolPerTime.empty()) {
261 Dump();
262 G4String errMsg = "You are trying to remove molecule " +
263 pMolecule->GetName() +
264 " from the counter while this kind of molecules has not "
265 "been registered yet";
266 G4Exception("G4DNAScavengerMaterial::RemoveAMoleculeAtTime", "", FatalErrorInArgument, errMsg);
267
268 return;
269 }
270
271 auto it = nbMolPerTime.rbegin();
272
273 if (it == nbMolPerTime.rend()) {
274 it--;
275
276 G4String errMsg = "There was no " + pMolecule->GetName()
277 + " recorded at the time or even before the time asked";
278 G4Exception("G4DNAScavengerMaterial::RemoveAMoleculeAtTime", "", FatalErrorInArgument, errMsg);
279 }
280
281 G4double finalN = it->second - number;
282 if (finalN < 0) {
283 Dump();
284
285 G4cout << "fScavengerTable : " << pMolecule->GetName() << " : " << (fScavengerTable[pMolecule])
286 << G4endl;
287
289 errMsg << "After removal of " << number << " species of "
290 << " " << it->second << " " << pMolecule->GetName() << " the final number at time "
291 << G4BestUnit(time, "Time") << " is less than zero and so not valid." << G4endl;
292 G4cout << " Global time is " << G4BestUnit(G4Scheduler::Instance()->GetGlobalTime(), "Time")
293 << ". Previous selected time is " << G4BestUnit(it->first, "Time") << G4endl;
294 G4Exception("G4DNAScavengerMaterial::RemoveAMoleculeAtTime", "N_INF_0", FatalException, errMsg);
295 }
296 nbMolPerTime[time] = finalN;
297
298 if (finalN != (floor)(fScavengerTable[pMolecule])) // protection
299 {
300 assert(false);
301 }
302}
303
305{
306 auto pConfinedBox = fpChemistryInfo->GetChemistryBoundary();
307 auto V = pConfinedBox->Volume();
308 for (const auto& it : fCounterMap) {
309 auto pReactant = it.first;
310
311 G4cout << " --- > For " << pReactant->GetName() << G4endl;
312
313 for (const auto& it2 : it.second) {
314 G4cout << " " << G4BestUnit(it2.first, "Time") << " "
315 << it2.second / (Avogadro * V * 1.0e-6 /*mm3 to L*/) << G4endl;
316 }
317 }
318}
319
321{
322 if (!fCounterAgainstTime) {
323 G4cout << "fCounterAgainstTime == false" << G4endl;
324 assert(false);
325 }
326
327 G4bool sameTypeOfMolecule = SearchTimeMap(molecule);
328 auto output = SearchUpperBoundTime(time, sameTypeOfMolecule);
329 if (output < 0) {
331 errMsg << "N molecules not valid < 0 : " << molecule->GetName() << " N : " << output << G4endl;
332 G4Exception("G4DNAScavengerMaterial::GetNMoleculesAtTime", "", FatalErrorInArgument, errMsg);
333 }
334 return output;
335}
336
338{
339 if (fpLastSearch == nullptr) {
340 fpLastSearch = std::make_unique<Search>();
341 }
342 else {
343 if (fpLastSearch->fLowerBoundSet && fpLastSearch->fLastMoleculeSearched->first == molecule) {
344 return true;
345 }
346 }
347
348 auto mol_it = fCounterMap.find(molecule);
349 fpLastSearch->fLastMoleculeSearched = mol_it;
350
351 if (mol_it != fCounterMap.end()) {
352 fpLastSearch->fLowerBoundTime = fpLastSearch->fLastMoleculeSearched->second.end();
353 fpLastSearch->fLowerBoundSet = true;
354 }
355 else {
356 fpLastSearch->fLowerBoundSet = false;
357 }
358
359 return false;
360}
361
362//------------------------------------------------------------------------------
363
365{
366 auto mol_it = fpLastSearch->fLastMoleculeSearched;
367 if (mol_it == fCounterMap.end()) {
368 return 0;
369 }
370
371 NbMoleculeInTime& timeMap = mol_it->second;
372 if (timeMap.empty()) {
373 return 0;
374 }
375
376 if (sameTypeOfMolecule) {
377 if (fpLastSearch->fLowerBoundSet && fpLastSearch->fLowerBoundTime != timeMap.end()) {
378 if (fpLastSearch->fLowerBoundTime->first < time) {
379 auto upperToLast = fpLastSearch->fLowerBoundTime;
380 upperToLast++;
381
382 if (upperToLast == timeMap.end()) {
383 return fpLastSearch->fLowerBoundTime->second;
384 }
385
386 if (upperToLast->first > time) {
387 return fpLastSearch->fLowerBoundTime->second;
388 }
389 }
390 }
391 }
392
393 auto up_time_it = timeMap.upper_bound(time);
394
395 if (up_time_it == timeMap.end()) {
396 auto last_time = timeMap.rbegin();
397 return last_time->second;
398 }
399 if (up_time_it == timeMap.begin()) {
400 return 0;
401 }
402
403 up_time_it--;
404
405 fpLastSearch->fLowerBoundTime = up_time_it;
406 fpLastSearch->fLowerBoundSet = true;
407
408 return fpLastSearch->fLowerBoundTime->second;
409}
410
411void G4DNAScavengerMaterial::WaterEquilibrium()
412{
413 auto convertFactor = Avogadro * fpChemistryInfo->GetChemistryBoundary()->Volume() / liter;
414 G4double kw = 1.01e-14;
415 fScavengerTable[fHOm] = (kw / ((G4double)fScavengerTable[fH3Op] / convertFactor)) * convertFactor;
416 G4cout << "pH : " << GetpH() << G4endl;
417 return;
418}
419
421{
422 auto volume = fpChemistryInfo->GetChemistryBoundary()->Volume();
423 fScavengerTable[fH3Op] = floor(Avogadro * std::pow(10, -ph) * volume / liter);
424 fScavengerTable[fHOm] = floor(Avogadro * std::pow(10, -(14 - ph)) * volume / liter);
425}
426
428{
429 G4double volumeInLiter = fpChemistryInfo->GetChemistryBoundary()->Volume() / liter;
430 G4double Cion = (G4double)fScavengerTable[fH3Op] / (Avogadro * volumeInLiter);
431 G4double pH = std::log10(Cion);
432 // G4cout<<"OH- : "<<fScavengerTable[fHOm]<<" H3O+ : "<<fScavengerTable[fH3Op]<<" pH :
433 // "<<-pH<<G4endl;
434 if (fScavengerTable[fH3Op] < 0) // protect me
435 {
436 G4Exception("G4DNAScavengerMaterial::GetpH()", "G4DNAScavengerMaterial001", JustWarning,
437 "H3O+ < 0");
438 fScavengerTable[fH3Op] = 0;
439 }
440 if (fScavengerTable[fHOm] < 0) // protect me
441 {
442 G4Exception("G4DNAScavengerMaterial::GetpH()", "G4DNAScavengerMaterial001", JustWarning,
443 "HO- < 0");
444 fScavengerTable[fHOm] = 0;
445 }
446 return -pH;
447}
448
450 G4double time)
451{
452 for(auto& it : fEquilibriumProcesses)
453 {
454 it.second->SetGlobalTime(time);
455 it.second->SetEquilibrium(pReaction);
456 if(it.second->IsStatusChanged()) return true;
457 }
458 return false;
459}
460
462{
463 for(auto& it : fEquilibriumProcesses)
464 {
465 it.second->Reset();
466 }
467}
468
470{
471 auto reaction = fEquilibriumProcesses.find(reactionType);
472 if(reaction == fEquilibriumProcesses.end())
473 {
474 return true;
475 }else
476 {
477 return (reaction->second->GetEquilibriumStatus());
478 }
479
480}
@ JustWarning
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
#define G4BestUnit(a, b)
CLHEP::Hep3Vector G4ThreeVector
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
G4double Volume() const
G4double GetNumberMoleculePerVolumeUnitForMaterialConf(MolType) const
MaterialMap::iterator end()
G4bool IsEquilibrium(const G4int &reactionType) const
int64_t SearchUpperBoundTime(G4double time, G4bool sameTypeOfMolecule)
G4bool SetEquilibrium(const G4DNAMolecularReactionData *pReaction, G4double time)
std::map< G4double, int64_t, G4::MoleculeCounter::FixedTimeComparer > NbMoleculeInTime
void ReduceNumberMoleculePerVolumeUnitForMaterialConf(MolType, G4double)
void AddAMoleculeAtTime(MolType, G4double time, const G4ThreeVector *position=nullptr, G4int number=1)
int64_t GetNMoleculesAtTime(MolType molecule, G4double time)
void AddNumberMoleculePerVolumeUnitForMaterialConf(MolType, G4double)
G4DNAScavengerMaterial()=default
G4bool SearchTimeMap(MolType molecule)
void RemoveAMoleculeAtTime(MolType, G4double time, const G4ThreeVector *position=nullptr, G4int number=1)
const G4MolecularConfiguration * MolType
const G4String & GetName() const
static G4Scheduler * Instance()
G4DNABoundingBox * GetChemistryBoundary() const