Files
geant4/source/processes/electromagnetic/lowenergy/src/G4MicroElecCrossSectionDataSet.cc
T
2017-12-08 12:52:30 +01:00

548 lines
14 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. *
// ********************************************************************
//
// MR - 04/04/2012
// Based on G4DNACrossSectionDataSet
//
#include "G4MicroElecCrossSectionDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4EMDataSet.hh"
#include <vector>
#include <fstream>
#include <sstream>
G4MicroElecCrossSectionDataSet::G4MicroElecCrossSectionDataSet(G4VDataSetAlgorithm* argAlgorithm,
G4double argUnitEnergies,
G4double argUnitData)
:
algorithm(argAlgorithm), unitEnergies(argUnitEnergies), unitData(argUnitData)
{
z = 0;
}
G4MicroElecCrossSectionDataSet::~G4MicroElecCrossSectionDataSet()
{
CleanUpComponents();
if (algorithm)
delete algorithm;
}
G4bool G4MicroElecCrossSectionDataSet::LoadData(const G4String & argFileName)
{
CleanUpComponents();
G4String fullFileName(FullFileName(argFileName));
std::ifstream in(fullFileName, std::ifstream::binary|std::ifstream::in);
if (!in.is_open())
{
G4String message("Data file \"");
message+=fullFileName;
message+="\" not found";
G4Exception("G4MicroElecCrossSectionDataSet::LoadData","em0003",
FatalException,message);
return false;
}
std::vector<G4DataVector *> columns;
std::vector<G4DataVector *> log_columns;
std::stringstream *stream(new std::stringstream);
char c;
G4bool comment(false);
G4bool space(true);
G4bool first(true);
try
{
while (!in.eof())
{
in.get(c);
switch (c)
{
case '\r':
case '\n':
if (!first)
{
unsigned long i(0);
G4double value;
while (!stream->eof())
{
(*stream) >> value;
while (i>=columns.size())
{
columns.push_back(new G4DataVector);
log_columns.push_back(new G4DataVector);
}
columns[i]->push_back(value);
// N. A. Karakatsanis
// A condition is applied to check if negative or zero values are present in the dataset.
// If yes, then a near-zero value is applied to allow the computation of the logarithmic value
// If a value is zero, this simplification is acceptable
// If a value is negative, then it is not acceptable and the data of the particular column of
// logarithmic values should not be used by interpolation methods.
//
// Therefore, G4LogLogInterpolation and G4LinLogLogInterpolation should not be used if negative values are present.
// Instead, G4LinInterpolation is safe in every case
// SemiLogInterpolation is safe only if the energy columns are non-negative
// G4LinLogInterpolation is safe only if the cross section data columns are non-negative
if (value <=0.) value = 1e-300;
log_columns[i]->push_back(std::log10(value));
i++;
}
delete stream;
stream=new std::stringstream;
}
first=true;
comment=false;
space=true;
break;
case '#':
comment=true;
break;
case '\t':
case ' ':
space = true;
break;
default:
if (comment) { break; }
if (space && (!first)) { (*stream) << ' '; }
first=false;
(*stream) << c;
space=false;
}
}
}
catch(const std::ios::failure &e)
{
// some implementations of STL could throw a "failture" exception
// when read wants read characters after end of file
}
delete stream;
std::vector<G4DataVector *>::size_type maxI(columns.size());
if (maxI<2)
{
G4String message("Data file \"");
message+=fullFileName;
message+="\" should have at least two columns";
G4Exception("G4MicroElecCrossSectionDataSet::LoadData","em0005",
FatalException,message);
return false;
}
std::vector<G4DataVector*>::size_type i(1);
while (i<maxI)
{
G4DataVector::size_type maxJ(columns[i]->size());
if (maxJ!=columns[0]->size())
{
G4String message("Data file \"");
message+=fullFileName;
message+="\" has lines with a different number of columns";
G4Exception("G4MicroElecCrossSectionDataSet::LoadData","em0005",
FatalException,message);
return false;
}
G4DataVector::size_type j(0);
G4DataVector *argEnergies=new G4DataVector;
G4DataVector *argData=new G4DataVector;
G4DataVector *argLogEnergies=new G4DataVector;
G4DataVector *argLogData=new G4DataVector;
while(j<maxJ)
{
argEnergies->push_back(columns[0]->operator[] (j)*GetUnitEnergies());
argData->push_back(columns[i]->operator[] (j)*GetUnitData());
argLogEnergies->push_back(log_columns[0]->operator[] (j) + std::log10(GetUnitEnergies()));
argLogData->push_back(log_columns[i]->operator[] (j) + std::log10(GetUnitData()));
j++;
}
AddComponent(new G4EMDataSet(i-1, argEnergies, argData, argLogEnergies, argLogData, GetAlgorithm()->Clone(), GetUnitEnergies(), GetUnitData()));
i++;
}
i=maxI;
while (i>0)
{
i--;
delete columns[i];
delete log_columns[i];
}
return true;
}
G4bool G4MicroElecCrossSectionDataSet::LoadNonLogData(const G4String & argFileName)
{
CleanUpComponents();
G4String fullFileName(FullFileName(argFileName));
std::ifstream in(fullFileName, std::ifstream::binary|std::ifstream::in);
if (!in.is_open())
{
G4String message("Data file \"");
message+=fullFileName;
message+="\" not found";
G4Exception("G4MicroElecCrossSectionDataSet::LoadData","em0003",
FatalException,message);
return false;
}
std::vector<G4DataVector *> columns;
std::stringstream *stream(new std::stringstream);
char c;
G4bool comment(false);
G4bool space(true);
G4bool first(true);
try
{
while (!in.eof())
{
in.get(c);
switch (c)
{
case '\r':
case '\n':
if (!first)
{
unsigned long i(0);
G4double value;
while (!stream->eof())
{
(*stream) >> value;
while (i>=columns.size())
{
columns.push_back(new G4DataVector);
}
columns[i]->push_back(value);
i++;
}
delete stream;
stream=new std::stringstream;
}
first=true;
comment=false;
space=true;
break;
case '#':
comment=true;
break;
case '\t':
case ' ':
space = true;
break;
default:
if (comment) { break; }
if (space && (!first)) { (*stream) << ' '; }
first=false;
(*stream) << c;
space=false;
}
}
}
catch(const std::ios::failure &e)
{
// some implementations of STL could throw a "failture" exception
// when read wants read characters after end of file
}
delete stream;
std::vector<G4DataVector *>::size_type maxI(columns.size());
if (maxI<2)
{
G4String message("Data file \"");
message+=fullFileName;
message+="\" should have at least two columns";
G4Exception("G4MicroElecCrossSectionDataSet::LoadData","em0005",
FatalException,message);
return false;
}
std::vector<G4DataVector*>::size_type i(1);
while (i<maxI)
{
G4DataVector::size_type maxJ(columns[i]->size());
if (maxJ!=columns[0]->size())
{
G4String message("Data file \"");
message+=fullFileName;
message+="\" has lines with a different number of columns.";
G4Exception("G4MicroElecCrossSectionDataSet::LoadData","em0005",
FatalException,message);
return false;
}
G4DataVector::size_type j(0);
G4DataVector *argEnergies=new G4DataVector;
G4DataVector *argData=new G4DataVector;
while(j<maxJ)
{
argEnergies->push_back(columns[0]->operator[] (j)*GetUnitEnergies());
argData->push_back(columns[i]->operator[] (j)*GetUnitData());
j++;
}
AddComponent(new G4EMDataSet(i-1, argEnergies, argData, GetAlgorithm()->Clone(), GetUnitEnergies(), GetUnitData()));
i++;
}
i=maxI;
while (i>0)
{
i--;
delete columns[i];
}
return true;
}
G4bool G4MicroElecCrossSectionDataSet::SaveData(const G4String & argFileName) const
{
const size_t n(NumberOfComponents());
if (n==0)
{
G4Exception("G4MicroElecCrossSectionDataSet::SaveData","em0005",
FatalException,"Expected at least one component");
return false;
}
G4String fullFileName(FullFileName(argFileName));
std::ofstream out(fullFileName);
if (!out.is_open())
{
G4String message("Cannot open \"");
message+=fullFileName;
message+="\"";
G4Exception("G4MicroElecCrossSectionDataSet::SaveData","em0005",
FatalException,message);
return false;
}
G4DataVector::const_iterator iEnergies(GetComponent(0)->GetEnergies(0).begin());
G4DataVector::const_iterator iEnergiesEnd(GetComponent(0)->GetEnergies(0).end());
G4DataVector::const_iterator * iData(new G4DataVector::const_iterator[n]);
size_t k(n);
while (k>0)
{
k--;
iData[k]=GetComponent(k)->GetData(0).begin();
}
while (iEnergies!=iEnergiesEnd)
{
out.precision(10);
out.width(15);
out.setf(std::ofstream::left);
out << ((*iEnergies)/GetUnitEnergies());
k=0;
while (k<n)
{
out << ' ';
out.precision(10);
out.width(15);
out.setf(std::ofstream::left);
out << ((*(iData[k]))/GetUnitData());
iData[k]++;
k++;
}
out << std::endl;
iEnergies++;
}
delete[] iData;
return true;
}
G4String G4MicroElecCrossSectionDataSet::FullFileName(const G4String& argFileName) const
{
char* path = getenv("G4LEDATA");
if (!path)
{
G4Exception("G4MicroElecCrossSectionDataSet::FullFileName","em0006",
FatalException,"G4LEDATA environment variable not set.");
return "";
}
std::ostringstream fullFileName;
fullFileName << path << "/" << argFileName << ".dat";
return G4String(fullFileName.str().c_str());
}
G4double G4MicroElecCrossSectionDataSet::FindValue(G4double argEnergy, G4int /* argComponentId */) const
{
// Returns the sum over the shells corresponding to e
G4double value = 0.;
std::vector<G4VEMDataSet *>::const_iterator i(components.begin());
std::vector<G4VEMDataSet *>::const_iterator end(components.end());
while (i!=end)
{
value+=(*i)->FindValue(argEnergy);
i++;
}
return value;
}
void G4MicroElecCrossSectionDataSet::PrintData(void) const
{
const size_t n(NumberOfComponents());
G4cout << "The data set has " << n << " components" << G4endl;
G4cout << G4endl;
size_t i(0);
while (i<n)
{
G4cout << "--- Component " << i << " ---" << G4endl;
GetComponent(i)->PrintData();
i++;
}
}
void G4MicroElecCrossSectionDataSet::SetEnergiesData(G4DataVector* argEnergies,
G4DataVector* argData,
G4int argComponentId)
{
G4VEMDataSet * component(components[argComponentId]);
if (component)
{
component->SetEnergiesData(argEnergies, argData, 0);
return;
}
std::ostringstream message;
message << "Component " << argComponentId << " not found";
G4Exception("G4MicroElecCrossSectionDataSet::SetEnergiesData","em0005",
FatalException,message.str().c_str());
}
void G4MicroElecCrossSectionDataSet::SetLogEnergiesData(G4DataVector* argEnergies,
G4DataVector* argData,
G4DataVector* argLogEnergies,
G4DataVector* argLogData,
G4int argComponentId)
{
G4VEMDataSet * component(components[argComponentId]);
if (component)
{
component->SetLogEnergiesData(argEnergies, argData, argLogEnergies, argLogData, 0);
return;
}
std::ostringstream message;
message << "Component " << argComponentId << " not found";
G4Exception("G4MicroElecCrossSectionDataSet::SetLogEnergiesData","em0005",
FatalException,message.str().c_str());
}
void G4MicroElecCrossSectionDataSet::CleanUpComponents()
{
while (!components.empty())
{
if (components.back()) delete components.back();
components.pop_back();
}
}