Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/dna/utils/src/G4DNAScavengerMaterial.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

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