Import Geant4 11.4.0 source tree
This commit is contained in:
@@ -6,6 +6,43 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2025-10-18 Sebastien Incerti, Wook Geun Shin (emdna-V11-03-20)
|
||||
- Extended G4DNAELSEPAElasticModel up to 10 MeV for water.
|
||||
Requires G4EMLOW8.8
|
||||
|
||||
## 2025-10-10 Le Tuan Anh (emdna-V11-03-19)
|
||||
- Changed the condition in calculateDistanceFromTimeStep
|
||||
(G4ChemReboundTransportation) to allow calculate even with DiffusionCoefficient = 0.
|
||||
|
||||
## 2025-09-30 Vladimir Ivanchenko (emdna-V11-03-18)
|
||||
- G4DNARuddIonisationDynamicModel - use G4ExtendedPhysicsVector for data,
|
||||
results are unchanged, performance should be improved.
|
||||
|
||||
## 2025-09-22 Hoang Tran (emdna-V11-03-17)
|
||||
- Fixed the state update in AlongStepDoIt (G4ChemReboundTransportation) to
|
||||
avoid setting incorrect molecule positions (leading tracks) when the scavenger
|
||||
process is called.
|
||||
- Fixed the IRT_syn model (Stepper) to ensure it does not use minTimeStep (default = 1 ps)
|
||||
when DNA reactions do not yet share the same minTimeStep(The MinTimeStep is
|
||||
used to optimize the chemistry).
|
||||
- Fixed the missed Equilibrium process (in G4DNAMakeReaction) for particle-based
|
||||
models (SBS, IRT_syn).
|
||||
- Deleted exception of no reactant (or reactions for the defined molecules) that
|
||||
should return nullptr for no reaction data.
|
||||
|
||||
## 2025-09-10 Vladimir Ivanchenko (emdna-V11-03-16)
|
||||
- for DNA Rudd and Born models enable atomic de-excitation in stationary regime.
|
||||
|
||||
## 2025-07-06 Vladimir Ivanchenko (emdna-V11-03-15)
|
||||
- G4DNARuddIonisationDynamicModel - simplified model using alpha and alpha+ data
|
||||
|
||||
## 2025-07-23 Sebastien Incerti (emdna-V11-03-14)
|
||||
- force cross section to zero below limit of validity of G4DNACPA100ElasticModel
|
||||
|
||||
## 2025-07-06 Vladimir Ivanchenko (emdna-V11-03-13)
|
||||
- G4DNARuddIonisationDynamicModel - fixed problem in sampling of electron energy
|
||||
- G4DNARuddIonisationExtendedModel - improved debug printout
|
||||
|
||||
## 2025-05-28 Hoang Tran (emdna-V11-03-12)
|
||||
- Fixed COVERTY issues on new moleculecounter imple
|
||||
|
||||
|
||||
+11
-7
@@ -41,8 +41,9 @@
|
||||
|
||||
class G4DNAChemistryManager;
|
||||
class G4VAtomDeexcitation;
|
||||
class G4DNACrossSectionDataSet;
|
||||
class G4ExtendedPhysicsVector;
|
||||
class G4Pow;
|
||||
class G4EmCorrections;
|
||||
|
||||
class G4DNARuddIonisationDynamicModel : public G4VEmModel, public G4VSIntegration
|
||||
{
|
||||
@@ -119,18 +120,21 @@ private:
|
||||
// Water density table
|
||||
static const std::vector<G4double>* fpWaterDensity;
|
||||
|
||||
// data for protons
|
||||
static G4DNACrossSectionDataSet* xsdata_hydrogen;
|
||||
static G4DNACrossSectionDataSet* xsdata_helium;
|
||||
static G4DNACrossSectionDataSet* xsdata_p;
|
||||
// cross section data
|
||||
static G4ExtendedPhysicsVector* xsdata_alpha;
|
||||
static G4ExtendedPhysicsVector* xsdata_alphap;
|
||||
static G4ExtendedPhysicsVector* xsdata_hydrogen;
|
||||
static G4ExtendedPhysicsVector* xsdata_helium;
|
||||
static G4ExtendedPhysicsVector* xsdata_p;
|
||||
|
||||
// run time data
|
||||
G4DNACrossSectionDataSet* xsdata{nullptr};
|
||||
G4ExtendedPhysicsVector* xsdata{nullptr};
|
||||
|
||||
const G4ParticleDefinition* fParticle{nullptr};
|
||||
const G4Track* fTrack{nullptr};
|
||||
|
||||
G4DNAChemistryManager* fChemistry{nullptr};
|
||||
G4EmCorrections* fEmCorrections;
|
||||
G4Pow* fGpow;
|
||||
|
||||
//deexcitation manager to produce fluo photons and e-
|
||||
@@ -148,7 +152,6 @@ private:
|
||||
|
||||
G4double slaterEffectiveCharge[3] = {0.0};
|
||||
G4double sCoefficient[3] = {0.0};
|
||||
G4double fTemp[5] = {0.0};
|
||||
|
||||
G4double F1{0.0};
|
||||
G4double F2{0.0};
|
||||
@@ -160,6 +163,7 @@ private:
|
||||
|
||||
G4int fSelectedShell{0};
|
||||
G4int verbose{0};
|
||||
std::size_t idx{0};
|
||||
|
||||
G4bool isFirst{false};
|
||||
G4bool isInitialised{false};
|
||||
|
||||
@@ -169,8 +169,7 @@ void G4DNABornIonisationModel::Initialise(const G4ParticleDefinition* p,
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// initialise atomic de-excitation
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
// chemistry
|
||||
auto chem = G4DNAChemistryManager::Instance();
|
||||
|
||||
@@ -183,7 +183,7 @@ G4double G4DNACPA100ElasticModel::CrossSectionPerVolume(const G4Material* pMater
|
||||
|
||||
if (ekin < fpModelData->GetHighELimit(materialID, p)) {
|
||||
if (ekin < fKillBelowEnergy) {
|
||||
return DBL_MAX;
|
||||
return 0.;
|
||||
}
|
||||
|
||||
auto tableData = fpModelData->GetData();
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
//
|
||||
// Authors: D. Sakata, W.G. Shin, S. Incerti
|
||||
//
|
||||
// Based on a recent release of the ELSEPA code
|
||||
// developed and provided kindly by F. Salvat et al.
|
||||
// Based on a recent release of the ELSEPA code
|
||||
// developed and provided kindly by F. Salvat et al.
|
||||
// See
|
||||
// Computer Physics Communications, 165(2), 157-190. (2005)
|
||||
// http://dx.doi.org/10.1016/j.cpc.2004.09.006
|
||||
@@ -48,21 +48,21 @@ using namespace std;
|
||||
|
||||
G4DNAELSEPAElasticModel::G4DNAELSEPAElasticModel(const G4ParticleDefinition*,
|
||||
const G4String& nam) :
|
||||
G4VEmModel(nam)
|
||||
G4VEmModel(nam)
|
||||
{
|
||||
verboseLevel = 0;
|
||||
|
||||
G4ProductionCutsTable* theCoupleTable =
|
||||
G4ProductionCutsTable::GetProductionCutsTable();
|
||||
auto numOfCouples = (G4int)theCoupleTable->GetTableSize();
|
||||
|
||||
|
||||
fpBaseWater = G4Material::GetMaterial("G4_WATER");
|
||||
|
||||
for(G4int i=0; i<numOfCouples; ++i)
|
||||
{
|
||||
const G4MaterialCutsCouple* couple =
|
||||
theCoupleTable->GetMaterialCutsCouple(i);
|
||||
|
||||
|
||||
const G4Material* material = couple->GetMaterial()->GetBaseMaterial();
|
||||
if(!material) material = couple->GetMaterial();
|
||||
|
||||
@@ -86,7 +86,7 @@ G4VEmModel(nam)
|
||||
}else{// Protection: H2O only is available
|
||||
if(material==fpBaseWater){
|
||||
flowEnergyLimit = 10. * eV;
|
||||
fhighEnergyLimit = 1 * MeV;
|
||||
fhighEnergyLimit = 10. * MeV;
|
||||
SetLowEnergyLimit (flowEnergyLimit);
|
||||
SetHighEnergyLimit(fhighEnergyLimit);
|
||||
}else{
|
||||
@@ -96,8 +96,8 @@ G4VEmModel(nam)
|
||||
|
||||
if (verboseLevel > 0)
|
||||
{
|
||||
G4cout << "ELSEPA Elastic model is constructed for "
|
||||
<< material->GetName() << G4endl
|
||||
G4cout << "ELSEPA Elastic model is constructed for "
|
||||
<< material->GetName() << G4endl
|
||||
<< "Energy range: "
|
||||
<< flowEnergyLimit / eV << " eV - "
|
||||
<< fhighEnergyLimit / MeV << " MeV"
|
||||
@@ -143,11 +143,11 @@ const G4DataVector& )
|
||||
FatalException,"Model not applicable to particle type.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
G4ProductionCutsTable* theCoupleTable =
|
||||
G4ProductionCutsTable::GetProductionCutsTable();
|
||||
auto numOfCouples = (G4int)theCoupleTable->GetTableSize();
|
||||
|
||||
|
||||
// UNIT OF TCS
|
||||
G4double scaleFactor = 1.*cm*cm;
|
||||
|
||||
@@ -155,9 +155,9 @@ const G4DataVector& )
|
||||
fpData_H2O=nullptr;
|
||||
fpBaseWater = G4Material::GetMaterial("G4_WATER");
|
||||
|
||||
for(G4int i=0; i<numOfCouples; ++i)
|
||||
for(G4int i=0; i<numOfCouples; ++i)
|
||||
{
|
||||
const G4MaterialCutsCouple* couple =
|
||||
const G4MaterialCutsCouple* couple =
|
||||
theCoupleTable->GetMaterialCutsCouple(i);
|
||||
const G4Material* material = couple->GetMaterial()->GetBaseMaterial();
|
||||
if(!material) material = couple->GetMaterial();
|
||||
@@ -170,8 +170,8 @@ const G4DataVector& )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Z>0)
|
||||
|
||||
if (Z>0)
|
||||
{
|
||||
G4String fileZElectron("dna/sigma_elastic_e_elsepa_Z");
|
||||
std::ostringstream oss;
|
||||
@@ -184,7 +184,7 @@ const G4DataVector& )
|
||||
eV,
|
||||
scaleFactor );
|
||||
fpData_Au->LoadData(fileZElectron);
|
||||
|
||||
|
||||
std::ostringstream eFullFileNameZ;
|
||||
const char *path = G4EmParameters::Instance()->GetDirLEDATA();
|
||||
|
||||
@@ -197,25 +197,25 @@ const G4DataVector& )
|
||||
|
||||
eFullFileNameZ.str("");
|
||||
eFullFileNameZ.clear(stringstream::goodbit);
|
||||
|
||||
eFullFileNameZ
|
||||
<< path
|
||||
<< "/dna/sigmadiff_cumulated_elastic_e_elsepa_Z"
|
||||
|
||||
eFullFileNameZ
|
||||
<< path
|
||||
<< "/dna/sigmadiff_cumulated_elastic_e_elsepa_Z"
|
||||
<< Z << "_muffintin.dat";
|
||||
|
||||
|
||||
std::ifstream eDiffCrossSectionZ(eFullFileNameZ.str().c_str());
|
||||
|
||||
|
||||
if (!eDiffCrossSectionZ)
|
||||
{
|
||||
G4Exception("G4DNAELSEPAElasticModel::Initialise","em0003",
|
||||
FatalException,"Missing data file for cumulated DCS");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
eEdummyVec_Au.clear();
|
||||
eCum_Au.clear();
|
||||
fAngleData_Au.clear();
|
||||
|
||||
|
||||
eEdummyVec_Au.push_back(0.);
|
||||
do
|
||||
{
|
||||
@@ -233,7 +233,7 @@ const G4DataVector& )
|
||||
eCum_Au[eDummy].push_back(cumDummy);
|
||||
}
|
||||
}while(!eDiffCrossSectionZ.eof());
|
||||
}
|
||||
}
|
||||
|
||||
}else{// Protection: H2O only is available
|
||||
if(material == fpBaseWater && !fpData_H2O){
|
||||
@@ -245,12 +245,12 @@ const G4DataVector& )
|
||||
SetLowEnergyLimit(10.*eV);
|
||||
}
|
||||
|
||||
if (HighEnergyLimit() > 1.*MeV)
|
||||
if (HighEnergyLimit() > 10.*MeV)
|
||||
{
|
||||
G4cout<<"G4DNAELSEPAElasticModel: high energy limit decreased from "
|
||||
<< HighEnergyLimit()/MeV << " MeV to " << 1. << " MeV"
|
||||
<< HighEnergyLimit()/MeV << " MeV to " << 10. << " MeV"
|
||||
<< G4endl;
|
||||
SetHighEnergyLimit(1.*MeV);
|
||||
SetHighEnergyLimit(10.*MeV);
|
||||
}
|
||||
|
||||
G4String fileZElectron("dna/sigma_elastic_e_elsepa_muffin");
|
||||
@@ -356,7 +356,7 @@ G4double G4DNAELSEPAElasticModel::CrossSectionPerVolume
|
||||
{
|
||||
// Protection: only for GOLD
|
||||
if (material->GetZ()!=79) return 0.0;
|
||||
|
||||
|
||||
const G4ElementVector* theElementVector = material->GetElementVector();
|
||||
G4int Z = G4lrint((*theElementVector)[0]->GetZ());
|
||||
|
||||
@@ -377,11 +377,11 @@ G4double G4DNAELSEPAElasticModel::CrossSectionPerVolume
|
||||
G4cout << "__________________________________" << G4endl;
|
||||
G4cout << "=== G4DNAELSEPAElasticModel - XS INFO START" << G4endl;
|
||||
G4cout << "=== Material is made of one element with Z =" << Z << G4endl;
|
||||
G4cout << "=== Kinetic energy(eV)=" << ekin/eV << " particle : "
|
||||
G4cout << "=== Kinetic energy(eV)=" << ekin/eV << " particle : "
|
||||
<< particleName << G4endl;
|
||||
G4cout << "=== Cross section per atom for Z="<<Z<<" is (cm^2)"
|
||||
G4cout << "=== Cross section per atom for Z="<<Z<<" is (cm^2)"
|
||||
<< sigma/cm/cm << G4endl;
|
||||
G4cout << "=== Cross section per atom for Z="<<Z<<" is (cm^-1)="
|
||||
G4cout << "=== Cross section per atom for Z="<<Z<<" is (cm^-1)="
|
||||
<< sigma*atomicNDensity/(1./cm) << G4endl;
|
||||
G4cout << "=== G4DNAELSEPAElasticModel - XS INFO END" << G4endl;
|
||||
}
|
||||
@@ -400,11 +400,11 @@ G4double G4DNAELSEPAElasticModel::CrossSectionPerVolume
|
||||
{
|
||||
G4cout << "__________________________________" << G4endl;
|
||||
G4cout << "=== G4DNAELSEPAElasticModel - XS INFO START" << G4endl;
|
||||
G4cout << "=== Kinetic energy(eV)=" << ekin/eV
|
||||
G4cout << "=== Kinetic energy(eV)=" << ekin/eV
|
||||
<< " particle : " << particle->GetParticleName() << G4endl;
|
||||
G4cout << "=== Cross section per water molecule (cm^2)="
|
||||
G4cout << "=== Cross section per water molecule (cm^2)="
|
||||
<< sigma/cm/cm << G4endl;
|
||||
G4cout << "=== Cross section per water molecule (cm^-1)="
|
||||
G4cout << "=== Cross section per water molecule (cm^-1)="
|
||||
<< sigma*atomicNDensity/(1./cm) << G4endl;
|
||||
G4cout << "=== G4DNAELSEPAElasticModel - XS INFO END" << G4endl;
|
||||
}
|
||||
@@ -424,8 +424,8 @@ void G4DNAELSEPAElasticModel::SampleSecondaries(
|
||||
{
|
||||
|
||||
if (verboseLevel > 3){
|
||||
G4cout <<
|
||||
"Calling SampleSecondaries() of G4DNAELSEPAElasticModel"
|
||||
G4cout <<
|
||||
"Calling SampleSecondaries() of G4DNAELSEPAElasticModel"
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ void G4DNAELSEPAElasticModel::SampleSecondaries(
|
||||
|
||||
const G4Material* material = couple->GetMaterial()->GetBaseMaterial();
|
||||
if(!material) material = couple->GetMaterial();
|
||||
|
||||
|
||||
std::size_t nelm = material->GetNumberOfElements();
|
||||
if (nelm==1) // Protection: only for single element
|
||||
{
|
||||
@@ -457,12 +457,12 @@ void G4DNAELSEPAElasticModel::SampleSecondaries(
|
||||
cosTheta = RandomizeCosTheta(Z,electronEnergy0);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
cosTheta = RandomizeCosTheta(Z,10*eV);
|
||||
}
|
||||
|
||||
G4double phi = 2. * CLHEP::pi * G4UniformRand();
|
||||
|
||||
|
||||
G4ThreeVector zVers = aDynamicElectron->GetMomentumDirection();
|
||||
G4ThreeVector xVers = zVers.orthogonal();
|
||||
G4ThreeVector yVers = zVers.cross(xVers);
|
||||
@@ -475,7 +475,7 @@ void G4DNAELSEPAElasticModel::SampleSecondaries(
|
||||
G4ThreeVector zPrimeVers((xDir*xVers + yDir*yVers + cosTheta*zVers));
|
||||
fParticleChangeForGamma->ProposeMomentumDirection(zPrimeVers.unit());
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(electronEnergy0);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -545,10 +545,10 @@ G4double G4DNAELSEPAElasticModel::Theta(G4int Z,
|
||||
cum12 = std::upper_bound(eCum_Au[(*e1)].begin(),
|
||||
eCum_Au[(*e1)].end(),integrDiff);
|
||||
}
|
||||
|
||||
|
||||
auto cum11 = cum12 - 1;
|
||||
|
||||
//std::vector<G4double>::iterator cum22
|
||||
//std::vector<G4double>::iterator cum22
|
||||
// = std::upper_bound(eCumZ[Z][(*e2)].begin(),
|
||||
// eCumZ[Z][(*e2)].end(),integrDiff);
|
||||
std::vector<G4double>::iterator cum22;
|
||||
@@ -559,7 +559,7 @@ G4double G4DNAELSEPAElasticModel::Theta(G4int Z,
|
||||
cum22 = std::upper_bound(eCum_Au[(*e2)].begin(),
|
||||
eCum_Au[(*e2)].end(),integrDiff);
|
||||
}
|
||||
|
||||
|
||||
auto cum21 = cum22 - 1;
|
||||
|
||||
valueE1 = *e1;
|
||||
@@ -585,7 +585,7 @@ G4double G4DNAELSEPAElasticModel::Theta(G4int Z,
|
||||
|
||||
if (a11 == 0 && a12 == 0 && a21 == 0 && a22 == 0) return (0.);
|
||||
|
||||
theta = QuadInterpolator(valuecum11, valuecum12, valuecum21, valuecum22,
|
||||
theta = QuadInterpolator(valuecum11, valuecum12, valuecum21, valuecum22,
|
||||
a11, a12,a21, a22, valueE1, valueE2, k, integrDiff);
|
||||
return theta;
|
||||
}
|
||||
@@ -708,7 +708,7 @@ G4double G4DNAELSEPAElasticModel::RandomizeCosTheta(G4int Z, G4double k)
|
||||
G4double cosTheta = 0.;
|
||||
theta = Theta(Z, G4Electron::ElectronDefinition(), k / eV, integrdiff);
|
||||
|
||||
cosTheta = std::cos(theta * CLHEP::pi / 180.);
|
||||
cosTheta = std::cos(theta * CLHEP::pi / 180.);
|
||||
|
||||
return cosTheta;
|
||||
}
|
||||
|
||||
+8
-3
@@ -178,9 +178,14 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& track
|
||||
continue;
|
||||
}
|
||||
fSampledMinTimeStep = tempMinET;
|
||||
if (tempMinET < fUserMinTimeStep) {
|
||||
fSampledMinTimeStep = fUserMinTimeStep;
|
||||
}
|
||||
// Fixed the IRT_syn model (Stepper) to ensure it does not use minTimeStep (default = 1 ps)
|
||||
// when DNA reactions do not yet share
|
||||
// the same minTimeStep(The MinTimeStep is used to optimize the chemistry).
|
||||
// TODO: full test
|
||||
|
||||
//if (tempMinET < fUserMinTimeStep) {
|
||||
// fSampledMinTimeStep = fUserMinTimeStep;
|
||||
//}
|
||||
}
|
||||
CheckAndRecordResults(fSampledMinTimeStep, utils);
|
||||
}
|
||||
|
||||
@@ -87,6 +87,9 @@ G4DNAMakeReaction::MakeReaction(const G4Track &trackA,
|
||||
|
||||
const auto pReactionData = fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
|
||||
const G4int nbProducts = pReactionData->GetNbProducts();
|
||||
//add Equilibrium process for particle-based models.
|
||||
if(fpScavengerMaterial != nullptr) { fpScavengerMaterial->SetEquilibrium(pReactionData, trackA.GetGlobalTime()); }
|
||||
|
||||
// Notify molecule (reaction) counter
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive()) {
|
||||
G4MoleculeCounterManager::Instance()->RecordReaction(pReactionData, trackA.GetGlobalTime());
|
||||
|
||||
+60
-43
@@ -35,14 +35,17 @@
|
||||
#include "G4VAtomDeexcitation.hh"
|
||||
#include "G4UAtomicDeexcitation.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4EmCorrections.hh"
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4LogLogInterpolation.hh"
|
||||
|
||||
#include "G4ProductionCutsTable.hh"
|
||||
|
||||
#include "G4DNAGenericIonsManager.hh"
|
||||
#include "G4DNACrossSectionDataSet.hh"
|
||||
#include "G4MatUtils.hh"
|
||||
#include "G4ExtendedPhysicsVector.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4NistManager.hh"
|
||||
|
||||
#include "G4IonTable.hh"
|
||||
@@ -57,9 +60,11 @@
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNACrossSectionDataSet* G4DNARuddIonisationDynamicModel::xsdata_hydrogen = nullptr;
|
||||
G4DNACrossSectionDataSet* G4DNARuddIonisationDynamicModel::xsdata_helium = nullptr;
|
||||
G4DNACrossSectionDataSet* G4DNARuddIonisationDynamicModel::xsdata_p = nullptr;
|
||||
G4ExtendedPhysicsVector* G4DNARuddIonisationDynamicModel::xsdata_alpha = nullptr;
|
||||
G4ExtendedPhysicsVector* G4DNARuddIonisationDynamicModel::xsdata_alphap = nullptr;
|
||||
G4ExtendedPhysicsVector* G4DNARuddIonisationDynamicModel::xsdata_hydrogen = nullptr;
|
||||
G4ExtendedPhysicsVector* G4DNARuddIonisationDynamicModel::xsdata_helium = nullptr;
|
||||
G4ExtendedPhysicsVector* G4DNARuddIonisationDynamicModel::xsdata_p = nullptr;
|
||||
const std::vector<G4double>* G4DNARuddIonisationDynamicModel::fpWaterDensity = nullptr;
|
||||
|
||||
namespace
|
||||
@@ -79,6 +84,7 @@ G4DNARuddIonisationDynamicModel::G4DNARuddIonisationDynamicModel(const G4Particl
|
||||
const G4String& nam)
|
||||
: G4VEmModel(nam)
|
||||
{
|
||||
fEmCorrections = G4LossTableManager::Instance()->EmCorrections();
|
||||
fGpow = G4Pow::GetInstance();
|
||||
fLowestEnergy = 100*CLHEP::eV;
|
||||
fAbsorptionEnergy = 50*CLHEP::eV;
|
||||
@@ -100,6 +106,8 @@ G4DNARuddIonisationDynamicModel::G4DNARuddIonisationDynamicModel(const G4Particl
|
||||
G4DNARuddIonisationDynamicModel::~G4DNARuddIonisationDynamicModel()
|
||||
{
|
||||
if (isFirst) {
|
||||
delete xsdata_alpha;
|
||||
delete xsdata_alphap;
|
||||
delete xsdata_p;
|
||||
delete xsdata_hydrogen;
|
||||
delete xsdata_helium;
|
||||
@@ -111,17 +119,27 @@ G4DNARuddIonisationDynamicModel::~G4DNARuddIonisationDynamicModel()
|
||||
void G4DNARuddIonisationDynamicModel::LoadData()
|
||||
{
|
||||
// initialisation of static data once
|
||||
G4String filename = "dna/sigma_ionisation_p_rudd";
|
||||
xsdata_p = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_p->LoadData(filename);
|
||||
const G4String& dirpath = G4EmParameters::Instance()->GetDirLEDATA();
|
||||
|
||||
filename = "dna/sigma_ionisation_h_rudd";
|
||||
xsdata_hydrogen = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_hydrogen->LoadData(filename);
|
||||
G4String filename = "dna/sigma_ionisation_p_rudd.dat";
|
||||
xsdata_p =
|
||||
G4MatUtils::BuildExtendedVector(dirpath, filename, 5, 645, CLHEP::eV, scaleFactor);
|
||||
|
||||
filename = "dna/sigma_ionisation_he_rudd";
|
||||
xsdata_helium = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_helium->LoadData(filename);
|
||||
filename = "dna/sigma_ionisation_alphaplusplus_rudd.dat";
|
||||
xsdata_alpha =
|
||||
G4MatUtils::BuildExtendedVector(dirpath, filename, 5, 540, CLHEP::eV, scaleFactor);
|
||||
|
||||
filename = "dna/sigma_ionisation_alphaplus_rudd.dat";
|
||||
xsdata_alphap =
|
||||
G4MatUtils::BuildExtendedVector(dirpath, filename, 5, 540, CLHEP::eV, scaleFactor);
|
||||
|
||||
filename = "dna/sigma_ionisation_h_rudd.dat";
|
||||
xsdata_hydrogen =
|
||||
G4MatUtils::BuildExtendedVector(dirpath, filename, 5, 600, CLHEP::eV, scaleFactor);
|
||||
|
||||
filename = "dna/sigma_ionisation_he_rudd.dat";
|
||||
xsdata_helium =
|
||||
G4MatUtils::BuildExtendedVector(dirpath, filename, 5, 540, CLHEP::eV, scaleFactor);
|
||||
|
||||
// to avoid possible threading problem fill this vector only once
|
||||
auto water = G4NistManager::Instance()->FindMaterial("G4_WATER");
|
||||
@@ -168,6 +186,7 @@ void G4DNARuddIonisationDynamicModel::Initialise(const G4ParticleDefinition* p,
|
||||
fLowestEnergy = 1*CLHEP::keV;
|
||||
} else if (pname == "alpha+") {
|
||||
isHelium = true;
|
||||
xsdata = xsdata_alphap;
|
||||
// The following values are provided by M. Dingfelder (priv. comm)
|
||||
slaterEffectiveCharge[0]=2.0;
|
||||
slaterEffectiveCharge[1]=2.0;
|
||||
@@ -175,16 +194,21 @@ void G4DNARuddIonisationDynamicModel::Initialise(const G4ParticleDefinition* p,
|
||||
sCoefficient[0]=0.7;
|
||||
sCoefficient[1]=0.15;
|
||||
sCoefficient[2]=0.15;
|
||||
} else if (pname == "alpha") {
|
||||
isHelium = true;
|
||||
xsdata = xsdata_alpha;
|
||||
} else if (pname == "hydrogen") {
|
||||
xsdata = xsdata_hydrogen;
|
||||
} else if (pname != "proton") {
|
||||
isIon = true;
|
||||
}
|
||||
if (isHelium) { fLowestEnergy = 1*CLHEP::keV; }
|
||||
|
||||
// defined stationary mode
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// initialise atomic de-excitation
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
// chemistry
|
||||
auto chem = G4DNAChemistryManager::Instance();
|
||||
@@ -192,7 +216,7 @@ void G4DNARuddIonisationDynamicModel::Initialise(const G4ParticleDefinition* p,
|
||||
fChemistry = chem;
|
||||
}
|
||||
|
||||
InitialiseIntegrator(0.1, 0.25, 1.05, 1*CLHEP::eV, 0.2*CLHEP::eV, 10*CLHEP::keV);
|
||||
InitialiseIntegrator(0.1, 0.25, 1.05, 4*CLHEP::eV, 0.2*CLHEP::eV, 10*CLHEP::keV);
|
||||
|
||||
if (verbose > 0) {
|
||||
G4cout << "### G4DNARuddIonisationDynamicModel::Initialise(..) "
|
||||
@@ -207,7 +231,10 @@ void G4DNARuddIonisationDynamicModel::SetParticle(const G4ParticleDefinition* p)
|
||||
{
|
||||
fParticle = p;
|
||||
fMass = p->GetPDGMass();
|
||||
fMassRate = CLHEP::proton_mass_c2/fMass;
|
||||
if (isIon) {
|
||||
fMassRate = CLHEP::proton_mass_c2/fMass;
|
||||
fMass = CLHEP::proton_mass_c2;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -235,19 +262,17 @@ G4DNARuddIonisationDynamicModel::CrossSectionPerVolume(const G4Material* materia
|
||||
|
||||
// ion may be different
|
||||
if (fParticle != part) { SetParticle(part); }
|
||||
G4double q = fTrack->GetDynamicParticle()->GetCharge()*inveplus;
|
||||
|
||||
// cross section for scaled energy
|
||||
G4double e = kinE*fMassRate;
|
||||
|
||||
auto xs = xsdata;
|
||||
if (0.0 == q) { xs = isHelium ? xsdata_helium : xsdata_hydrogen; }
|
||||
|
||||
G4double sigma = (e > fLowestEnergy) ? xs->FindValue(e)
|
||||
: xs->FindValue(fLowestEnergy) * e / fLowestEnergy;
|
||||
G4double sigma = (e > fLowestEnergy) ? xsdata->LogLogValue(e, idx)
|
||||
: xsdata->LogLogValue(fLowestEnergy, idx) * e / fLowestEnergy;
|
||||
|
||||
sigma *= density;
|
||||
if (q > 1.5) { sigma *= q * q; }
|
||||
if (isIon) {
|
||||
sigma *= fEmCorrections->EffectiveChargeSquareRatio(part, material, kinE);
|
||||
}
|
||||
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNARuddIonisationDynamicModel for " << part->GetParticleName()
|
||||
@@ -323,7 +348,11 @@ G4DNARuddIonisationDynamicModel::SampleSecondaries(std::vector<G4DynamicParticle
|
||||
<< G4endl;
|
||||
}
|
||||
scatteredEnergy = std::max(scatteredEnergy, 0.0);
|
||||
|
||||
/*
|
||||
G4cout << "Eprim(keV)=" << kinE/CLHEP::keV << " Efin(keV)=" << scatteredEnergy/CLHEP::keV
|
||||
<< " Esec(keV)=" << esec/CLHEP::keV << " Exc(keV)=" << exc/CLHEP::keV
|
||||
<< " tolerance(keV)=" << tolerance/CLHEP::keV << G4endl;
|
||||
*/
|
||||
// projectile
|
||||
if (!statCode) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
|
||||
@@ -347,20 +376,7 @@ G4DNARuddIonisationDynamicModel::SampleSecondaries(std::vector<G4DynamicParticle
|
||||
|
||||
G4int G4DNARuddIonisationDynamicModel::SelectShell()
|
||||
{
|
||||
G4double sum = 0.0;
|
||||
G4double xs;
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
auto ptr = xsdata->GetComponent(i);
|
||||
xs = (fScaledEnergy > fLowestEnergy) ? ptr->FindValue(fScaledEnergy)
|
||||
: ptr->FindValue(fLowestEnergy)*fScaledEnergy/fLowestEnergy;
|
||||
sum += xs;
|
||||
fTemp[i] = sum;
|
||||
}
|
||||
sum *= G4UniformRand();
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
if (sum <= fTemp[i]) { return i; }
|
||||
}
|
||||
return 0;
|
||||
return xsdata->SampleReactionChannel(fScaledEnergy, G4UniformRand(), idx);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -369,7 +385,7 @@ G4double
|
||||
G4DNARuddIonisationDynamicModel::MaxEnergy()
|
||||
{
|
||||
// kinematic limit
|
||||
G4double tau = fScaledEnergy/CLHEP::proton_mass_c2;
|
||||
G4double tau = fScaledEnergy/fMass;
|
||||
G4double gam = 1.0 + tau;
|
||||
G4double emax = 2.0*CLHEP::electron_mass_c2*tau*(tau + 2.0);
|
||||
|
||||
@@ -431,6 +447,7 @@ G4DNARuddIonisationDynamicModel::SampleElectronEnergy()
|
||||
G4cout << "G4DNARuddIonisationDynamicModel::SampleElectronEnergy: "
|
||||
<< fParticle->GetParticleName()
|
||||
<< " Escaled(keV)=" << fScaledEnergy/CLHEP::keV << " Ee(keV)=" << e/CLHEP::keV
|
||||
<< " Emax(keV)=" << emax/CLHEP::keV << " shell=" << fSelectedShell
|
||||
<< G4endl;
|
||||
}
|
||||
return e;
|
||||
@@ -540,13 +557,13 @@ G4double G4DNARuddIonisationDynamicModel::Rh(G4double ekin, G4double etrans,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::CorrectionFactor()
|
||||
G4double G4DNARuddIonisationDynamicModel::CorrectionFactor()
|
||||
{
|
||||
// ZF Shortened
|
||||
G4double res = 1.0;
|
||||
if (fSelectedShell < 4) {
|
||||
const G4double ln10 = fGpow->logZ(10);
|
||||
G4double x = 2.0*((G4Log(fScaledEnergy/CLHEP::eV)/ln10) - 4.2);
|
||||
G4double x = 2.0*((G4Log(fScaledEnergy/(fMassRate*CLHEP::eV))/ln10) - 4.2);
|
||||
// The following values are provided by M. Dingfelder (priv. comm)
|
||||
res = 0.6/(1.0 + G4Exp(x)) + 0.9;
|
||||
}
|
||||
|
||||
@@ -222,8 +222,7 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* p,
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// initialise atomic de-excitation
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
if (verbose > 0) {
|
||||
G4cout << "### G4DNARuddIonisationExtendedModel::Initialise(..) " << pname
|
||||
@@ -343,7 +342,11 @@ G4DNARuddIonisationExtendedModel::SampleSecondaries(std::vector<G4DynamicParticl
|
||||
<< G4endl;
|
||||
}
|
||||
scatteredEnergy = std::max(scatteredEnergy, 0.0);
|
||||
|
||||
/*
|
||||
G4cout << "Eprim(keV)=" << kinE/CLHEP::keV << " Efin(keV)=" << scatteredEnergy/CLHEP::keV
|
||||
<< " Esec(keV)=" << esec/CLHEP::keV << " Exc(keV)=" << exc/CLHEP::keV
|
||||
<< " tolerance(keV)=" << tolerance/CLHEP::keV << G4endl;
|
||||
*/
|
||||
// projectile
|
||||
if (!statCode) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
|
||||
@@ -449,8 +452,6 @@ G4double G4DNARuddIonisationExtendedModel::SampleElectronEnergy(G4double kine,
|
||||
|
||||
// find max probability
|
||||
G4double pmax = ProbabilityFunction(kine, 0.0, shell);
|
||||
//G4cout << "## E(keV)=" << kine/keV << " emax=" << emax/keV
|
||||
// << " pmax(0)=" << pmax << " shell=" << shell << " nn=" << nn << G4endl;
|
||||
|
||||
G4double e0 = 0.0; // energy with max probability
|
||||
// 2 areas after point with max probability
|
||||
|
||||
+2
-2
@@ -26,7 +26,7 @@
|
||||
#ifndef G4MOLECULECOUNTERTIMECOMPARER_HH
|
||||
#define G4MOLECULECOUNTERTIMECOMPARER_HH 1
|
||||
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include <CLHEP/Units/PhysicalConstants.h>
|
||||
#include "G4Types.hh"
|
||||
|
||||
#include <map>
|
||||
@@ -58,7 +58,7 @@ class G4MoleculeCounterTimeComparer
|
||||
|
||||
private:
|
||||
TimeComparerType fType;
|
||||
G4double fPrecision{1 * picosecond};
|
||||
G4double fPrecision{1 * CLHEP::picosecond};
|
||||
std::map<G4double, G4double> fVariablePrecision{};
|
||||
|
||||
public: // Factory
|
||||
|
||||
+1
@@ -26,6 +26,7 @@
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#include "G4VMoleculeCounterInternalBase.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
namespace G4
|
||||
{
|
||||
|
||||
@@ -125,7 +125,7 @@ void G4ChemReboundTransportation::ComputeStep(const G4Track& track, const G4Step
|
||||
spaceStep = 0.;
|
||||
}
|
||||
else {
|
||||
auto molConf = GetMolecule(track)->GetMolecularConfiguration();
|
||||
const auto molConf = GetMolecule(track)->GetMolecularConfiguration();
|
||||
spaceStep = calculateDistanceFromTimeStep(molConf, timeStep);
|
||||
}
|
||||
State(fTransportEndPosition) =
|
||||
@@ -240,7 +240,8 @@ G4double G4ChemReboundTransportation::AlongStepGetPhysicalInteractionLength(
|
||||
|
||||
geometryStepLength = calculateDistanceFromTimeStep(molConf, State(theInteractionTimeLeft));
|
||||
State(fTransportEndPosition) =
|
||||
geometryStepLength * track.GetMomentumDirection() + track.GetPosition();
|
||||
BouncingAction(track.GetPosition() + geometryStepLength * G4RandomDirection());
|
||||
|
||||
State(fTimeStepReachedLimit) = true;
|
||||
State(fCandidateEndGlobalTime) = track.GetGlobalTime() + State(theInteractionTimeLeft);
|
||||
State(fEndGlobalTimeComputed) = true;
|
||||
@@ -261,29 +262,33 @@ G4VParticleChange* G4ChemReboundTransportation::AlongStepDoIt(const G4Track& tra
|
||||
const G4Step& step)
|
||||
{
|
||||
if (GetIT(track)->GetTrackingInfo()->IsLeadingStep()) {
|
||||
G4double spaceStep = DBL_MAX;
|
||||
auto molConf = GetMolecule(track)->GetMolecularConfiguration();
|
||||
spaceStep = calculateDistanceFromTimeStep(molConf, State(theInteractionTimeLeft));
|
||||
// Hoang fixed: - Fixed the state update in AlongStepDoIt (G4ChemReboundTransportation) to
|
||||
// avoid setting incorrect molecule positions (leading tracks)
|
||||
// when the scavenger process is called.
|
||||
|
||||
State(fGeometryLimitedStep) = false;
|
||||
State(fTransportEndPosition) =
|
||||
BouncingAction(track.GetPosition() + spaceStep * G4RandomDirection());
|
||||
State(fEndPointDistance) = spaceStep;
|
||||
// G4double spaceStep = DBL_MAX;
|
||||
// const auto molConf = GetMolecule(track)->GetMolecularConfiguration();
|
||||
// spaceStep = calculateDistanceFromTimeStep(molConf, State(theInteractionTimeLeft));
|
||||
|
||||
// State(fGeometryLimitedStep) = false;
|
||||
// State(fTransportEndPosition) =
|
||||
// BouncingAction(track.GetPosition() + spaceStep * G4RandomDirection());
|
||||
// State(fEndPointDistance) = spaceStep;
|
||||
if (fVerboseLevel > 1)
|
||||
// if(GetMolecule(track)->GetName() == "e_aq^-1")
|
||||
|
||||
{
|
||||
G4cout << "ChemReboundTransportation::AlongStepDoIt() :" << " trackID : "
|
||||
<< track.GetTrackID()
|
||||
<< " Molecule name: " << "prePosition : " << step.GetPreStepPoint()->GetPosition()
|
||||
<< " postPostion : " << step.GetPostStepPoint()->GetPosition() << " "
|
||||
<< GetMolecule(track)->GetName() << " State(theInteractionTimeLeft) : "
|
||||
<< G4BestUnit(State(theInteractionTimeLeft), "Time")
|
||||
<< " Diffusion length : " << G4BestUnit(step.GetStepLength(), "Length")
|
||||
<< " within time step : " << G4BestUnit(step.GetDeltaTime(), "Time")
|
||||
<< "\t Current global time : " << G4BestUnit(track.GetGlobalTime(), "Time")
|
||||
<< " track.GetMomentumDirection() : " << track.GetMomentumDirection() << G4endl;
|
||||
}
|
||||
//if(GetMolecule(track)->GetName() == "e_aq^-1")
|
||||
{
|
||||
G4cout << "G4DNABrownianTransportation::AlongStepDoIt() : IsLeadingStep " << " trackID : "
|
||||
<< track.GetTrackID()
|
||||
<< "position : "<<track.GetPosition()
|
||||
<< " Molecule name: "
|
||||
<< GetMolecule(track)->GetName()<< "State(fTransportEndPosition) : "<<State(fTransportEndPosition) << " State(theInteractionTimeLeft) : "
|
||||
<< G4BestUnit(State(theInteractionTimeLeft), "Time")
|
||||
<< " Diffusion length : " << G4BestUnit(step.GetStepLength(), "Length")
|
||||
<< " within time step : " << G4BestUnit(step.GetDeltaTime(), "Time")
|
||||
<< "\t Current global time : " << G4BestUnit(track.GetGlobalTime(), "Time")
|
||||
<< " track.GetMomentumDirection() : " << track.GetMomentumDirection()<<" GetIT(track)->GetTrackingInfo()->IsLeadingStep() : "<<GetIT(track)->GetTrackingInfo()->IsLeadingStep() << G4endl;
|
||||
//throw;
|
||||
}
|
||||
}
|
||||
|
||||
G4ITTransportation::AlongStepDoIt(track, step);
|
||||
@@ -353,7 +358,7 @@ G4double G4ChemReboundTransportation::calculateNextCoordinate(G4double nextPos,
|
||||
G4double G4ChemReboundTransportation::calculateDistanceFromTimeStep(MolConf mol, G4double timeStep)
|
||||
{
|
||||
G4double diffuCoeff = mol->GetDiffusionCoefficient();
|
||||
if (mol->GetDiffusionCoefficient() <= 0) {
|
||||
if (mol->GetDiffusionCoefficient() < 0) {
|
||||
G4ExceptionDescription exceptionDescription;
|
||||
exceptionDescription << "GetDiffusionCoefficient is negative";
|
||||
G4Exception("ChemReboundTransportation::calculateDistanceFromTimeStep",
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
#include "G4DNAElectronSolvation.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4DNAWaterExcitationStructure.hh"
|
||||
#include "G4LowEnergyEmProcessSubType.hh"
|
||||
|
||||
@@ -616,12 +616,13 @@ G4DNAMolecularReactionTable::GetReactionData(Reactant* pReactant1,
|
||||
|
||||
if (it1 == fReactionData.end())
|
||||
{
|
||||
G4String errMsg =
|
||||
"No reaction table was implemented for this molecule Definition : " + pReactant1
|
||||
->GetName();
|
||||
G4Exception("G4MolecularInteractionTable::GetReactionData", "",
|
||||
FatalErrorInArgument, errMsg);
|
||||
// Though the above is Fatal and will terminate program, put return in to quieten Coverity
|
||||
if (fVerbose) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "No reaction table was implemented for this molecule Definition : "
|
||||
+ pReactant1->GetName();
|
||||
G4Exception(G4String("G4MolecularInteractionTable::GetReactionData"),
|
||||
"", JustWarning, errMsg);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -629,10 +630,9 @@ G4DNAMolecularReactionTable::GetReactionData(Reactant* pReactant1,
|
||||
|
||||
if (it2 == it1->second.end())
|
||||
{
|
||||
G4cout << "Name : " << pReactant2->GetName() << G4endl;
|
||||
G4String errMsg = "No reaction table was implemented for this molecule : "
|
||||
+ pReactant2->GetName();
|
||||
G4Exception("G4MolecularInteractionTable::GetReactionData", "", FatalErrorInArgument, errMsg);
|
||||
//no reactant should return nullptr reaction data (not an exception).
|
||||
//This helps UI chemistry
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return (it2->second);
|
||||
@@ -751,10 +751,13 @@ G4DNAMolecularReactionTable::GetReactionData(const G4MolecularConfiguration* mol
|
||||
|
||||
if (it == fReactionDataMV.end())
|
||||
{
|
||||
G4String errMsg = "No reaction table was implemented for this molecule Definition : "
|
||||
+ molecule->GetName();
|
||||
G4Exception("G4MolecularInteractionTable::GetReactionData", "", FatalErrorInArgument, errMsg);
|
||||
// Though the above is Fatal and will terminate program, put return in to quieten Coverity
|
||||
if (fVerbose) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "No reaction table was implemented for this molecule Definition : "
|
||||
+ molecule->GetName();
|
||||
G4Exception(G4String("G4MolecularInteractionTable::GetReactionData"),
|
||||
"", JustWarning, errMsg);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user