Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/dna/models/src/G4DNATripleIonisationModel.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 // G4DNATripleIonisationModel.cc
 27 //
 28 //  Created at 2024/04/03 (Thu.)
 29 //  Author: Shogo OKADA @KEK-CRC (shogo.okada@kek.jp)
 30 //
 31 //  Reference: J.Meesungnoen et. al, DOI: 10.1021/jp058037z
 32 //
 33 
 34 #include "G4DNATripleIonisationModel.hh"
 35 
 36 #include "G4PhysicalConstants.hh"
 37 #include "G4SystemOfUnits.hh"
 38 #include "G4UAtomicDeexcitation.hh"
 39 #include "G4LossTableManager.hh"
 40 
 41 #include "G4SystemOfUnits.hh"
 42 #include "G4DNAMolecularMaterial.hh"
 43 #include "G4IonTable.hh"
 44 #include "G4GenericIon.hh"
 45 #include "G4DNARuddAngle.hh"
 46 
 47 #include <sstream>
 48 
 49 namespace {
 50 
 51 G4DNAWaterIonisationStructure water_structure;
 52 
 53 } // end of anonymous namespace
 54 
 55 //==============================================================================
 56 
 57 // constructor
 58 G4DNATripleIonisationModel::G4DNATripleIonisationModel(
 59   const G4ParticleDefinition* p, const G4String& model_name)
 60     : G4DNADoubleIonisationModel(p, model_name)
 61 {
 62   // Triple-ionisation energy
 63   energy_threshold_ = 65.0 * eV;
 64 }
 65 
 66 //------------------------------------------------------------------------------
 67 void G4DNATripleIonisationModel::Initialise(
 68   const G4ParticleDefinition* particle, const G4DataVector&)
 69 {
 70   if (verbose_level_ > 3) {
 71     G4cout << "Calling G4DNATripleIonisationModel::Initialise()" << G4endl;
 72   }
 73 
 74   proton_def_ = G4Proton::ProtonDefinition();
 75   alpha_def_  = G4DNAGenericIonsManager::Instance()->GetIon("alpha++");
 76   carbon_def_ = G4IonTable::GetIonTable()->GetIon(6, 12);
 77 
 78   constexpr G4double kScaleFactor = 1.0 * m * m;
 79 
 80   mioni_manager_ = new G4DNAMultipleIonisationManager();
 81 
 82   G4double Z{0.0}, A{0.0};
 83   G4String alpha_param_file{"dna/multipleionisation_alphaparam_champion.dat"};
 84 
 85   if (particle == proton_def_) {
 86 
 87     // *************************************************************************
 88     // for protons
 89     const auto& proton = proton_def_->GetParticleName();
 90     elow_tab_[proton] = model_elow_tab_[1];
 91     eupp_tab_[proton] = 3.0 * MeV;
 92 
 93     // load cross-section data for single ionization process
 94     auto xs_proton = new G4DNACrossSectionDataSet(
 95                           new G4LogLogInterpolation, eV, kScaleFactor);
 96     xs_proton->LoadData("dna/sigma_ionisation_p_rudd");
 97     xs_tab_[proton] = xs_proton;
 98 
 99     // set energy limits
100     SetLowEnergyLimit(elow_tab_[proton]);
101     SetHighEnergyLimit(eupp_tab_[proton]);
102 
103     if (!use_champion_param_) {
104       alpha_param_file = "dna/multipleionisation_alphaparam_p.dat";
105     }
106 
107     Z = static_cast<G4double>(proton_def_->GetAtomicNumber());
108     A = static_cast<G4double>(proton_def_->GetAtomicMass());
109 
110   } else if (particle == alpha_def_) {
111 
112     //**************************************************************************
113     // for alpha particles
114     const auto& alpha = alpha_def_->GetParticleName();
115     elow_tab_[alpha] = model_elow_tab_[4];
116     eupp_tab_[alpha] = 23.0 * MeV;
117 
118     // load cross-section data for single ionization process
119     auto xs_alpha = new G4DNACrossSectionDataSet(
120                         new G4LogLogInterpolation, eV, kScaleFactor);
121     xs_alpha->LoadData("dna/sigma_ionisation_alphaplusplus_rudd");
122     xs_tab_[alpha] = xs_alpha;
123 
124     // set energy limits
125     SetLowEnergyLimit(elow_tab_[alpha]);
126     SetHighEnergyLimit(eupp_tab_[alpha]);
127 
128     if (!use_champion_param_) {
129       alpha_param_file = "dna/multipleionisation_alphaparam_alphaplusplus.dat";
130     }
131 
132     Z = static_cast<G4double>(alpha_def_->GetAtomicNumber());
133     A = static_cast<G4double>(alpha_def_->GetAtomicMass());
134 
135   } else if (particle == G4GenericIon::GenericIonDefinition()) {
136 
137     // *************************************************************************
138     // for carbon ions
139     const auto& carbon = carbon_def_->GetParticleName();
140     elow_tab_[carbon] = model_elow_tab_[5] * carbon_def_->GetAtomicMass();
141     eupp_tab_[carbon] = 120.0 * MeV;
142 
143     // load cross-section data for single ionization process
144     auto xs_carbon = new G4DNACrossSectionDataSet(
145                         new G4LogLogInterpolation, eV, kScaleFactor);
146     xs_carbon->LoadData("dna/sigma_ionisation_c_rudd");
147     xs_tab_[carbon] = xs_carbon;
148 
149     // set energy limits
150     SetLowEnergyLimit(elow_tab_[carbon]);
151     SetHighEnergyLimit(eupp_tab_[carbon]);
152 
153     if (!use_champion_param_) {
154       alpha_param_file = "dna/multipleionisation_alphaparam_c.dat";
155     }
156 
157     Z = static_cast<G4double>(carbon_def_->GetAtomicNumber());
158     A = static_cast<G4double>(carbon_def_->GetAtomicMass());
159 
160   }
161 
162   // load alpha parameter
163   mioni_manager_->LoadAlphaParam(alpha_param_file, Z, A);
164 
165   if (verbose_level_ > 0) {
166     G4cout << "G4DNATripleIonisationModel is initialized " << G4endl
167            << "Energy range: "
168            << LowEnergyLimit() / eV << " eV - "
169            << HighEnergyLimit() / keV << " keV for "
170            << particle->GetParticleName()
171            << G4endl;
172   }
173 
174   water_density_ = G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(
175                       G4Material::GetMaterial("G4_WATER"));
176 
177   atom_deex_ = G4LossTableManager::Instance()->AtomDeexcitation();
178 
179   if (is_initialized_) { return; }
180 
181   particle_change_ = GetParticleChangeForGamma();
182   is_initialized_ = true;
183 }
184 
185 //------------------------------------------------------------------------------
186 G4double G4DNATripleIonisationModel::CrossSectionPerVolume(
187   const G4Material* material, const G4ParticleDefinition* pdef,
188   G4double ekin, G4double, G4double)
189 {
190 
191   if (verbose_level_ > 3) {
192     G4cout << "Calling G4DNATripleIonisationModel::CrossSectionPerVolume()"
193            << G4endl;
194   }
195 
196   // Calculate total cross section for model
197 
198   if (pdef != proton_def_ && pdef != alpha_def_ && pdef != carbon_def_) {
199     return 0.0;
200   }
201 
202   static G4double water_dens = (*water_density_)[material->GetIndex()];
203 
204   const auto& pname = pdef->GetParticleName();
205 
206   const auto low_energy_lim = GetLowEnergyLimit(pname);
207   const auto upp_energy_lim = GetUppEnergyLimit(pname);
208 
209   G4double sigma{0.0};
210   if (ekin <= upp_energy_lim) {
211 
212     if (ekin < low_energy_lim) { ekin = low_energy_lim; }
213 
214     CrossSectionDataTable::iterator pos = xs_tab_.find(pname);
215     if (pos == xs_tab_.end()) {
216       G4Exception("G4DNATripleIonisationModel::CrossSectionPerVolume",
217                   "em0002", FatalException,
218                   "Model not applicable to particle type.");
219     }
220 
221     G4DNACrossSectionDataSet* table = pos->second;
222     if (table != nullptr) {
223       const auto a = mioni_manager_->GetAlphaParam(ekin);
224       sigma = table->FindValue(ekin) * a * a;
225     }
226 
227   }
228 
229   if (verbose_level_ > 2) {
230 
231     std::stringstream msg;
232 
233     msg << "----------------------------------------------------------------\n";
234     msg << " G4DNATripleIonisationModel - XS INFO START\n";
235     msg << "  - Kinetic energy(eV): " << ekin/eV << ", Particle : "
236         << pdef->GetParticleName() << "\n";
237     msg << "  - Cross section per water molecule (cm^2):  "
238         << sigma / cm / cm << "\n";
239     msg << "  - Cross section per water molecule (cm^-1): "
240         << sigma * water_dens / (1.0 / cm) << "\n";
241     msg << " G4DNATripleIonisationModel - XS INFO END\n";
242     msg << "----------------------------------------------------------------\n";
243 
244     G4cout << msg.str() << G4endl;
245 
246   }
247 
248   return (sigma * water_dens);
249 
250 }
251 
252 //------------------------------------------------------------------------------
253 void G4DNATripleIonisationModel::SampleSecondaries(
254   std::vector<G4DynamicParticle*>* vsec, const G4MaterialCutsCouple* couple,
255   const G4DynamicParticle* particle, G4double, G4double)
256 {
257 
258   if (verbose_level_ > 3) {
259     G4cout << "Calling SampleSecondaries() of G4DNATripleIonisationModel"
260            << G4endl;
261   }
262 
263   // get the definition for this parent particle
264   auto pdef = particle->GetDefinition();
265 
266   // get kinetic energy
267   auto ekin = particle->GetKineticEnergy();
268 
269   // get particle name
270   const auto& pname = pdef->GetParticleName();
271 
272   // get energy limits
273   const auto low_energy_lim = GetLowEnergyLimit(pname);
274 
275   // ***************************************************************************
276   // stop the transportation process of this parent particle
277   // if its kinetic energy  is below the lower limit
278   if (ekin < low_energy_lim) {
279     particle_change_->SetProposedKineticEnergy(0.0);
280     particle_change_->ProposeTrackStatus(fStopAndKill);
281     particle_change_->ProposeLocalEnergyDeposit(ekin);
282     return;
283   }
284   // ***************************************************************************
285 
286   constexpr G4int kNumSecondaries = 3;
287   constexpr G4double kDeltaTheta  = pi * 0.666666667;
288 
289   G4int ioni_shell[kNumSecondaries] = {0, 0, 0};
290   G4double shell_energy[kNumSecondaries];
291 
292   auto scale_param = mioni_manager_->GetAlphaParam(ekin);
293   scale_param *= scale_param;
294 
295   G4bool is_continue{true};
296   while (1) {
297     ioni_shell[0] = RandomSelect(ekin, scale_param, pname);
298     ioni_shell[1] = RandomSelect(ekin, scale_param, pname);
299     ioni_shell[2] = RandomSelect(ekin, scale_param, pname);
300     is_continue = (ioni_shell[0] == ioni_shell[1] &&
301                    ioni_shell[1] == ioni_shell[2]);
302     if (!is_continue) { break; }
303   }
304 
305   G4double tot_ioni_energy{0.0};
306   for (int i = 0; i < kNumSecondaries; i++) {
307     shell_energy[i] = ::water_structure.IonisationEnergy(ioni_shell[i]);
308     tot_ioni_energy += shell_energy[i];
309   }
310 
311   if (ekin < tot_ioni_energy || tot_ioni_energy < energy_threshold_) {
312     return;
313   }
314 
315   // generate secondary electrons
316   G4double theta{0.0}, phi{0.0}, tot_ekin2{0.0};
317   for (int i = 0; i < kNumSecondaries; i++) {
318     tot_ekin2 += GenerateSecondaries(vsec, couple, particle, ioni_shell[i],
319                                      theta, phi, shell_energy[i]);
320     theta += kDeltaTheta;
321   }
322 
323   // This should never happen
324   if (mioni_manager_->CheckShellEnergy(eTripleIonisedMolecule, shell_energy)) {
325     G4Exception("G4DNATripleIonisatioModel::SampleSecondaries()",
326         "em2050", FatalException, "Negative local energy deposit");
327   }
328 
329   // ***************************************************************************
330   // update kinematics for this parent particle
331   const auto primary_dir = particle->GetMomentumDirection();
332   particle_change_->ProposeMomentumDirection(primary_dir);
333 
334   const auto scattered_energy = ekin - tot_ioni_energy - tot_ekin2;
335 
336   // update total amount of shell energy
337   tot_ioni_energy = shell_energy[0] + shell_energy[1] + shell_energy[2];
338 
339   if (stat_code_) {
340     particle_change_->SetProposedKineticEnergy(ekin);
341     particle_change_->ProposeLocalEnergyDeposit(
342                                 ekin - scattered_energy);
343   } else {
344     particle_change_->SetProposedKineticEnergy(scattered_energy);
345     particle_change_->ProposeLocalEnergyDeposit(tot_ioni_energy);
346   }
347 
348   // ***************************************************************************
349   // generate triple-ionized water molecules (H2O^3+)
350   const auto the_track = particle_change_->GetCurrentTrack();
351   mioni_manager_->CreateMultipleIonisedWaterMolecule(
352                     eTripleIonisedMolecule, ioni_shell, the_track);
353   // ***************************************************************************
354 
355 }
356