Files
geant4/source/processes/electromagnetic/standard/src/G4IonICRU73Data.cc
T
2022-07-01 10:44:02 +02:00

327 lines
9.9 KiB
C++

//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//---------------------------------------------------------------------------
//
// GEANT4 Class file
//
// Description: Data on stopping power
//
// Author: Vladimir Ivanchenko
//
// Creation date: 23.10.2021
//
//----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include <fstream>
#include <sstream>
#include "G4IonICRU73Data.hh"
#include "G4SystemOfUnits.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsFreeVector.hh"
#include "G4EmParameters.hh"
#include "G4ProductionCutsTable.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Material.hh"
#include "G4Element.hh"
const G4String namesICRU73[31] = {
"G4_A-150_TISSUE"
"G4_ADIPOSE_TISSUE_ICRP"
"G4_AIR"
"G4_ALUMINUM_OXIDE"
"G4_BONE_COMPACT_ICRU"
"G4_BONE_CORTICAL_ICRP"
"G4_C-552"
"G4_CALCIUM_FLUORIDE"
"G4_CARBON_DIOXIDE"
"G4_KAPTON"
"G4_LITHIUM_FLUORIDE"
"G4_LITHIUM_TETRABORATE"
"G4_LUCITE"
"G4_METHANE"
"G4_MUSCLE_STRIATED_ICRU"
"G4_MYLAR"
"G4_NYLON-6-6"
"G4_PHOTO_EMULSION"
"G4_PLASTIC_SC_VINYLTOLUENE"
"G4_POLYCARBONATE"
"G4_POLYETHYLENE"
"G4_POLYSTYRENE"
"G4_PROPANE"
"G4_Pyrex_Glass"
"G4_SILICON_DIOXIDE"
"G4_SODIUM_IODIDE"
"G4_TEFLON"
"G4_TISSUE-METHANE"
"G4_TISSUE-PROPANE"
"G4_WATER"
"G4_WATER_VAPOR"};
const G4String namesICRU90[3] = {"G4_AIR","G4_GRAPHITE","G4_WATER"};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4IonICRU73Data::G4IonICRU73Data()
{
fEmin = 0.025*CLHEP::MeV;
fEmax = 2.5*CLHEP::MeV;
fNbins = fNbinsPerDecade*G4lrint(std::log10(fEmax/fEmin) + 0.000001);
fVector = new G4PhysicsFreeVector(fSpline);
for(G4int i=0; i<81; ++i) {
fMatData[i] = new std::vector<G4PhysicsLogVector*>;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4IonICRU73Data::~G4IonICRU73Data()
{
delete fVector;
for(G4int i=0; i<81; ++i) {
auto v = fMatData[i];
for(G4int j=0; j<fNmat; ++j) {
delete (*v)[j];
}
delete v;
for(G4int j=0; j<81; ++j) { delete fElmData[i][j]; }
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4IonICRU73Data::GetDEDX(const G4Material* mat, const G4int Z,
const G4double e, const G4double loge) const
{
G4PhysicsLogVector* v = nullptr;
if(1 == mat->GetNumberOfElements()) {
G4int Z1 = (*(mat->GetElementVector()))[0]->GetZasInt();
if(Z <= 80 && Z1 <= 80) {
v = fElmData[Z][Z1];
}
} else {
G4int idx = fMatIndex[mat->GetIndex()];
if(idx < fNmat && Z <= 80) {
v = (*(fMatData[Z]))[idx];
}
}
G4double res = (nullptr != v) ? v->LogVectorValue(e, loge) : 0.0;
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4IonICRU73Data::Initialise()
{
// fill directory path
if(fDataDirectory.empty()) {
const char* path = G4FindDataDir("G4LEDATA");
if (nullptr != path) {
std::ostringstream ost;
ost << path << "/ion_stopping_data/";
fDataDirectory = ost.str();
} else {
G4Exception("G4IonICRU73Data::Initialise(..)","em013",
FatalException,
"Environment variable G4LEDATA is not defined");
}
}
G4bool useICRU90 = G4EmParameters::Instance()->UseICRU90Data();
size_t nmat = G4Material::GetNumberOfMaterials();
fMatIndex.resize(nmat, -1);
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for(size_t i=0; i<numOfCouples; ++i) {
const G4MaterialCutsCouple* couple =
theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* mat = couple->GetMaterial();
G4int idx = mat->GetIndex();
if(fMatIndex[idx] == -1) {
G4String matname = mat->GetName();
G4bool isOK = false;
if(1 == mat->GetNumberOfElements()) {
ReadElementData(mat, useICRU90);
isOK = true;
}
if(!isOK && useICRU90) {
for(G4int j=0; j<3; ++j) {
if(matname == namesICRU90[j]) {
ReadMaterialData(matname, true);
isOK = true;
fMatIndex[idx] = fNmat;
++fNmat;
break;
}
}
}
if(!isOK) {
for(G4int j=0; j<31; ++j) {
if(matname == namesICRU73[j]) {
ReadMaterialData(matname, false);
isOK = true;
fMatIndex[idx] = fNmat;
++fNmat;
break;
}
}
}
if(!isOK) {
ReadElementData(mat, useICRU90);
fMatIndex[idx] = fNmat;
++fNmat;
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4IonICRU73Data::ReadMaterialData(const G4String& name, G4bool isICRU90)
{
for(G4int Z=3; Z<81; ++Z) {
std::ostringstream ost;
ost << fDataDirectory << "icru";
if(isICRU90 && Z <= 18) { ost << "90"; }
else { ost << "73"; }
ost << "/z" << Z << "_" << name << ".dat";
G4PhysicsLogVector* v = RetrieveVector(ost, false);
(fMatData[Z])->push_back(v);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4IonICRU73Data::ReadElementData(const G4Material* mat, G4bool useICRU90)
{
const G4ElementVector* elmv = mat->GetElementVector();
const G4double* dens = mat->GetFractionVector();
const G4int nelm = mat->GetNumberOfElements();
for(G4int Z=3; Z<81; ++Z) {
if(1 == nelm) {
FindOrBuildElementData(Z, (*elmv)[0]->GetZasInt(), useICRU90);
} else {
G4PhysicsLogVector* v2 = nullptr;
for(G4int j=0; j<nelm; ++j) {
v2 = FindOrBuildElementData(Z, (*elmv)[j]->GetZasInt(), useICRU90);
if(nullptr == v2) { break; }
}
// for one or more elements there is no data
if(nullptr == v2) {
fMatData[Z]->push_back(v2);
continue;
}
auto v = new G4PhysicsLogVector(fEmin, fEmax, fNbins, fSpline);
for(G4int i=0; i<=fNbins; ++i) {
G4double dedx = 0;
for(G4int j=0; j<nelm; ++j) {
G4PhysicsLogVector* v1 =
FindOrBuildElementData(Z, (*elmv)[j]->GetZasInt(), useICRU90);
dedx += (*v1)[i]*dens[j];
}
v->PutValue(i, dedx);
}
if(fSpline) { v->FillSecondDerivatives(); }
fMatData[Z]->push_back(v);
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4PhysicsLogVector*
G4IonICRU73Data::FindOrBuildElementData(const G4int Z, const G4int Z1,
G4bool useICRU90)
{
G4PhysicsLogVector* v = nullptr;
if(Z <= 80 && Z1 <= 80) {
v = fElmData[Z][Z1];
if(nullptr == v) {
G4bool isICRU90 = (useICRU90 && Z <= 18 &&
(Z1 == 1 || Z1 == 6 || Z1 == 7 || Z1 == 8));
std::ostringstream ost;
ost << fDataDirectory << "icru";
if(isICRU90) { ost << "90"; }
else { ost << "73"; }
ost << "/z" << Z << "_" << Z1 << ".dat";
v = RetrieveVector(ost, false);
fElmData[Z][Z1] = v;
}
}
return v;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4PhysicsLogVector*
G4IonICRU73Data::RetrieveVector(std::ostringstream& ost, G4bool warn)
{
G4PhysicsLogVector* v = nullptr;
std::ifstream filein(ost.str().c_str());
if (!filein.is_open()) {
if(warn) {
G4ExceptionDescription ed;
ed << "Data file <" << ost.str().c_str()
<< "> is not opened";
G4Exception("G4IonICRU73Data::RetrieveVector(..)","em013",
FatalException, ed, "Check G4LEDATA");
}
} else {
if(fVerbose > 0) {
G4cout << "File " << ost.str()
<< " is opened by G4IonICRU73Data" << G4endl;
}
// retrieve data from DB
if(!fVector->Retrieve(filein, true)) {
G4ExceptionDescription ed;
ed << "Data file <" << ost.str().c_str()
<< "> is not retrieved!";
G4Exception("G4IonICRU73Data::RetrieveVector(..)","had015",
FatalException, ed, "Check G4LEDATA");
} else {
if(fSpline) { fVector->FillSecondDerivatives(); }
v = new G4PhysicsLogVector(fEmin, fEmax, fNbins, fSpline);
for(G4int i=0; i<=fNbins; ++i) {
G4double e = v->Energy(i);
G4double dedx = fVector->Value(e);
v->PutValue(i, dedx);
}
const G4double fact = CLHEP::MeV * CLHEP::cm2 /( 0.001 * CLHEP::g);
v->ScaleVector(CLHEP::MeV, fact);
if(fSpline) { v->FillSecondDerivatives(); }
if(fVerbose > 1) { G4cout << *v << G4endl; }
}
}
return v;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......