Import Geant4 11.3.0.beta source tree
This commit is contained in:
@@ -0,0 +1,439 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// Author: E.Mendoza
|
||||
//
|
||||
// Creation date: May 2024
|
||||
//
|
||||
// Modifications:
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// NuDEX code (https://doi.org/10.1016/j.nima.2022.167894)
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include "G4NuDEXInternalConversion.hh"
|
||||
|
||||
|
||||
|
||||
//If alpha>0, use that value
|
||||
G4bool G4NuDEXInternalConversion::SampleInternalConversion(G4double Ene,G4int multipolarity,G4double alpha,G4bool CalculateProducts){
|
||||
|
||||
if(theZ<MINZINTABLES){ //then we have no info
|
||||
if(alpha<0){
|
||||
Ne=0;
|
||||
Ng=0;
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
G4double rand=theRandom4->Uniform(0,alpha+1);
|
||||
if(rand<alpha){ //then electron conversion
|
||||
Ne=1;
|
||||
Ng=0;
|
||||
Eele[0]=Ene; //which is not correct, but we don't know the binding energy
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ne=0;
|
||||
Ng=0;
|
||||
|
||||
if(multipolarity==0){ //maybe it is better to return true ... ?? --> no
|
||||
//return true;
|
||||
if(alpha<=0){
|
||||
return false;
|
||||
}
|
||||
//NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
G4bool usegivenalpha=true;
|
||||
if(NShells==0 || std::abs(multipolarity)>ICC_NMULTIP){return false;}
|
||||
if(alpha<0){
|
||||
usegivenalpha=false;
|
||||
alpha=GetICC(Ene,multipolarity);
|
||||
}
|
||||
|
||||
G4double rand=theRandom4->Uniform(0,alpha+1);
|
||||
if(rand<alpha){ //then electron conversion
|
||||
if(!CalculateProducts){return true;}
|
||||
//Select the orbital:
|
||||
if(usegivenalpha){rand=rand*GetICC(Ene,multipolarity)/alpha;} //renormalize rand to our alpha
|
||||
G4double cumul=0;
|
||||
for(G4int i=1;i<NShells;i++){
|
||||
cumul+=GetICC(Ene,multipolarity,i);
|
||||
//std::cout<<Ene<<" "<<multipolarity<<" "<<i<<" "<<GetICC(Ene,multipolarity,i)<<" "<<rand-1<<std::endl;
|
||||
if(cumul>=rand || multipolarity==0){ //then is this orbital
|
||||
Ne=1;
|
||||
Eele[0]=Ene-BindingEnergy[i];
|
||||
FillElectronHole(i); //now there is a hole there, in the filling procedure we emitt gammas and/or electrons
|
||||
if(Eele[0]<0){
|
||||
std::cout<<" For Z = "<<theZ<<" and orbital "<<OrbitalName[i]<<" --> Ene = "<<Ene<<" and BindingEnergy = "<<BindingEnergy[i]<<std::endl;
|
||||
std::cout<<" Given alpha is "<<alpha<<" ("<<usegivenalpha<<"), rand = "<<rand<<" and tabulated alpha for Ene = "<<Ene<<" and mult = "<<multipolarity<<" is "<<GetICC(Ene,multipolarity)<<" -- cumul = "<<cumul<<std::endl;
|
||||
for(G4int j=1;j<=NShells;j++){
|
||||
std::cout<<j<<" "<<GetICC(Ene,multipolarity,j)<<std::endl;
|
||||
}
|
||||
Eele[0]=0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
std::cout<<" ############ Warning in "<<__FILE__<<", line "<<__LINE__<<" ############"<<std::endl;
|
||||
std::cout<<" Given alpha is "<<alpha<<" and tabulated alpha for Ene = "<<Ene<<" and mult = "<<multipolarity<<" is "<<GetICC(Ene,multipolarity)<<" -- cumul = "<<cumul<<std::endl;
|
||||
for(G4int i=1;i<=NShells;i++){
|
||||
std::cout<<i<<" "<<GetICC(Ene,multipolarity,i)<<std::endl;
|
||||
}
|
||||
Ne=1;
|
||||
Eele[0]=Ene-BindingEnergy[NShells-1];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void G4NuDEXInternalConversion::FillElectronHole(G4int i_shell){
|
||||
|
||||
//A very simplified version of the process (... and false). It can be done with accuracy with G4AtomicTransitionManager
|
||||
|
||||
G4double fluoyield=0;
|
||||
if(i_shell==1){ //K-shell
|
||||
//Hubbell et al. (1994) formula for the fluorescence yield:
|
||||
G4double C0=0.0370,C1=0.03112,C2=5.44e-5,C3=-1.25e-6;
|
||||
G4double w_fac=std::pow(C0+C1*theZ+C2*theZ*theZ+C3*theZ*theZ*theZ,4);
|
||||
fluoyield=w_fac/(1.+w_fac);
|
||||
}
|
||||
else if(i_shell>=2 && i_shell<=4){ //L-shell
|
||||
//Hubbell et al. (1994) formula for the fluorescence yield:
|
||||
if(theZ>=3 && theZ<=36){
|
||||
fluoyield=1.939e-8*std::pow(theZ,3.8874);
|
||||
}
|
||||
else if(theZ>36){
|
||||
G4double C0=0.17765,C1=0.00298937,C2=8.91297e-5,C3=-2.67184e-7;
|
||||
G4double w_fac=std::pow(C0+C1*theZ+C2*theZ*theZ+C3*theZ*theZ*theZ,4);
|
||||
fluoyield=w_fac/(1.+w_fac);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4double rand=theRandom4->Uniform(0,1);
|
||||
if(rand<fluoyield){ //gamma emission
|
||||
Egam[Ng]=BindingEnergy[i_shell];
|
||||
Ng++;
|
||||
}
|
||||
else{ //electron emission
|
||||
Eele[Ne]=BindingEnergy[i_shell];
|
||||
Ne++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//If i_shell<0 --> the total alpha
|
||||
G4double G4NuDEXInternalConversion::GetICC(G4double Ene,G4int multipolarity,G4int i_shell){
|
||||
|
||||
if(theZ<MINZINTABLES){ //then we have no info
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(NShells==0 || std::abs(multipolarity)>ICC_NMULTIP){return 0;}
|
||||
|
||||
//-----------------------------------------
|
||||
//Total:
|
||||
//The following line does not work, due to interpolation below binding energies:
|
||||
//if(i_shell<0){i_shell=NShells;}
|
||||
|
||||
if(i_shell<0){
|
||||
G4double result=0;
|
||||
for(G4int i=1;i<NShells;i++){
|
||||
result+=GetICC(Ene,multipolarity,i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
if(Ene<BindingEnergy[i_shell]){return 0;}
|
||||
|
||||
if(np[i_shell]==0){
|
||||
std::cout<<" shell "<<i_shell<<" has not been initialized"<<std::endl;
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
if(i_shell==NShells && Ene<Eg[i_shell][0]){ //then we cannot extrapolate, because of the binding energies of the different shells
|
||||
G4double total=0;
|
||||
for(G4int i=1;i<NShells;i++){total+=GetICC(Ene,multipolarity,i);}
|
||||
return total;
|
||||
}
|
||||
|
||||
if(multipolarity>0){
|
||||
return Interpolate(Ene,np[i_shell],Eg[i_shell],Icc_E[multipolarity-1][i_shell]);
|
||||
}
|
||||
else if(multipolarity<0){
|
||||
return Interpolate(Ene,np[i_shell],Eg[i_shell],Icc_M[(-multipolarity)-1][i_shell]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4NuDEXInternalConversion::G4NuDEXInternalConversion(G4int Z){
|
||||
theZ=Z;
|
||||
NShells=0;
|
||||
for(G4int i=0;i<ICC_MAXNSHELLS;i++){
|
||||
Eg[i]=0; np[i]=0; BindingEnergy[i]=0;
|
||||
for(G4int j=0;j<ICC_NMULTIP;j++){
|
||||
Icc_E[j][i]=0; Icc_M[j][i]=0;
|
||||
}
|
||||
}
|
||||
theRandom4= new G4NuDEXRandom(1234567);
|
||||
}
|
||||
|
||||
|
||||
G4NuDEXInternalConversion::~G4NuDEXInternalConversion(){
|
||||
for(G4int i=0;i<ICC_MAXNSHELLS;i++){
|
||||
if(Eg[i]!=0){delete [] Eg[i];}
|
||||
for(G4int j=0;j<ICC_NMULTIP;j++){
|
||||
if(Icc_E[j][i]!=0){delete [] Icc_E[j][i];}
|
||||
if(Icc_M[j][i]!=0){delete [] Icc_M[j][i];}
|
||||
}
|
||||
}
|
||||
delete theRandom4;
|
||||
}
|
||||
|
||||
void G4NuDEXInternalConversion::PrintICC(std::ostream &out){
|
||||
|
||||
char word[1000];
|
||||
out<<" ######################################################################################################################################### "<<std::endl;
|
||||
out<<" ICC"<<std::endl;
|
||||
out<<" Z = "<<theZ<<std::endl;
|
||||
out<<" NShells = "<<NShells<<std::endl;
|
||||
out<<" ----------------------------------------------------------------------------------------------------------------------------------------"<<std::endl;
|
||||
out<<" Total calculated from the sum of the partials:"<<std::endl;
|
||||
out<<" E_g E1 E2 E3 E4 E5 M1 M2 M3 M4 M5 "<<std::endl;
|
||||
for(G4int j=0;j<np[NShells];j++){
|
||||
snprintf(word,1000,"%10.4g",Eg[NShells][j]); out<<word;
|
||||
for(G4int k=0;k<ICC_NMULTIP;k++){
|
||||
snprintf(word,1000," %10.4g",Icc_E[k][NShells][j]); out<<word;
|
||||
}
|
||||
for(G4int k=0;k<ICC_NMULTIP;k++){
|
||||
snprintf(word,1000," %10.4g",Icc_M[k][NShells][j]); out<<word;
|
||||
}
|
||||
out<<std::endl;
|
||||
}
|
||||
out<<" ----------------------------------------------------------------------------------------------------------------------------------------"<<std::endl;
|
||||
for(G4int i=0;i<NShells;i++){
|
||||
out<<" ----------------------------------------------------------------------------------------------------------------------------------------"<<std::endl;
|
||||
out<<" Binding energy = "<<BindingEnergy[i]<<" MeV - OrbitalName = "<<OrbitalName[i]<<" - np = "<<np[i]<<std::endl;
|
||||
out<<" E_g E1 E2 E3 E4 E5 M1 M2 M3 M4 M5 "<<std::endl;
|
||||
for(G4int j=0;j<np[i];j++){
|
||||
snprintf(word,1000,"%10.4g",Eg[i][j]); out<<word;
|
||||
for(G4int k=0;k<ICC_NMULTIP;k++){
|
||||
snprintf(word,1000," %10.4g",Icc_E[k][i][j]); out<<word;
|
||||
}
|
||||
for(G4int k=0;k<ICC_NMULTIP;k++){
|
||||
snprintf(word,1000," %10.4g",Icc_M[k][i][j]); out<<word;
|
||||
}
|
||||
out<<std::endl;
|
||||
}
|
||||
out<<" ----------------------------------------------------------------------------------------------------------------------------------------"<<std::endl;
|
||||
}
|
||||
out<<" ########################################################################################################################################## "<<std::endl;
|
||||
}
|
||||
|
||||
void G4NuDEXInternalConversion::Init(const char* fname){
|
||||
|
||||
if(theZ<MINZINTABLES){ //then we have no info
|
||||
return;
|
||||
}
|
||||
|
||||
if(NShells!=0){ //Init only once
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
std::ifstream in(fname);
|
||||
if(!in.good()){
|
||||
std::cout<<" ################ Error opening "<<fname<<" ################"<<std::endl;
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
std::string word;
|
||||
NShells=1;
|
||||
while(in>>word){
|
||||
if(word.c_str()[0]=='Z' && word.c_str()[1]=='='){
|
||||
if(std::atoi(&(word.c_str()[2]))==theZ){
|
||||
in>>word>>word;
|
||||
G4int orbindex;
|
||||
if(word==std::string("Total")){
|
||||
in.ignore(1000,'\n');
|
||||
in.ignore(1000,'\n');
|
||||
orbindex=0;
|
||||
}
|
||||
else{
|
||||
orbindex=NShells;
|
||||
in>>word>>word>>BindingEnergy[NShells]>>word;
|
||||
BindingEnergy[NShells]*=1.e-6; // all in MeV
|
||||
in.ignore(1000,'\n');
|
||||
in.ignore(1000,'\n');
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
size_t sz,sz2;
|
||||
G4int np_tmp=0;
|
||||
G4double Eg_tmp[1000],Icc_E_tmp[ICC_NMULTIP][100],Icc_M_tmp[ICC_NMULTIP][100];
|
||||
while(getline(in,word)){
|
||||
if(word.size()<100){
|
||||
np[orbindex]=np_tmp;
|
||||
Eg[orbindex]=new G4double[np_tmp];
|
||||
for(G4int j=0;j<np_tmp;j++){
|
||||
Eg[orbindex][j]=Eg_tmp[j];
|
||||
}
|
||||
for(G4int i=0;i<ICC_NMULTIP;i++){
|
||||
Icc_E[i][orbindex]=new G4double[np_tmp];
|
||||
Icc_M[i][orbindex]=new G4double[np_tmp];
|
||||
}
|
||||
for(G4int i=0;i<ICC_NMULTIP;i++){
|
||||
for(G4int j=0;j<np_tmp;j++){
|
||||
Icc_E[i][orbindex][j]=Icc_E_tmp[i][j];
|
||||
Icc_M[i][orbindex][j]=Icc_M_tmp[i][j];
|
||||
}
|
||||
}
|
||||
if(orbindex!=0){NShells++;}
|
||||
break;
|
||||
}
|
||||
else{
|
||||
sz=0;
|
||||
Eg_tmp[np_tmp]=std::stof(word,&sz2);
|
||||
Eg_tmp[np_tmp]*=1.e-3; //all to MeV
|
||||
sz+=sz2;
|
||||
for(G4int i=0;i<ICC_NMULTIP;i++){
|
||||
Icc_E_tmp[i][np_tmp]=std::stof(word.substr(sz),&sz2); sz+=sz2;
|
||||
}
|
||||
for(G4int i=0;i<ICC_NMULTIP;i++){
|
||||
Icc_M_tmp[i][np_tmp]=std::stof(word.substr(sz),&sz2); sz+=sz2;
|
||||
}
|
||||
if((G4int)(std::stof(word.substr(sz),&sz2)+0.01)!=theZ){
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
sz+=sz2;
|
||||
sz2=word.find_first_not_of(' ',sz);
|
||||
if(np_tmp==0){OrbitalName[orbindex]=word.substr(sz2,word.substr(sz2).size()-1);}
|
||||
np_tmp++;
|
||||
}
|
||||
}
|
||||
if(orbindex==0){break;}
|
||||
//--------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!in.good()){
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
in.close();
|
||||
|
||||
MakeTotal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Total Icc goes to nShell=NShells
|
||||
void G4NuDEXInternalConversion::MakeTotal(){
|
||||
|
||||
if(np[0]==0 || Eg[0]==0){
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
//We evaluate it in the same frame as the total given by the data:
|
||||
BindingEnergy[NShells]=0;
|
||||
np[NShells]=np[0];
|
||||
Eg[NShells]=new G4double[np[NShells]];
|
||||
for(G4int i=0;i<ICC_NMULTIP;i++){
|
||||
Icc_E[i][NShells]=new G4double[np[NShells]];
|
||||
Icc_M[i][NShells]=new G4double[np[NShells]];
|
||||
}
|
||||
for(G4int k=0;k<np[NShells];k++){
|
||||
for(G4int j=0;j<ICC_NMULTIP;j++){
|
||||
Icc_E[j][NShells][k]=0;
|
||||
Icc_M[j][NShells][k]=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(G4int k=0;k<np[NShells];k++){
|
||||
Eg[NShells][k]=Eg[0][k];
|
||||
for(G4int i=1;i<NShells;i++){
|
||||
for(G4int j=0;j<ICC_NMULTIP;j++){
|
||||
Icc_E[j][NShells][k]+=GetICC(Eg[NShells][k],j+1,i);
|
||||
Icc_M[j][NShells][k]+=GetICC(Eg[NShells][k],-j-1,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//if val>x[npmax] then ---> return 0
|
||||
G4double G4NuDEXInternalConversion::Interpolate(G4double val,G4int npoints,G4double* x,G4double* y){
|
||||
|
||||
G4int i_interp=-1;
|
||||
for(G4int i=1;i<npoints;i++){
|
||||
if(x[i]>=val){i_interp=i-1; break;}
|
||||
}
|
||||
if(i_interp<0){return 0;}
|
||||
|
||||
|
||||
/*
|
||||
//y=a0+a1*x
|
||||
G4double a1=(y[i_interp+1]-y[i_interp])/(x[i_interp+1]-x[i_interp]);
|
||||
G4double a0=y[i_interp]-a1*x[i_interp];
|
||||
|
||||
return (a0+a1*val);
|
||||
*/
|
||||
|
||||
//It is better a log-log interpolation:
|
||||
if(y[i_interp+1]<=0 || y[i_interp]<=0 || x[i_interp+1]<=0 || x[i_interp]<=0){
|
||||
//y=a0+a1*x
|
||||
G4double a1=(y[i_interp+1]-y[i_interp])/(x[i_interp+1]-x[i_interp]);
|
||||
G4double a0=y[i_interp]-a1*x[i_interp];
|
||||
|
||||
return (a0+a1*val);
|
||||
}
|
||||
|
||||
//log(y)=a0+a1*log(x)
|
||||
G4double a1=std::log(y[i_interp+1]/y[i_interp])/std::log(x[i_interp+1]/x[i_interp]);
|
||||
G4double a0=std::log(y[i_interp])-a1*std::log(x[i_interp]);
|
||||
|
||||
G4double result=std::exp(a0+a1*std::log(val));
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// Author: E.Mendoza
|
||||
//
|
||||
// Creation date: May 2024
|
||||
//
|
||||
// Modifications:
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// NuDEX code (https://doi.org/10.1016/j.nima.2022.167894)
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
#include "G4NuDEXRandom.hh"
|
||||
#include "G4NuDEXLevelDensity.hh"
|
||||
|
||||
|
||||
|
||||
G4NuDEXLevelDensity::G4NuDEXLevelDensity(G4int aZ,G4int aA,G4int ldtype){
|
||||
|
||||
Z_Int=aZ;
|
||||
A_Int=aA;
|
||||
LDType=ldtype;
|
||||
if(LDType<0){LDType=DEFAULTLDTYPE;}
|
||||
A_mass=A_Int;
|
||||
if(LDType!=1 && LDType!=2 && LDType!=3){
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
HasData=false;
|
||||
|
||||
Sn=-1; D0=-1; I0=-1000;
|
||||
Ed=0;
|
||||
ainf_ldpar=0; gamma_ldpar=0; dW_ldpar=0; Delta_ldpar=0; T_ldpar=0; E0_ldpar=0; Ex_ldpar=0;
|
||||
}
|
||||
|
||||
|
||||
G4int G4NuDEXLevelDensity::ReadLDParameters(const char* dirname,const char* inputfname,const char* defaultinputfname){
|
||||
|
||||
char fname[100];
|
||||
if(LDType==1 || LDType==3){ // Back-Shifted-Fermi-Gas model
|
||||
snprintf(fname,100,"%s/LevelDensities/level-densities-bfmeff.dat",dirname);
|
||||
}
|
||||
else{ // Constant Temperature
|
||||
snprintf(fname,100,"%s/LevelDensities/level-densities-ctmeff.dat",dirname);
|
||||
}
|
||||
G4double EL=0,EU=0;
|
||||
|
||||
std::ifstream in(fname);
|
||||
if(!in.good()){
|
||||
std::cout<<" ######## Error opening file "<<fname<<" ########"<<std::endl;
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
G4int aZ,aA;
|
||||
char word[200];
|
||||
in.ignore(10000,'\n');
|
||||
|
||||
//std::cout<<" LDType="<<LDType<<" "<<fname<<" "<<Z_Int<<" "<<A_Int<<std::endl;
|
||||
|
||||
while(in>>aZ>>aA){
|
||||
if(aZ==Z_Int && aA==A_Int){
|
||||
if(LDType==1 || LDType==3){
|
||||
in>>word>>I0>>Sn>>D0>>word>>word>>EL>>word>>EU>>dW_ldpar>>gamma_ldpar>>ainf_ldpar>>word>>Delta_ldpar;
|
||||
Ex_ldpar=0; E0_ldpar=0; T_ldpar=0;
|
||||
Ed=(EL+EU)/2.;
|
||||
}
|
||||
else if(LDType==2){
|
||||
in>>word>>I0>>Sn>>D0>>word>>word>>EL>>word>>EU>>dW_ldpar>>gamma_ldpar>>ainf_ldpar>>word>>Delta_ldpar>>Ex_ldpar>>E0_ldpar>>T_ldpar;
|
||||
Ed=(EL+EU)/2.;
|
||||
}
|
||||
else{
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
if(in.good()){
|
||||
HasData=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
in.ignore(10000,'\n');
|
||||
}
|
||||
in.close();
|
||||
|
||||
|
||||
//Re-write some parameters if inputfname!=0
|
||||
if(defaultinputfname!=0){
|
||||
SearchLDParametersInInputFile(defaultinputfname);
|
||||
}
|
||||
if(inputfname!=0){
|
||||
SearchLDParametersInInputFile(inputfname);
|
||||
}
|
||||
|
||||
if(!HasData){ //no data
|
||||
G4int check=CalculateLDParameters_BSFG(dirname);
|
||||
if(check==0){
|
||||
HasData=true;
|
||||
if(LDType==2){
|
||||
LDType=1;
|
||||
std::cout<<" ##### WARNING: level density model for ZA="<<Z_Int*1000+A_Int<<" changed to Back-Shifted-Fermi-Gas model #####"<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(HasData){return 0;}
|
||||
|
||||
|
||||
//else, some problem reading ...
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
G4int G4NuDEXLevelDensity::CalculateLDParameters_BSFG(const char* dirname){
|
||||
|
||||
//Eq. 61 of RIPL-3:
|
||||
G4double alpha=0.0722396; //MeV^{-1}
|
||||
G4double beta= 0.195267; //MeV^{-1}
|
||||
G4double gamma0=0.410289; //MeV^{-1}
|
||||
G4double delta=0.173015; //MeV
|
||||
|
||||
//Delta_ldpar: Eq. 50 of RIPL-3:
|
||||
G4double n_par=0;
|
||||
if((Z_Int%2)==1 && ((A_Int-Z_Int)%2)==1){n_par=-1;} //odd-odd (impar-impar)
|
||||
if((Z_Int%2)==0 && ((A_Int-Z_Int)%2)==0){n_par=1;} //even-even (par-par)
|
||||
Delta_ldpar=n_par*12/std::sqrt(A_mass)+delta;
|
||||
|
||||
//ainf_ldpar: Eq. 52 of RIPL-3:
|
||||
ainf_ldpar=alpha*A_Int+beta*std::pow(A_mass,2./3.);
|
||||
|
||||
//gamma_ldpar: Eq. 53 of RIPL-3:
|
||||
gamma_ldpar=gamma0/std::pow(A_mass,1./3.);
|
||||
|
||||
//dW_ldpar --> from data file
|
||||
char fname[100];
|
||||
snprintf(fname,100,"%s/LevelDensities/shellcor-ms.dat",dirname);
|
||||
std::ifstream in(fname);
|
||||
if(!in.good()){
|
||||
std::cout<<" ######## Error opening file "<<fname<<" ########"<<std::endl;
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
G4int aZ,aA;
|
||||
char word[200];
|
||||
in.ignore(10000,'\n');
|
||||
in.ignore(10000,'\n');
|
||||
in.ignore(10000,'\n');
|
||||
in.ignore(10000,'\n');
|
||||
while(in>>aZ>>aA){
|
||||
if(aZ==Z_Int && aA==A_Int){
|
||||
in>>word>>dW_ldpar;
|
||||
if(in.good()){break;}
|
||||
}
|
||||
in.ignore(10000,'\n');
|
||||
}
|
||||
if(!in.good()){//no data found
|
||||
return -1;
|
||||
}
|
||||
in.close();
|
||||
|
||||
Ex_ldpar=0; E0_ldpar=0; T_ldpar=0;
|
||||
Ed=0;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4int G4NuDEXLevelDensity::SearchLDParametersInInputFile(const char* inputfname){
|
||||
|
||||
if(inputfname!=0){
|
||||
std::ifstream in2(inputfname);
|
||||
if(!in2.good()){
|
||||
std::cout<<" ############## Error opening "<<inputfname<<" ##############"<<std::endl;
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
std::string word_tmp;
|
||||
while(in2>>word_tmp){
|
||||
if(word_tmp[0]=='#'){in2.ignore(10000,'\n');}
|
||||
if(word_tmp==std::string("END")){break;}
|
||||
if(word_tmp==std::string("LDPARAMETERS")){
|
||||
in2>>LDType;
|
||||
if(LDType==1){
|
||||
in2>>dW_ldpar>>gamma_ldpar>>ainf_ldpar>>Delta_ldpar;
|
||||
}
|
||||
else if(LDType==2){
|
||||
in2>>dW_ldpar>>gamma_ldpar>>ainf_ldpar>>Delta_ldpar>>Ex_ldpar>>E0_ldpar>>T_ldpar;
|
||||
}
|
||||
else if(LDType==3){
|
||||
in2>>ainf_ldpar>>Delta_ldpar;
|
||||
}
|
||||
else{
|
||||
std::cout<<" ############## Error: Unknown LDType="<<LDType<<" in "<<inputfname<<" ##############"<<std::endl;
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
if(!in2.good()){
|
||||
std::cout<<" ############## Error reading "<<inputfname<<" ##############"<<std::endl;
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
HasData=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
in2.close();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void G4NuDEXLevelDensity::PrintParametersInInputFileFormat(std::ostream &out){
|
||||
|
||||
out<<"LDPARAMETERS"<<std::endl;
|
||||
out<<LDType<<std::endl;
|
||||
out.precision(15);
|
||||
if(LDType==1){
|
||||
out<<dW_ldpar<<" "<<gamma_ldpar<<" "<<ainf_ldpar<<" "<<Delta_ldpar<<std::endl;
|
||||
}
|
||||
else if(LDType==2){
|
||||
out<<dW_ldpar<<" "<<gamma_ldpar<<" "<<ainf_ldpar<<" "<<Delta_ldpar<<" "<<Ex_ldpar<<" "<<E0_ldpar<<" "<<T_ldpar<<std::endl;
|
||||
}
|
||||
else if(LDType==3){
|
||||
out<<ainf_ldpar<<" "<<Delta_ldpar<<std::endl;
|
||||
}
|
||||
out<<std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
G4double G4NuDEXLevelDensity::GetNucleusTemperature(G4double ExcEnergy){
|
||||
|
||||
if(!HasData){
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
if(ExcEnergy<Ex_ldpar && LDType==2){
|
||||
return T_ldpar;
|
||||
}
|
||||
|
||||
G4double Uval=ExcEnergy-Delta_ldpar;
|
||||
if(Uval<=0){return 0;}
|
||||
G4double a_ldpar=ainf_ldpar*(1.+dW_ldpar/Uval*(1.-std::exp(-gamma_ldpar*Uval)));
|
||||
if(LDType==3){
|
||||
a_ldpar=ainf_ldpar;
|
||||
}
|
||||
return std::sqrt(Uval/a_ldpar);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Gilbert-Cameron:
|
||||
G4double G4NuDEXLevelDensity::GetLevelDensity(G4double ExcEnergy,G4double spin,G4bool ,G4bool TotalLevelDensity){
|
||||
|
||||
if(!HasData){
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
//If A_Int even/odd --> spinx2 (spin_val*2) should be even/odd
|
||||
if(((A_Int+(G4int)(spin*2+0.01))%2)!=0 && (TotalLevelDensity==false)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
G4double Uval=ExcEnergy-Delta_ldpar;
|
||||
if(Uval<0){Uval=1.e-6;}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Back shifted: von Egidy et al., NP A481 (1988) 189
|
||||
if(LDType==3){
|
||||
G4double sig2=0.0888*std::pow(A_mass,2./3.)*std::sqrt(ainf_ldpar*Uval);
|
||||
G4double sig=std::sqrt(sig2);
|
||||
G4double rho=0.05893*std::exp(2.*std::sqrt(ainf_ldpar*Uval))/sig/std::pow(ainf_ldpar,0.25)/std::pow(Uval,1.25);
|
||||
G4double xj2=(spin+0.5)*(spin+0.5);
|
||||
G4double fj=(2.*spin+1.)/2./sig2*std::exp(-xj2/2./sig2);
|
||||
return 0.5*fj*rho;
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
//statistical factor from eq. 39 of RIPL-3 manual, and sigma2 from eqs. 57-60
|
||||
G4double Uval_Sn=Sn-Delta_ldpar;
|
||||
G4double a_ldpar=ainf_ldpar*(1.+dW_ldpar/Uval*(1.-std::exp(-gamma_ldpar*Uval)));
|
||||
G4double a_ldpar_Sn=ainf_ldpar*(1.+dW_ldpar/Uval_Sn*(1.-std::exp(-gamma_ldpar*Uval_Sn)));
|
||||
G4double sigma2_f=0.01389*std::pow(A_mass,5./3.)/ainf_ldpar*std::sqrt(a_ldpar*Uval);
|
||||
G4double sigma2_f_Sn=0.01389*std::pow(A_mass,5./3.)/ainf_ldpar*std::sqrt(a_ldpar_Sn*Uval);
|
||||
G4double sigma2_d=(0.83*std::pow(A_mass,0.26))*(0.83*std::pow(A_mass,0.26));
|
||||
|
||||
G4double sigma2;
|
||||
if(ExcEnergy<=Ed){
|
||||
sigma2=sigma2_d;//if ExcEnergy<Ed
|
||||
}
|
||||
else if(ExcEnergy<=Sn){
|
||||
sigma2=sigma2_d+(ExcEnergy-Ed)/(Sn-Ed)*(sigma2_f_Sn-sigma2_d);
|
||||
}
|
||||
else{
|
||||
sigma2=sigma2_f;
|
||||
}
|
||||
G4double statfactor=1./2.*(2.*spin+1.)/(2.*sigma2)*std::exp(-(spin+1/2.)*(spin+1/2.)/2./sigma2);
|
||||
if(TotalLevelDensity==true){
|
||||
statfactor=1;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
//CT + BSFG: Gilbert & Cameron, Can.J.Phys. 43 (1965) 1446
|
||||
if(LDType==2 && ExcEnergy<Ex_ldpar){
|
||||
G4double totalrho=std::exp((ExcEnergy-E0_ldpar)/T_ldpar)/T_ldpar;
|
||||
return totalrho*statfactor;
|
||||
}
|
||||
|
||||
//Else: BSFGM (LDType==1 or ExcEnergy>Ex_ldpar)
|
||||
G4double rhotot_f=1./std::sqrt(2.*sigma2)/12.*std::exp(2.*std::sqrt(a_ldpar*Uval))/std::pow(a_ldpar,1./4.)/std::pow(Uval,5./4.);
|
||||
G4double rhotot_0=std::exp(1.)*a_ldpar/12./std::sqrt(sigma2)*std::exp(a_ldpar*Uval);
|
||||
G4double totalrho=1./(1./rhotot_f+1./rhotot_0);
|
||||
|
||||
return totalrho*statfactor;
|
||||
|
||||
}
|
||||
|
||||
|
||||
G4double G4NuDEXLevelDensity::EstimateInverse(G4double LevDen_iMeV,G4double spin,G4bool parity){
|
||||
|
||||
//We assume that rho is a monotonically increasing function
|
||||
|
||||
G4double tolerance=0.001; //the result will have this relative tolerance. 0.01 means 1%
|
||||
|
||||
G4double xmin=0;
|
||||
G4double xmax=1;
|
||||
while(GetLevelDensity(xmax,spin,parity)<LevDen_iMeV){
|
||||
xmax*=2;
|
||||
}
|
||||
|
||||
while(xmin/xmax<1-tolerance){
|
||||
G4double x0=(xmin+xmax)/2.;
|
||||
if(GetLevelDensity(x0,spin,parity)<LevDen_iMeV){
|
||||
xmin=x0;
|
||||
}
|
||||
else{
|
||||
xmax=x0;
|
||||
}
|
||||
}
|
||||
|
||||
return (xmin+xmax)/2.;
|
||||
|
||||
}
|
||||
|
||||
|
||||
G4double G4NuDEXLevelDensity::Integrate(G4double Emin,G4double Emax,G4double spin,G4bool parity){
|
||||
|
||||
G4int nb=1000;
|
||||
G4double Integral=0,x1,x2,y1,y2;
|
||||
for(G4int i=0;i<nb;i++){
|
||||
x1=Emin+(Emax-Emin)*i/(G4double)(nb-1.);
|
||||
x2=Emin+(Emax-Emin)*(i+1.)/(G4double)(nb-1.);
|
||||
y1=GetLevelDensity(x1,spin,parity);
|
||||
y2=GetLevelDensity(x2,spin,parity);
|
||||
Integral+=(y1+y2)/2.*(x2-x1);
|
||||
}
|
||||
|
||||
return Integral;
|
||||
}
|
||||
|
||||
void G4NuDEXLevelDensity::PrintParameters(std::ostream &out){
|
||||
|
||||
out<<" Level density type: "<<LDType<<std::endl;
|
||||
if(LDType==1){ // Back-Shifted-Fermi-Gas model
|
||||
out<<" ainf = "<<ainf_ldpar<<" gamma = "<<gamma_ldpar<<" dW = "<<dW_ldpar<<" Delta = "<<Delta_ldpar<<std::endl;
|
||||
}
|
||||
else{
|
||||
out<<" ainf = "<<ainf_ldpar<<" gamma = "<<gamma_ldpar<<" dW = "<<dW_ldpar<<" Delta = "<<Delta_ldpar<<" T = "<<T_ldpar<<" E0 = "<<E0_ldpar<<" Ex = "<<Ex_ldpar<<std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,351 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 source file
|
||||
//
|
||||
// File name: G4NuDEXNeutronCaptureModel
|
||||
//
|
||||
// Author: E.Mendoza & A.Ribon
|
||||
//
|
||||
// Creation date: 29 May 2024
|
||||
//
|
||||
// Description: This class (a proxy of the class G4NuDEX) uses
|
||||
// the NuDEX model to produce gammas and internal
|
||||
// conversion electrons from neutron capture.
|
||||
// Whenever NuDEX is not applicable, G4PhotonEvaporation
|
||||
// is used.
|
||||
// The implementation of this class follows the code
|
||||
// of the class G4NeutronRadCapture.
|
||||
//
|
||||
// Modifications:
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
|
||||
#include "G4NuDEXNeutronCaptureModel.hh"
|
||||
#include "G4NuDEXStatisticalNucleus.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4LorentzVector.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Positron.hh"
|
||||
#include "G4Deuteron.hh"
|
||||
#include "G4Triton.hh"
|
||||
#include "G4He3.hh"
|
||||
#include "G4Alpha.hh"
|
||||
#include "G4NucleiProperties.hh"
|
||||
#include "G4IonTable.hh"
|
||||
#include "G4ParticleTable.hh"
|
||||
#include "G4HadronicParameters.hh"
|
||||
#include "G4DeexPrecoParameters.hh"
|
||||
#include "G4NuclearLevelData.hh"
|
||||
#include "G4PhotonEvaporation.hh"
|
||||
#include "G4PhysicsModelCatalog.hh"
|
||||
|
||||
|
||||
G4NuDEXNeutronCaptureModel::G4NuDEXNeutronCaptureModel() : G4HadronicInteraction( "nuDEX_neutronCapture" ) {
|
||||
for ( G4int i = 0; i < G4NUDEX_MAXZA; i++ ) {
|
||||
theStatisticalNucleus[i] = nullptr;
|
||||
HasData[i] = 0;
|
||||
}
|
||||
BrOption = -1;
|
||||
BandWidth = 0;
|
||||
NuDEXLibDirectory = "";
|
||||
photonEvaporation = nullptr;
|
||||
auto ch = G4FindDataDir( "G4NUDEXLIBDATA" );
|
||||
if ( ch == nullptr ) {
|
||||
G4Exception( "G4NuDEXNeutronCaptureModel()", "had0707", FatalException, "Environment variable G4NUDEXLIBDATA is not defined" );
|
||||
} else {
|
||||
NuDEXLibDirectory = G4String(ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void G4NuDEXNeutronCaptureModel::InitialiseModel() {
|
||||
if ( photonEvaporation != nullptr ) return;
|
||||
G4DeexPrecoParameters* param = G4NuclearLevelData::GetInstance()->GetParameters();
|
||||
minExcitation = param->GetMinExcitation();
|
||||
photonEvaporation = new G4PhotonEvaporation;
|
||||
photonEvaporation->Initialise();
|
||||
photonEvaporation->SetICM( true );
|
||||
secID = G4PhysicsModelCatalog::GetModelID( "model_" + GetModelName() );
|
||||
lowestEnergyLimit = 10.0*CLHEP::eV;
|
||||
minExcitation = 0.1*CLHEP::keV;
|
||||
}
|
||||
|
||||
|
||||
G4NuDEXNeutronCaptureModel::~G4NuDEXNeutronCaptureModel(){
|
||||
for ( G4int i = 0; i < G4NUDEX_MAXZA; i++ ) {
|
||||
if ( theStatisticalNucleus[i] ) delete theStatisticalNucleus[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4HadFinalState* G4NuDEXNeutronCaptureModel::ApplyYourself( const G4HadProjectile &aTrack, G4Nucleus &theNucleus ) {
|
||||
theParticleChange.Clear();
|
||||
theParticleChange.SetStatusChange( stopAndKill );
|
||||
G4int A = theNucleus.GetA_asInt();
|
||||
G4int Z = theNucleus.GetZ_asInt();
|
||||
G4double time = aTrack.GetGlobalTime(); // Time in the lab frame
|
||||
// Create initial state
|
||||
G4LorentzVector lab4mom( 0.0, 0.0, 0.0, G4NucleiProperties::GetNuclearMass(A, Z) );
|
||||
lab4mom += aTrack.Get4Momentum();
|
||||
G4double systemMass = lab4mom.mag();
|
||||
++A; // Compound nucleus: target nucleus + neutron
|
||||
G4double compoundMass = G4NucleiProperties::GetNuclearMass(A, Z);
|
||||
// If the energy available is to small to do anything interesting, gives up
|
||||
if ( systemMass - compoundMass <= lowestEnergyLimit ) return &theParticleChange;
|
||||
G4ThreeVector boostFromCMtoLAB = lab4mom.boostVector();
|
||||
G4double neutronEnergy = aTrack.GetKineticEnergy();
|
||||
|
||||
// Try to apply NuDEX
|
||||
//G4int lspin = 0; // l-spin = 0, 1, 2 --> s-wave, p-wave, d-wave ...
|
||||
//G4int jspinx2 = -1; // A negative value of jspinx2 means that is sampled according to the 2J+1 rule.
|
||||
//G4int initialLevel = SelectInitialLevel( Z, A, neutronEnergy, lspin, jspinx2 );
|
||||
G4int initialLevel = -1; // thermal neutron capture
|
||||
std::vector< char > pType;
|
||||
std::vector< G4double > pEnergy, pTime;
|
||||
G4int npar = GenerateNeutronCaptureCascade( Z, A, neutronEnergy, initialLevel, pType, pEnergy, pTime );
|
||||
if ( npar > 0 ) { // NuDEX can be applied
|
||||
|
||||
G4LorentzVector remainingLab4mom = lab4mom;
|
||||
G4double latestEmission = time;
|
||||
// Loop over the EM particles produced by 'GenerateNeutronCaptureCascade' and add them to the
|
||||
// theParticleChange as secondaries. These particles are produced by NuDEX in the nucleus' rest-frame.
|
||||
for ( G4int i = 0; i < npar; i++ ) {
|
||||
G4ParticleDefinition* particleDef = nullptr;
|
||||
if ( pType.at(i) == 'g' ) {
|
||||
particleDef = G4Gamma::Definition();
|
||||
} else if (pType.at(i) == 'e' ) {
|
||||
particleDef = G4Electron::Definition();
|
||||
} else if ( pType.at(i) == 'p' ) {
|
||||
particleDef = G4Positron::Definition();
|
||||
} else {
|
||||
G4Exception( "G4NUDEXNeutronCaptureModel::ApplyYourself()", "had0707", FatalException, "Unknown particle type" );
|
||||
}
|
||||
G4double phi = G4UniformRand()*twopi;
|
||||
G4double costheta = 2.0*G4UniformRand() - 1.0;
|
||||
G4double sintheta = std::sqrt( 1.0 - costheta*costheta );
|
||||
G4ThreeVector direction( sintheta*std::cos(phi), sintheta*std::sin(phi), costheta );
|
||||
G4double mass = particleDef->GetPDGMass();
|
||||
G4double particle3momMod = std::sqrt( pEnergy.at(i) * ( pEnergy.at(i) + 2.0*mass ) );
|
||||
G4LorentzVector particle4mom( particle3momMod*direction, mass + pEnergy.at(i) ); // In the center-of-mass frame
|
||||
particle4mom.boost( boostFromCMtoLAB ); // Now in the Lab frame
|
||||
G4HadSecondary* secondary = new G4HadSecondary( new G4DynamicParticle( particleDef, particle4mom ) );
|
||||
remainingLab4mom -= particle4mom;
|
||||
// For simplicity, we neglect below the different frames of time (Lab) and pTime (center-of-mass)
|
||||
secondary->SetTime( time + pTime.at(i) );
|
||||
if ( latestEmission < time + pTime.at(i) ) latestEmission = time + pTime.at(i);
|
||||
secondary->SetCreatorModelID( secID );
|
||||
theParticleChange.AddSecondary( *secondary );
|
||||
delete secondary;
|
||||
}
|
||||
// Treat now the residual nucleus (which is neglected by NuDEX)
|
||||
const G4ParticleDefinition* resNuclDef = nullptr;
|
||||
if ( Z == 1 && A == 2 ) resNuclDef = G4Deuteron::Definition();
|
||||
else if ( Z == 1 && A == 3 ) resNuclDef = G4Triton::Definition();
|
||||
else if ( Z == 2 && A == 3 ) resNuclDef = G4He3::Definition();
|
||||
else if ( Z == 2 && A == 4 ) resNuclDef = G4Alpha::Alpha();
|
||||
else resNuclDef = G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon( Z, A, 0.0, noFloat, 0 );
|
||||
if ( resNuclDef ) {
|
||||
// To conserve energy-momentum, remainingLab4mom should be the Lorentz 4-momentum of the residual nucleus.
|
||||
// Imposing the mass 'compoundMass' to the residual nucleus, and trying to conserve the total energy
|
||||
// while keeping as low as possible the violation of the 3-momentum; in the case that the total energy
|
||||
// cannot be conserved, the residual nucleus is produced at rest (in the Lab frame).
|
||||
G4double resNuclLabEkin = std::max( remainingLab4mom.e() - compoundMass, 0.0 );
|
||||
G4double resNuclLab3momMod = 0.0;
|
||||
G4ThreeVector resNuclLabDir( 0.0, 0.0, 0.0 );
|
||||
if ( resNuclLabEkin > 0.0 ) {
|
||||
resNuclLab3momMod = std::sqrt( resNuclLabEkin * ( resNuclLabEkin + 2.0*compoundMass ) );
|
||||
resNuclLabDir = remainingLab4mom.vect().unit();
|
||||
}
|
||||
G4LorentzVector resNuclLab4mom( resNuclLab3momMod*resNuclLabDir, resNuclLabEkin + compoundMass );
|
||||
G4HadSecondary* secondary = new G4HadSecondary( new G4DynamicParticle( resNuclDef, resNuclLab4mom ) );
|
||||
secondary->SetTime( latestEmission );
|
||||
secondary->SetCreatorModelID( secID );
|
||||
theParticleChange.AddSecondary( *secondary );
|
||||
delete secondary;
|
||||
}
|
||||
|
||||
} else { // NuDEX cannot be applied: use G4PhotonEvaporation
|
||||
|
||||
// Code taken from G4NeutronRadCapture
|
||||
|
||||
G4Fragment* aFragment = new G4Fragment( A, Z, lab4mom );
|
||||
G4FragmentVector* fv = photonEvaporation->BreakUpFragment( aFragment );
|
||||
if ( fv == nullptr ) fv = new G4FragmentVector;
|
||||
fv->push_back( aFragment );
|
||||
size_t n = fv->size();
|
||||
for ( size_t i = 0; i < n; ++i ) {
|
||||
G4Fragment* f = (*fv)[i];
|
||||
G4double etot = f->GetMomentum().e();
|
||||
Z = f->GetZ_asInt();
|
||||
A = f->GetA_asInt();
|
||||
const G4ParticleDefinition* theDef = nullptr;
|
||||
if ( Z == 0 && A == 0 ) { theDef = f->GetParticleDefinition(); }
|
||||
else if ( Z == 1 && A == 2 ) { theDef = G4Deuteron::Definition(); }
|
||||
else if ( Z == 1 && A == 3 ) { theDef = G4Triton::Definition(); }
|
||||
else if ( Z == 2 && A == 3 ) { theDef = G4He3::Definition(); }
|
||||
else if ( Z == 2 && A == 4 ) { theDef = G4Alpha::Definition(); }
|
||||
else {
|
||||
G4double eexc = f->GetExcitationEnergy();
|
||||
if ( eexc <= minExcitation ) eexc = 0.0;
|
||||
theDef = G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon( Z, A, eexc, noFloat, 0 );
|
||||
}
|
||||
G4double ekin = std::max( 0.0, etot - theDef->GetPDGMass() );
|
||||
G4HadSecondary* news = new G4HadSecondary( new G4DynamicParticle( theDef, f->GetMomentum().vect().unit(), ekin ) );
|
||||
G4double timeF = f->GetCreationTime();
|
||||
if ( timeF < 0.0 ) timeF = 0.0;
|
||||
news->SetTime( time + timeF );
|
||||
news->SetCreatorModelID( secID );
|
||||
theParticleChange.AddSecondary( *news );
|
||||
delete news;
|
||||
delete f;
|
||||
}
|
||||
delete fv;
|
||||
}
|
||||
|
||||
return &theParticleChange;
|
||||
}
|
||||
|
||||
|
||||
G4int G4NuDEXNeutronCaptureModel::GenerateNeutronCaptureCascade( G4int theZ, G4int theA, G4double NeutronEnergy, G4int InitialLevel,
|
||||
std::vector< char >& pType, std::vector< G4double >& pEnergy,
|
||||
std::vector< G4double >& pTime ) {
|
||||
// Returns the number of emitted particles. Returns -1 if the nucleus is not in the database.
|
||||
G4int theZA = 1000*theZ + theA;
|
||||
G4int check = Init( theZA );
|
||||
if ( check < 0 ) return -1;
|
||||
G4double Sn, I0;
|
||||
theStatisticalNucleus[theZA]->GetSnAndI0( Sn, I0 ); Sn *= MeV; // I0 is the spin of the A-1 nucleus in the g.s.
|
||||
G4double ExcitationEnergy = Sn + (theA-1.0)/(G4double)theA*NeutronEnergy;
|
||||
G4int nPar = theStatisticalNucleus[theZA]->GenerateCascade( InitialLevel, ExcitationEnergy/MeV, pType, pEnergy, pTime );
|
||||
for ( G4int i = 0; i < nPar; i++ ) {
|
||||
pEnergy.at(i) *= MeV;
|
||||
pTime.at(i) *= s;
|
||||
}
|
||||
return nPar;
|
||||
}
|
||||
|
||||
|
||||
G4int G4NuDEXNeutronCaptureModel::Init( G4int theZA, unsigned int seed1, unsigned int seed2, unsigned int seed3 ) {
|
||||
if ( HasData[theZA] == -1 ) return -1;
|
||||
if ( HasData[theZA] == 1 ) return 0;
|
||||
if ( theStatisticalNucleus[theZA] == 0 ) {
|
||||
G4int theZ = theZA/1000;
|
||||
G4int theA = theZA-1000*theZ;
|
||||
theStatisticalNucleus[theZA] = new G4NuDEXStatisticalNucleus( theZ, theA );
|
||||
if ( BandWidth != 0 ) theStatisticalNucleus[theZA]->SetBandWidth( BandWidth );
|
||||
theStatisticalNucleus[theZA]->SetBrOption( BrOption );
|
||||
if ( seed1 > 0 ) theStatisticalNucleus[theZA]->SetRandom1Seed( seed1 );
|
||||
if ( seed2 > 0 ) theStatisticalNucleus[theZA]->SetRandom1Seed( seed2 );
|
||||
if ( seed3 > 0 ) theStatisticalNucleus[theZA]->SetRandom1Seed( seed3 );
|
||||
G4int check = theStatisticalNucleus[theZA]->Init( NuDEXLibDirectory.c_str() );
|
||||
if ( check < 0 ) {
|
||||
HasData[theZA] = -1;
|
||||
return -1;
|
||||
} else {
|
||||
HasData[theZA] = 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4int G4NuDEXNeutronCaptureModel::SelectInitialLevel( G4int theCompoundZ, G4int theCompoundA, G4double NeutronEnergy, G4int lspin, G4int jspinx2 ) {
|
||||
// Initial level for neutron capture. If jspinx2 < 0 it is sampled according to the 2J+1 rule.
|
||||
// l-spin = 0, 1, 2 --> s-wave, p-wave, d-wave ...
|
||||
G4int theZ = theCompoundZ;
|
||||
G4int theA = theCompoundA;
|
||||
G4int theZA = 1000*theZ + theA;
|
||||
G4int check = Init( theZA );
|
||||
if ( check < 0 ) return -1;
|
||||
G4double Sn, I0;
|
||||
theStatisticalNucleus[theZA]->GetSnAndI0( Sn, I0 ); Sn *= MeV; // I0 is the spin of the A-1 nucleus in the g.s.
|
||||
G4double ExcitationEnergy = Sn + (theA-1.0)/(G4double)theA*NeutronEnergy;
|
||||
if ( lspin < 0 ) lspin = 0;
|
||||
if ( jspinx2 < 0 ) jspinx2 = SampleJ( theZ, theA, lspin );
|
||||
G4bool parity = false;
|
||||
if ( ( I0 >= 0 && (lspin%2) == 0 ) || ( I0 < 0 && (lspin%2) == 1 ) ) parity = true;
|
||||
G4int InitialLevel = theStatisticalNucleus[theZA]->GetClosestLevel( ExcitationEnergy/MeV, jspinx2, parity );
|
||||
return InitialLevel;
|
||||
}
|
||||
|
||||
|
||||
G4int G4NuDEXNeutronCaptureModel ::SampleJ( G4int theCompoundZ, G4int theCompoundA, G4int lspin ) {
|
||||
// Samples J for this l-spin (l-spin = 0, 1, 2 --> s-wave, p-wave, d-wave ...)
|
||||
// The probability will be proportional to 2J+1
|
||||
// Returns Jx2
|
||||
G4int AllowedJx2[100];
|
||||
G4int NAllowedJvals = GetAllowedJx2values( theCompoundZ, theCompoundA, lspin, AllowedJx2 );
|
||||
G4double AllowedJx2CumulProb[100], TotalCumul = 0.0;
|
||||
for ( G4int i = 0; i < NAllowedJvals; i++ ) {
|
||||
AllowedJx2CumulProb[i] = AllowedJx2[i] + 1.0;
|
||||
TotalCumul += AllowedJx2CumulProb[i];
|
||||
}
|
||||
for ( G4int i = 0; i < NAllowedJvals; i++ ) {
|
||||
AllowedJx2CumulProb[i] /= TotalCumul;
|
||||
if ( i > 0 ) AllowedJx2CumulProb[i] += AllowedJx2CumulProb[i-1];
|
||||
}
|
||||
G4double rand = G4UniformRand();
|
||||
G4int i_result = -1;
|
||||
for ( G4int i = 0; i < NAllowedJvals; i++ ) {
|
||||
if ( rand < AllowedJx2CumulProb[i] ) {
|
||||
i_result = i; break;
|
||||
}
|
||||
}
|
||||
if ( i_result < 0 ) {
|
||||
G4cerr << " ############ Error in " << __FILE__ << ", line " << __LINE__ << " ############"<< G4endl;
|
||||
exit(1);
|
||||
}
|
||||
G4int jspinx2 = AllowedJx2[i_result];
|
||||
return jspinx2;
|
||||
}
|
||||
|
||||
|
||||
G4int G4NuDEXNeutronCaptureModel::GetAllowedJx2values( G4int theCompoundZ, G4int theCompoundA, G4int lspin, G4int* jx2vals ) {
|
||||
// Provides the allowed jx2 values in neutron capture for a certain l-spin (l-spin = 0, 1, 2 --> s-wave, p-wave, d-wave ...)
|
||||
G4int theZA = 1000*theCompoundZ + theCompoundA;
|
||||
G4int check = Init( theZA );
|
||||
if ( check < 0 ) return -1;
|
||||
G4double Sn, I0;
|
||||
theStatisticalNucleus[theZA]->GetSnAndI0( Sn, I0 ); Sn *= MeV; // I0 is the spin of the A-1 nucleus in the g.s.
|
||||
G4int Ix2 = (G4int)( ( std::fabs(I0) + 0.1 )*2.0 );
|
||||
G4int Jx2min = std::min( std::abs( Ix2-1-2*lspin ), std::abs( Ix2+1-2*lspin ) );
|
||||
G4int Jx2max = Ix2 + 1 + 2*lspin;
|
||||
G4int NAllowedJvals = 0;
|
||||
for ( G4int Jx2 = Jx2min; Jx2 <= Jx2max; Jx2 += 2 ) {
|
||||
if ( Jx2 >= 0 ) {
|
||||
jx2vals[NAllowedJvals] = Jx2;
|
||||
NAllowedJvals++;
|
||||
}
|
||||
}
|
||||
return NAllowedJvals;
|
||||
}
|
||||
@@ -0,0 +1,942 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// Author: E.Mendoza
|
||||
//
|
||||
// Creation date: May 2024
|
||||
//
|
||||
// Modifications:
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// NuDEX code (https://doi.org/10.1016/j.nima.2022.167894)
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include "G4NuDEXRandom.hh"
|
||||
#include "G4NuDEXLevelDensity.hh"
|
||||
#include "G4NuDEXPSF.hh"
|
||||
|
||||
|
||||
G4NuDEXPSF::G4NuDEXPSF(G4int aZ,G4int aA){
|
||||
Z_Int=aZ;
|
||||
A_Int=aA;
|
||||
nR_E1=0; nR_M1=0; nR_E2=0;
|
||||
x_E1=0; y_E1=0;
|
||||
x_M1=0; y_M1=0;
|
||||
x_E2=0; y_E2=0;
|
||||
E1_normFac=-1; M1_normFac=-1; E2_normFac=-1;
|
||||
NormEmin=0; NormEmax=6; //Integral between 0 and 6 MeV
|
||||
ScaleFactor_E1=1;
|
||||
ScaleFactor_M1=1;
|
||||
ScaleFactor_E2=1;
|
||||
}
|
||||
|
||||
G4NuDEXPSF::~G4NuDEXPSF(){
|
||||
if(x_E1!=0){delete [] x_E1;}
|
||||
if(y_E1!=0){delete [] y_E1;}
|
||||
if(x_M1!=0){delete [] x_M1;}
|
||||
if(y_M1!=0){delete [] y_M1;}
|
||||
if(x_E2!=0){delete [] x_E2;}
|
||||
if(y_E2!=0){delete [] y_E2;}
|
||||
}
|
||||
|
||||
|
||||
//If inputfname!=0 then we take the PSF data from the inputfname instead of the dirname
|
||||
G4int G4NuDEXPSF::Init(const char* dirname,G4NuDEXLevelDensity* aLD,const char* inputfname,const char* defaultinputfname,G4int PSFflag){
|
||||
|
||||
theLD=aLD;
|
||||
|
||||
//Three options: very detailed model, if not --> gdr-parameters&errors-exp-MLO.dat (RIPL-3), if not --> theorethical values
|
||||
|
||||
char fname[500];
|
||||
G4bool IsDone=false;
|
||||
|
||||
//input:
|
||||
if(inputfname!=0){
|
||||
IsDone=TakePSFFromInputFile(inputfname);
|
||||
if(IsDone){return 0;}
|
||||
}
|
||||
|
||||
//default input:
|
||||
if(defaultinputfname!=0){
|
||||
IsDone=TakePSFFromInputFile(defaultinputfname);
|
||||
if(IsDone){return 0;}
|
||||
}
|
||||
|
||||
//Detailed model
|
||||
snprintf(fname,500,"%s/PSF/PSF_param.dat",dirname);
|
||||
IsDone=TakePSFFromDetailedParFile(fname);
|
||||
if(IsDone){return 0;}
|
||||
|
||||
//IAEA - 2019 values:
|
||||
if(PSFflag==0){
|
||||
snprintf(fname,500,"%s/PSF/CRP_IAEA_SMLO_E1_v01.dat",dirname);
|
||||
IsDone=TakePSFFromIAEA01(fname);
|
||||
if(IsDone){return 0;}
|
||||
}
|
||||
else if(PSFflag!=1){
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
//RIPL-MLO values:
|
||||
snprintf(fname,500,"%s/PSF/gdr-parameters&errors-exp-MLO.dat",dirname);
|
||||
IsDone=TakePSFFromRIPL01(fname);
|
||||
if(IsDone){return 0;}
|
||||
|
||||
//RIPL-Theorethical values:
|
||||
snprintf(fname,500,"%s/PSF/gdr-parameters-theor.dat",dirname);
|
||||
IsDone=TakePSFFromRIPL02(fname);
|
||||
if(IsDone){return 0;}
|
||||
|
||||
//Theorethical values:
|
||||
// E1 for spherical nucleus:
|
||||
nR_E1=0;
|
||||
PSFType_E1[nR_E1]=2;
|
||||
//G4double a=31.2,b=20.6,c=0.026,d=1.05; //SLO-old (RIPL-2)
|
||||
//G4double a=27.47,b=22.063,c=0.0277,d=1.222;//SLO (RIPL-3)
|
||||
G4double a=28.69,b=21.731,c=0.0285,d=1.267;//MLO (RIPL-3)
|
||||
|
||||
E_E1[nR_E1]=a*std::pow(A_Int,-1./3.)+b*std::pow(A_Int,-1./6.);
|
||||
G_E1[nR_E1]=c*std::pow(E_E1[nR_E1],1.9);
|
||||
s_E1[nR_E1]=120/3.141592*d*(A_Int-Z_Int)*Z_Int/(G4double)A_Int/G_E1[nR_E1];
|
||||
nR_E1++;
|
||||
GenerateM1AndE2FromE1();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void G4NuDEXPSF::GenerateM1AndE2FromE1(){
|
||||
|
||||
//M1:
|
||||
nR_M1=0;
|
||||
E_M1[nR_M1]=41*std::pow(A_Int,-1./3.);
|
||||
G_M1[nR_M1]=4;
|
||||
s_M1[nR_M1]=1;
|
||||
PSFType_M1[nR_M1]=0;
|
||||
nR_M1++;
|
||||
|
||||
//f(E1)/f(M1) = 0.0588*A**0.878 at +-7 MeV
|
||||
G4double fE1=GetE1(7,7);
|
||||
G4double fM1=GetM1(7,7);
|
||||
s_M1[0]=fE1/0.0588/std::pow(A_Int,0.878)/fM1;
|
||||
|
||||
|
||||
//E2:
|
||||
nR_E2=0;
|
||||
E_E2[nR_E2]=63*std::pow(A_Int,-1./3.);
|
||||
G_E2[nR_E2]=6.11-0.021*A_Int;
|
||||
s_E2[nR_E2]=0.00014*Z_Int*Z_Int*E_E2[nR_E2]/std::pow(A_Int,1./3)/G_E2[nR_E2];
|
||||
PSFType_E2[nR_E2]=0;
|
||||
nR_E2++;
|
||||
|
||||
}
|
||||
|
||||
G4bool G4NuDEXPSF::TakePSFFromRIPL02(const char* fname){
|
||||
|
||||
G4bool result=false;
|
||||
G4int aA,aZ;
|
||||
std::ifstream in(fname);
|
||||
char dum[200];
|
||||
|
||||
for(G4int i=0;i<4;i++){in.ignore(10000,'\n');}
|
||||
while(in>>aZ>>aA){
|
||||
if(aZ==Z_Int && aA==A_Int){
|
||||
result=true;
|
||||
in>>dum>>dum;
|
||||
nR_E1=2;
|
||||
in>>E_E1[0]>>G_E1[0]>>E_E1[1]>>G_E1[1];
|
||||
PSFType_E1[0]=2; PSFType_E1[1]=2; //SMLO
|
||||
|
||||
G4double a=28.69,b=21.731,c=0.0285,d=1.267;//MLO
|
||||
G4double E_E1_0=a*std::pow(A_Int,-1./3.)+b*std::pow(A_Int,-1./6.);
|
||||
G4double G_E1_0=c*std::pow(E_E1_0,1.9);
|
||||
G4double s_E1_0=120/3.141592*d*(A_Int-Z_Int)*Z_Int/(G4double)A_Int/G_E1_0;
|
||||
s_E1[0]=s_E1_0/3.;
|
||||
s_E1[1]=2.*s_E1_0/3.;
|
||||
|
||||
break;
|
||||
}
|
||||
in.ignore(10000,'\n');
|
||||
}
|
||||
in.close();
|
||||
if(result){GenerateM1AndE2FromE1();}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
G4bool G4NuDEXPSF::TakePSFFromRIPL01(const char* fname){
|
||||
|
||||
G4bool result=false;
|
||||
G4int aA,aZ;
|
||||
std::ifstream in(fname);
|
||||
char dum[200];
|
||||
|
||||
for(G4int i=0;i<7;i++){in.ignore(10000,'\n');}
|
||||
while(in>>aZ>>aA){
|
||||
if(aZ==Z_Int && aA==A_Int){
|
||||
result=true;
|
||||
in>>dum>>dum;
|
||||
nR_E1=0;
|
||||
in>>E_E1[nR_E1]>>s_E1[nR_E1]>>G_E1[nR_E1];
|
||||
PSFType_E1[nR_E1]=2; //SMLO
|
||||
nR_E1++;
|
||||
//sometimes there is a second resonance:
|
||||
in>>E_E1[nR_E1]>>dum>>G_E1[nR_E1];
|
||||
if(dum[0]!='-'){ //there is a second resonance
|
||||
s_E1[nR_E1]=std::atof(dum);
|
||||
PSFType_E1[nR_E1]=2;
|
||||
nR_E1++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
in.ignore(10000,'\n');
|
||||
}
|
||||
in.close();
|
||||
if(result){GenerateM1AndE2FromE1();}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
G4bool G4NuDEXPSF::TakePSFFromIAEA01(const char* fname){
|
||||
|
||||
G4bool result=false;
|
||||
G4int aA,aZ;
|
||||
char dum[200];
|
||||
G4double beta=0;
|
||||
std::ifstream in(fname);
|
||||
while(in>>aZ>>aA){
|
||||
if(aZ==Z_Int && aA==A_Int){
|
||||
result=true;
|
||||
nR_E1=0;
|
||||
in>>dum>>dum>>E_E1[nR_E1]>>dum>>dum>>G_E1[nR_E1]>>dum>>dum>>s_E1[nR_E1];
|
||||
PSFType_E1[nR_E1]=11;
|
||||
nR_E1++;
|
||||
in>>dum;
|
||||
if(std::string(dum)==std::string("beta=")){
|
||||
in>>beta;
|
||||
break;
|
||||
}
|
||||
else if(std::string(dum)==std::string("Er2")){
|
||||
in>>dum>>E_E1[nR_E1]>>dum>>dum>>G_E1[nR_E1]>>dum>>dum>>s_E1[nR_E1]>>dum>>beta;
|
||||
PSFType_E1[nR_E1]=11;
|
||||
nR_E1++;
|
||||
|
||||
}
|
||||
else{
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
break;
|
||||
}
|
||||
in.ignore(10000,'\n');
|
||||
}
|
||||
if(!result){
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------
|
||||
//Now M1 (https://doi.org/10.1140/epja/i2019-12840-1)
|
||||
nR_M1=0;
|
||||
//Spin-flip:
|
||||
PSFType_M1[nR_M1]=0;
|
||||
E_M1[nR_M1]=18.0*std::pow(A_Int,-1./6.);
|
||||
G_M1[nR_M1]=4;
|
||||
s_M1[nR_M1]=0.03*std::pow(A_Int,5./6.);
|
||||
nR_M1++;
|
||||
//Scissors-mode:
|
||||
PSFType_M1[nR_M1]=0;
|
||||
E_M1[nR_M1]=5.0*std::pow(A_Int,-1./10.);
|
||||
G_M1[nR_M1]=1.5;
|
||||
s_M1[nR_M1]=0.02*std::fabs(beta)*std::pow(A_Int,9./10.);
|
||||
nR_M1++;
|
||||
//upbend:
|
||||
PSFType_M1[nR_M1]=21;
|
||||
E_M1[nR_M1]=0.4035*std::exp(-6.0*std::fabs(beta));
|
||||
G_M1[nR_M1]=0.8;
|
||||
s_M1[nR_M1]=0;
|
||||
nR_M1++;
|
||||
//---------------------------------------------------
|
||||
|
||||
//---------------------------------------------------
|
||||
//E2 same as in the old RIPL recommendations:
|
||||
nR_E2=0;
|
||||
E_E2[nR_E2]=63*std::pow(A_Int,-1./3.);
|
||||
G_E2[nR_E2]=6.11-0.021*A_Int;
|
||||
s_E2[nR_E2]=0.00014*Z_Int*Z_Int*E_E2[nR_E2]/std::pow(A_Int,1./3)/G_E2[nR_E2];
|
||||
PSFType_E2[nR_E2]=0;
|
||||
nR_E2++;
|
||||
//---------------------------------------------------
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
G4bool G4NuDEXPSF::TakePSFFromInputFile(const char* fname){
|
||||
|
||||
G4bool result=false;
|
||||
char word[1000];
|
||||
std::ifstream in(fname);
|
||||
while(in>>word){
|
||||
if(word[0]=='#'){in.ignore(10000,'\n');}
|
||||
if(std::string(word)==std::string("END")){break;}
|
||||
if(std::string(word)==std::string("PSF")){
|
||||
result=true;
|
||||
in>>nR_E1;
|
||||
for(G4int i=0;i<nR_E1;i++){
|
||||
in>>PSFType_E1[i]>>E_E1[i]>>G_E1[i]>>s_E1[i];
|
||||
if(PSFType_E1[i]==7){in>>p1_E1[i];}
|
||||
if(PSFType_E1[i]==8){in>>p1_E1[i]>>p2_E1[i];}
|
||||
if(PSFType_E1[i]==9){in>>p1_E1[i]>>p2_E1[i];}
|
||||
if(PSFType_E1[i]==10){in>>p1_E1[i]>>p2_E1[i]>>p3_E1[i];}
|
||||
if(PSFType_E1[i]==40 || PSFType_E1[i]==41){ //only one pointwise function is allowed
|
||||
if(x_E1!=0){NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");}
|
||||
in>>np_E1;
|
||||
x_E1=new G4double[np_E1]; y_E1=new G4double[np_E1];
|
||||
for(G4int j=0;j<np_E1;j++){in>>x_E1[j]>>y_E1[j];}
|
||||
in>>E1_normFac;
|
||||
}
|
||||
}
|
||||
in>>nR_M1;
|
||||
for(G4int i=0;i<nR_M1;i++){
|
||||
in>>PSFType_M1[i]>>E_M1[i]>>G_M1[i]>>s_M1[i];
|
||||
if(PSFType_M1[i]==7){in>>p1_M1[i];}
|
||||
if(PSFType_M1[i]==8){in>>p1_M1[i]>>p2_M1[i];}
|
||||
if(PSFType_M1[i]==9){in>>p1_M1[i]>>p2_M1[i];}
|
||||
if(PSFType_M1[i]==10){in>>p1_M1[i]>>p2_M1[i]>>p3_M1[i];}
|
||||
if(PSFType_M1[i]==40 || PSFType_M1[i]==41){//only one pointwise function is allowed
|
||||
if(x_M1!=0){NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");}
|
||||
in>>np_M1;
|
||||
x_M1=new G4double[np_M1]; y_M1=new G4double[np_M1];
|
||||
for(G4int j=0;j<np_M1;j++){in>>x_M1[j]>>y_M1[j];}
|
||||
in>>M1_normFac;
|
||||
}
|
||||
}
|
||||
in>>nR_E2;
|
||||
for(G4int i=0;i<nR_E2;i++){
|
||||
in>>PSFType_E2[i]>>E_E2[i]>>G_E2[i]>>s_E2[i];
|
||||
if(PSFType_E2[i]==7){in>>p1_E2[i];}
|
||||
if(PSFType_E2[i]==8){in>>p1_E2[i]>>p2_E2[i];}
|
||||
if(PSFType_E2[i]==9){in>>p1_E2[i]>>p2_E2[i];}
|
||||
if(PSFType_E2[i]==10){in>>p1_E2[i]>>p2_E2[i]>>p3_E2[i];}
|
||||
if(PSFType_E2[i]==40 || PSFType_E2[i]==41){//only one pointwise function is allowed
|
||||
if(x_E2!=0){NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");}
|
||||
in>>np_E2;
|
||||
x_E2=new G4double[np_E2]; y_E2=new G4double[np_E2];
|
||||
for(G4int j=0;j<np_E2;j++){in>>x_E2[j]>>y_E2[j];}
|
||||
in>>E2_normFac;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Renormalize(); // if XX_normFac>0 --> renormalization of the PSF
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void G4NuDEXPSF::Renormalize(){
|
||||
|
||||
G4int npIntegral=1000;
|
||||
G4double Integral=0,x_eval,y_eval;
|
||||
G4double binWidth=(NormEmax-NormEmin)/npIntegral;
|
||||
|
||||
//-------------------------------------------------
|
||||
if(E1_normFac>0){
|
||||
Integral=0;
|
||||
for(G4int i=0;i<npIntegral;i++){
|
||||
x_eval=NormEmin+binWidth*(i+0.5);
|
||||
y_eval=GetE1(x_eval,NormEmax);
|
||||
Integral+=y_eval;
|
||||
}
|
||||
Integral*=binWidth;
|
||||
ScaleFactor_E1=E1_normFac/Integral;
|
||||
}
|
||||
//-------------------------------------------------
|
||||
//-------------------------------------------------
|
||||
if(M1_normFac>0){
|
||||
Integral=0;
|
||||
for(G4int i=0;i<npIntegral;i++){
|
||||
x_eval=NormEmin+binWidth*(i+0.5);
|
||||
y_eval=GetM1(x_eval,NormEmax);
|
||||
Integral+=y_eval;
|
||||
}
|
||||
Integral*=binWidth;
|
||||
ScaleFactor_M1=M1_normFac/Integral;
|
||||
//std::cout<<M1_normFac<<" "<<Integral<<" "<<ScaleFactor_M1<<std::endl; getchar();
|
||||
}
|
||||
//-------------------------------------------------
|
||||
//-------------------------------------------------
|
||||
if(E2_normFac>0){
|
||||
Integral=0;
|
||||
for(G4int i=0;i<npIntegral;i++){
|
||||
x_eval=NormEmin+binWidth*(i+0.5);
|
||||
y_eval=GetE2(x_eval,NormEmax);
|
||||
Integral+=y_eval;
|
||||
}
|
||||
Integral*=binWidth;
|
||||
ScaleFactor_E2=E2_normFac/Integral;
|
||||
}
|
||||
//-------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
G4bool G4NuDEXPSF::TakePSFFromDetailedParFile(const char* fname){
|
||||
|
||||
G4bool result=false;
|
||||
G4int aA,aZ;
|
||||
std::ifstream in(fname);
|
||||
while(in>>aZ>>aA){
|
||||
if(aZ==Z_Int && aA==A_Int){
|
||||
result=true;
|
||||
in>>nR_E1;
|
||||
for(G4int i=0;i<nR_E1;i++){
|
||||
in>>PSFType_E1[i]>>E_E1[i]>>G_E1[i]>>s_E1[i];
|
||||
if(PSFType_E1[i]==7){in>>p1_E1[i];}
|
||||
if(PSFType_E1[i]==8){in>>p1_E1[i]>>p2_E1[i];}
|
||||
if(PSFType_E1[i]==9){in>>p1_E1[i]>>p2_E1[i];}
|
||||
if(PSFType_E1[i]==10){in>>p1_E1[i]>>p2_E1[i]>>p3_E1[i];}
|
||||
}
|
||||
in>>nR_M1;
|
||||
for(G4int i=0;i<nR_M1;i++){
|
||||
in>>PSFType_M1[i]>>E_M1[i]>>G_M1[i]>>s_M1[i];
|
||||
if(PSFType_M1[i]==7){in>>p1_M1[i];}
|
||||
if(PSFType_M1[i]==8){in>>p1_M1[i]>>p2_M1[i];}
|
||||
if(PSFType_M1[i]==9){in>>p1_M1[i]>>p2_M1[i];}
|
||||
if(PSFType_M1[i]==10){in>>p1_M1[i]>>p2_M1[i]>>p3_M1[i];}
|
||||
}
|
||||
in>>nR_E2;
|
||||
for(G4int i=0;i<nR_E2;i++){
|
||||
in>>PSFType_E2[i]>>E_E2[i]>>G_E2[i]>>s_E2[i];
|
||||
if(PSFType_E2[i]==7){in>>p1_E2[i];}
|
||||
if(PSFType_E2[i]==8){in>>p1_E2[i]>>p2_E2[i];}
|
||||
if(PSFType_E2[i]==9){in>>p1_E2[i]>>p2_E2[i];}
|
||||
if(PSFType_E2[i]==10){in>>p1_E2[i]>>p2_E2[i]>>p3_E2[i];}
|
||||
}
|
||||
break;
|
||||
}
|
||||
in.ignore(10000,'\n');
|
||||
}
|
||||
in.close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
G4double G4NuDEXPSF::GetE1(G4double Eg,G4double ExcitationEnergy){
|
||||
|
||||
G4double result=0;
|
||||
for(G4int i=0;i<nR_E1;i++){
|
||||
if(PSFType_E1[i]==0){
|
||||
result+=8.674E-8*SLO(Eg,E_E1[i],G_E1[i],s_E1[i]);
|
||||
}
|
||||
else if(PSFType_E1[i]==1){
|
||||
result+=8.674E-8*EGLO(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E1[i]==2){
|
||||
result+=8.674E-8*SMLO(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E1[i]==3){
|
||||
result+=8.674E-8*GLO(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E1[i]==4){
|
||||
result+=8.674E-8*MGLO(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E1[i]==5){
|
||||
result+=8.674E-8*KMF(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E1[i]==6){
|
||||
result+=8.674E-8*GH(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E1[i]==7){
|
||||
result+=8.674E-8*MEGLO(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy,p1_E1[i],p1_E1[i]);
|
||||
}
|
||||
else if(PSFType_E1[i]==8){
|
||||
result+=8.674E-8*MEGLO(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy,p1_E1[i],p2_E1[i]);
|
||||
}
|
||||
else if(PSFType_E1[i]==9){
|
||||
result+=8.674E-8*MEGLO(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy,p1_E1[i],p1_E1[i],p2_E1[i]);
|
||||
}
|
||||
else if(PSFType_E1[i]==10){
|
||||
result+=8.674E-8*MEGLO(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy,p1_E1[i],p2_E1[i],p3_E1[i]);
|
||||
}
|
||||
else if(PSFType_E1[i]==11){
|
||||
result+=8.674E-8*SMLO_v2(Eg,E_E1[i],G_E1[i],s_E1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E1[i]==20){
|
||||
result+=8.674E-8*Gauss(Eg,E_E1[i],G_E1[i],s_E1[i]);
|
||||
}
|
||||
else if(PSFType_E1[i]==21){
|
||||
result+=8.674E-8*Expo(Eg,E_E1[i],G_E1[i]);
|
||||
}
|
||||
else if(PSFType_E1[i]==40){
|
||||
result+=EvaluateFunction(Eg,np_E1,x_E1,y_E1);
|
||||
}
|
||||
else if(PSFType_E1[i]==41){
|
||||
result+=std::pow(10.,EvaluateFunction(Eg,np_E1,x_E1,y_E1));
|
||||
}
|
||||
else{
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
}
|
||||
|
||||
if(result!=result){ // nan
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
return result*ScaleFactor_E1;
|
||||
}
|
||||
|
||||
G4double G4NuDEXPSF::GetM1(G4double Eg,G4double ExcitationEnergy){
|
||||
|
||||
G4double result=0;
|
||||
for(G4int i=0;i<nR_M1;i++){
|
||||
if(PSFType_M1[i]==0){
|
||||
result+=8.674E-8*SLO(Eg,E_M1[i],G_M1[i],s_M1[i]);
|
||||
}
|
||||
else if(PSFType_M1[i]==1){
|
||||
result+=8.674E-8*EGLO(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_M1[i]==2){
|
||||
result+=8.674E-8*SMLO(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_M1[i]==3){
|
||||
result+=8.674E-8*GLO(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_M1[i]==4){
|
||||
result+=8.674E-8*MGLO(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_M1[i]==5){
|
||||
result+=8.674E-8*KMF(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_M1[i]==6){
|
||||
result+=8.674E-8*GH(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_M1[i]==7){
|
||||
result+=8.674E-8*MEGLO(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy,p1_M1[i],p1_M1[i]);
|
||||
}
|
||||
else if(PSFType_M1[i]==8){
|
||||
result+=8.674E-8*MEGLO(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy,p1_M1[i],p2_M1[i]);
|
||||
}
|
||||
else if(PSFType_M1[i]==9){
|
||||
result+=8.674E-8*MEGLO(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy,p1_M1[i],p1_M1[i],p2_M1[i]);
|
||||
}
|
||||
else if(PSFType_M1[i]==10){
|
||||
result+=8.674E-8*MEGLO(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy,p1_M1[i],p2_M1[i],p3_M1[i]);
|
||||
}
|
||||
else if(PSFType_M1[i]==11){
|
||||
result+=8.674E-8*SMLO_v2(Eg,E_M1[i],G_M1[i],s_M1[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_M1[i]==20){
|
||||
result+=8.674E-8*Gauss(Eg,E_M1[i],G_M1[i],s_M1[i]);
|
||||
}
|
||||
else if(PSFType_M1[i]==21){
|
||||
result+=8.674E-8*Expo(Eg,E_M1[i],G_M1[i]);
|
||||
}
|
||||
else if(PSFType_M1[i]==40){
|
||||
result+=EvaluateFunction(Eg,np_M1,x_M1,y_M1);
|
||||
}
|
||||
else if(PSFType_M1[i]==41){
|
||||
result+=std::pow(10.,EvaluateFunction(Eg,np_M1,x_M1,y_M1));
|
||||
}
|
||||
else{
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
}
|
||||
|
||||
if(result!=result){ // nan
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
return result*ScaleFactor_M1;
|
||||
}
|
||||
|
||||
G4double G4NuDEXPSF::GetE2(G4double Eg,G4double ExcitationEnergy){
|
||||
|
||||
G4double result=0;
|
||||
for(G4int i=0;i<nR_E2;i++){
|
||||
if(PSFType_E2[i]==0){
|
||||
result+=5.22E-8*SLO(Eg,E_E2[i],G_E2[i],s_E2[i]);
|
||||
}
|
||||
else if(PSFType_E2[i]==1){
|
||||
result+=5.22E-8*EGLO(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E2[i]==2){
|
||||
result+=5.22E-8*SMLO(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E2[i]==3){
|
||||
result+=5.22E-8*GLO(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E2[i]==4){
|
||||
result+=5.22E-8*MGLO(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E2[i]==5){
|
||||
result+=5.22E-8*KMF(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E2[i]==6){
|
||||
result+=5.22E-8*GH(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E2[i]==7){
|
||||
result+=5.22E-8*MEGLO(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy,p1_E2[i],p1_E2[i]);
|
||||
}
|
||||
else if(PSFType_E2[i]==8){
|
||||
result+=5.22E-8*MEGLO(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy,p1_E2[i],p2_E2[i]);
|
||||
}
|
||||
else if(PSFType_E2[i]==9){
|
||||
result+=5.22E-8*MEGLO(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy,p1_E2[i],p1_E2[i],p2_E2[i]);
|
||||
}
|
||||
else if(PSFType_E2[i]==10){
|
||||
result+=5.22E-8*MEGLO(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy,p1_E2[i],p2_E2[i],p3_E2[i]);
|
||||
}
|
||||
else if(PSFType_E2[i]==11){
|
||||
result+=5.22E-8*SMLO_v2(Eg,E_E2[i],G_E2[i],s_E2[i],ExcitationEnergy);
|
||||
}
|
||||
else if(PSFType_E2[i]==20){
|
||||
result+=5.22E-8*Gauss(Eg,E_E2[i],G_E2[i],s_E2[i]);
|
||||
}
|
||||
else if(PSFType_E2[i]==21){
|
||||
result+=5.22E-8*Expo(Eg,E_E2[i],G_E2[i]);
|
||||
}
|
||||
else if(PSFType_E2[i]==40){
|
||||
result+=EvaluateFunction(Eg,np_E2,x_E2,y_E2);
|
||||
}
|
||||
else if(PSFType_E2[i]==41){
|
||||
result+=std::pow(10.,EvaluateFunction(Eg,np_E2,x_E2,y_E2));
|
||||
}
|
||||
else{
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
}
|
||||
|
||||
if(result!=result){ // nan
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
return result*ScaleFactor_E2;
|
||||
}
|
||||
|
||||
|
||||
//**********************************************************************************************************
|
||||
//**********************************************************************************************************
|
||||
//**********************************************************************************************************
|
||||
|
||||
//Defined as in RIPL-3 when possible. Some of them come from other references:
|
||||
//http://dx.doi.org/10.1103/PhysRevC.88.034317
|
||||
|
||||
G4double G4NuDEXPSF::SLO(G4double Eg,G4double Er,G4double Gr,G4double sr){
|
||||
|
||||
return sr*Gr*Eg*Gr/((Eg*Eg-Er*Er)*(Eg*Eg-Er*Er)+Eg*Eg*Gr*Gr);
|
||||
|
||||
}
|
||||
|
||||
//Kadmenskij-Markushev-Furman model (KMF) --> not well described in RIPL-3 manual, taken from another document
|
||||
G4double G4NuDEXPSF::KMF(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double ExcitationEnergy){
|
||||
|
||||
G4double Tf=0;
|
||||
if(theLD!=0){
|
||||
Tf=theLD->GetNucleusTemperature(ExcitationEnergy-Eg);
|
||||
}
|
||||
G4double Gc=Gr/Er/Er*(Eg*Eg+4*3.141592*3.141592*Tf*Tf);
|
||||
|
||||
if(Eg==Er){return 0;}
|
||||
|
||||
return 0.7*Er*Gr*sr*Gc/((Eg*Eg-Er*Er)*(Eg*Eg-Er*Er));
|
||||
}
|
||||
|
||||
|
||||
G4double G4NuDEXPSF::EGLO(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double ExcitationEnergy){
|
||||
|
||||
G4double result=EGLO_GLO_MGLO(Eg,Er,Gr,sr,ExcitationEnergy,0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
G4double G4NuDEXPSF::GLO(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double ExcitationEnergy){
|
||||
|
||||
G4double result=EGLO_GLO_MGLO(Eg,Er,Gr,sr,ExcitationEnergy,1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
G4double G4NuDEXPSF::MGLO(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double ExcitationEnergy){
|
||||
|
||||
G4double result=EGLO_GLO_MGLO(Eg,Er,Gr,sr,ExcitationEnergy,2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//Hybrid model
|
||||
G4double G4NuDEXPSF::GH(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double ExcitationEnergy){
|
||||
|
||||
G4double Tf=0;
|
||||
if(theLD!=0){
|
||||
Tf=theLD->GetNucleusTemperature(ExcitationEnergy-Eg);
|
||||
}
|
||||
|
||||
G4double Gamma_h=0.63*Gr/Eg/Er*(Eg*Eg+4*3.141592*3.141592*Tf*Tf);
|
||||
|
||||
return sr*Gr*Eg*Gamma_h/((Eg*Eg-Er*Er)*(Eg*Eg-Er*Er)+Eg*Eg*Gr*Gamma_h);
|
||||
|
||||
}
|
||||
|
||||
G4double G4NuDEXPSF::SMLO(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double ExcitationEnergy){
|
||||
|
||||
G4double Tf=0;
|
||||
if(theLD!=0){
|
||||
Tf=theLD->GetNucleusTemperature(ExcitationEnergy-Eg);
|
||||
}
|
||||
|
||||
G4double Lambda=1/(1.-std::exp(-Eg/Tf));
|
||||
G4double Gk_Eg=Gr/Er*ExcitationEnergy;
|
||||
|
||||
return Lambda*sr*Gr*Eg*Gk_Eg/((Eg*Eg-Er*Er)*(Eg*Eg-Er*Er)+Eg*Eg*Gk_Eg*Gk_Eg);
|
||||
}
|
||||
|
||||
|
||||
G4double G4NuDEXPSF::SMLO_v2(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double ExcitationEnergy){
|
||||
|
||||
G4double Tf=0;
|
||||
if(Eg<ExcitationEnergy){
|
||||
Tf=std::sqrt((ExcitationEnergy-Eg)/(A_Int/10.));
|
||||
}
|
||||
|
||||
G4double Lambda=1/(1.-std::exp(-Eg/Tf));
|
||||
G4double sig_trk=60.*(A_Int-Z_Int)*Z_Int/(G4double)A_Int;
|
||||
G4double Gk_Eg=Gr/Er*(Eg+4*3.141592*3.141592*Tf*Tf/Er);
|
||||
|
||||
return Lambda*sig_trk*2./3.141592*sr*Eg*Gk_Eg/((Eg*Eg-Er*Er)*(Eg*Eg-Er*Er)+Eg*Eg*Gk_Eg*Gk_Eg);
|
||||
}
|
||||
|
||||
|
||||
G4double G4NuDEXPSF::Gauss(G4double Eg,G4double Er,G4double sigma,G4double Area){
|
||||
|
||||
return Area*(1./(sigma*std::sqrt(2.*3.141592)))*std::exp(-0.5*std::pow((Eg-Er)/sigma,2.));
|
||||
|
||||
}
|
||||
|
||||
G4double G4NuDEXPSF::Expo(G4double Eg,G4double C,G4double eta){
|
||||
|
||||
return C*std::exp(-eta*Eg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
G4double G4NuDEXPSF::MEGLO(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double ExcitationEnergy,G4double k_param1,G4double k_param2,G4double Temp){
|
||||
|
||||
G4double /*Ti=0,*/Tf=0;
|
||||
if(Temp>=0){
|
||||
//Ti=Temp;
|
||||
Tf=Temp;
|
||||
}
|
||||
else if(theLD!=0){
|
||||
//Ti=theLD->GetNucleusTemperature(ExcitationEnergy);
|
||||
Tf=theLD->GetNucleusTemperature(ExcitationEnergy-Eg);
|
||||
}
|
||||
|
||||
G4double Gk_Eg=Gamma_k(Eg,Er,Gr,Tf,k_param1);
|
||||
//G4double Gk_0=Gamma_k(0,Er,Gr,Ti,k_param2);
|
||||
G4double Gk_0=Gamma_k(0,Er,Gr,Tf,k_param2); // in most of the references they use just one temperature
|
||||
|
||||
return sr*Gr*(Eg*Gk_Eg/((Eg*Eg-Er*Er)*(Eg*Eg-Er*Er)+Eg*Eg*Gk_Eg*Gk_Eg)+0.7*Gk_0/Er/Er/Er);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Ti, Tf --> initial/final temperature of the nucleus
|
||||
//Opt = 0,1,2 --> EGLO, GLO, MGLO
|
||||
G4double G4NuDEXPSF::EGLO_GLO_MGLO(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double ExcitationEnergy,G4int Opt){
|
||||
|
||||
G4double Ti=0,Tf=0;
|
||||
if(theLD!=0){
|
||||
Ti=theLD->GetNucleusTemperature(ExcitationEnergy);
|
||||
Tf=theLD->GetNucleusTemperature(ExcitationEnergy-Eg);
|
||||
}
|
||||
|
||||
//k_param could be modified according to experimental data.
|
||||
//The following expression is just a general recomendation
|
||||
//If k_param==1 --> GLO
|
||||
G4double k_param=1;
|
||||
if(A_Int>=148){
|
||||
k_param=1+0.09*(A_Int-148)*(A_Int-148)*std::exp(-0.18*(A_Int-148));
|
||||
}
|
||||
G4double result=0;
|
||||
if(Opt==0){//EGLO
|
||||
result=FlexibleGLOType(Eg,Er,Gr,sr,Tf,k_param,Ti,k_param);
|
||||
}
|
||||
else if(Opt==1){//GLO --> same as EGLO, but k_param=1
|
||||
result=FlexibleGLOType(Eg,Er,Gr,sr,Tf,1,Ti,1);
|
||||
}
|
||||
else if(Opt==2){//MGLO --> same as EGLO, but k_param2=1
|
||||
result=FlexibleGLOType(Eg,Er,Gr,sr,Tf,k_param,Ti,1);
|
||||
}
|
||||
else{
|
||||
NuDEXException(__FILE__,std::to_string(__LINE__).c_str(),"##### Error in NuDEX #####");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
G4double G4NuDEXPSF::FlexibleGLOType(G4double Eg,G4double Er,G4double Gr,G4double sr,G4double Temp1,G4double k_param1,G4double /*Temp2*/,G4double k_param2){
|
||||
|
||||
G4double Gk_Eg=Gamma_k(Eg,Er,Gr,Temp1,k_param1);
|
||||
//G4double Gk_0=Gamma_k(0,Er,Gr,Temp2,k_param2);
|
||||
G4double Gk_0=Gamma_k(0,Er,Gr,Temp1,k_param2); // in most of the references they use just one temperature
|
||||
|
||||
return sr*Gr*(Eg*Gk_Eg/((Eg*Eg-Er*Er)*(Eg*Eg-Er*Er)+Eg*Eg*Gk_Eg*Gk_Eg)+0.7*Gk_0/Er/Er/Er);
|
||||
|
||||
}
|
||||
|
||||
|
||||
G4double G4NuDEXPSF::Gamma_k(G4double Eg,G4double Er,G4double Gr,G4double Temp,G4double k_param){
|
||||
|
||||
G4double eps0_param=4.5;
|
||||
G4double Chi=1;
|
||||
if(Er>eps0_param){
|
||||
Chi=k_param+(1-k_param)*(Eg-eps0_param)/(Er-eps0_param);
|
||||
}
|
||||
G4double C_coll=Gr/Er/Er*Chi;
|
||||
G4double Gamma_k=C_coll*(Eg*Eg+4*3.141592*3.141592*Temp*Temp);
|
||||
|
||||
return Gamma_k;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//**********************************************************************************************************
|
||||
//**********************************************************************************************************
|
||||
//**********************************************************************************************************
|
||||
|
||||
|
||||
|
||||
void G4NuDEXPSF::PrintPSFParameters(std::ostream &out){
|
||||
|
||||
out<<" ###################################################################################### "<<std::endl;
|
||||
out<<" PSF_PARAMS"<<std::endl;
|
||||
out<<" E1: nRes = "<<nR_E1<<std::endl;
|
||||
for(G4int i=0;i<nR_E1;i++){
|
||||
out<<" "<<PSFType_E1[i]<<" "<<E_E1[i]<<" "<<G_E1[i]<<" "<<s_E1[i]<<std::endl;
|
||||
if(PSFType_E1[i]==7){out<<" "<<p1_E1[i]<<std::endl;}
|
||||
if(PSFType_E1[i]==8){out<<" "<<p1_E1[i]<<" "<<p2_E1[i]<<std::endl;}
|
||||
if(PSFType_E1[i]==9){out<<" "<<p1_E1[i]<<" "<<p2_E1[i]<<std::endl;}
|
||||
if(PSFType_E1[i]==10){out<<" "<<p1_E1[i]<<" "<<p2_E1[i]<<" "<<p3_E1[i]<<std::endl;}
|
||||
if(PSFType_E1[i]==40 || PSFType_E1[i]==41){out<<np_E1; for(G4int j=0;j<np_E1;j++){out<<" "<<x_E1[j]<<" "<<y_E1[j];} out<<std::endl;}
|
||||
}
|
||||
out<<" M1: nRes = "<<nR_M1<<std::endl;
|
||||
for(G4int i=0;i<nR_M1;i++){
|
||||
out<<" "<<PSFType_M1[i]<<" "<<E_M1[i]<<" "<<G_M1[i]<<" "<<s_M1[i]<<std::endl;
|
||||
if(PSFType_M1[i]==7){out<<" "<<p1_M1[i]<<std::endl;}
|
||||
if(PSFType_M1[i]==8){out<<" "<<p1_M1[i]<<" "<<p2_M1[i]<<std::endl;}
|
||||
if(PSFType_M1[i]==9){out<<" "<<p1_M1[i]<<" "<<p2_M1[i]<<std::endl;}
|
||||
if(PSFType_M1[i]==10){out<<" "<<p1_M1[i]<<" "<<p2_M1[i]<<" "<<p3_M1[i]<<std::endl;}
|
||||
if(PSFType_M1[i]==40 || PSFType_M1[i]==41){out<<np_M1; for(G4int j=0;j<np_M1;j++){out<<" "<<x_M1[j]<<" "<<y_M1[j];} out<<std::endl;}
|
||||
}
|
||||
out<<" E2: nRes = "<<nR_E2<<std::endl;
|
||||
for(G4int i=0;i<nR_E2;i++){
|
||||
out<<" "<<PSFType_E2[i]<<" "<<E_E2[i]<<" "<<G_E2[i]<<" "<<s_E2[i]<<std::endl;
|
||||
if(PSFType_E2[i]==7){out<<" "<<p1_E2[i]<<std::endl;}
|
||||
if(PSFType_E2[i]==8){out<<" "<<p1_E2[i]<<" "<<p2_E2[i]<<std::endl;}
|
||||
if(PSFType_E2[i]==9){out<<" "<<p1_E2[i]<<" "<<p2_E2[i]<<std::endl;}
|
||||
if(PSFType_E2[i]==10){out<<" "<<p1_E2[i]<<" "<<p2_E2[i]<<" "<<p3_E2[i]<<std::endl;}
|
||||
if(PSFType_E2[i]==40 || PSFType_E2[i]==41){out<<np_E2; for(G4int j=0;j<np_E2;j++){out<<" "<<x_E2[j]<<" "<<y_E2[j];} out<<std::endl;}
|
||||
}
|
||||
out<<" ###################################################################################### "<<std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void G4NuDEXPSF::PrintPSFParametersInInputFileFormat(std::ostream &out){
|
||||
|
||||
out<<" PSF"<<std::endl;
|
||||
out.precision(15);
|
||||
out<<nR_E1<<std::endl;
|
||||
for(G4int i=0;i<nR_E1;i++){
|
||||
out<<" "<<PSFType_E1[i]<<" "<<E_E1[i]<<" "<<G_E1[i]<<" "<<s_E1[i];
|
||||
if(PSFType_E1[i]==7){out<<" "<<p1_E1[i];}
|
||||
if(PSFType_E1[i]==8){out<<" "<<p1_E1[i]<<" "<<p2_E1[i];}
|
||||
if(PSFType_E1[i]==9){out<<" "<<p1_E1[i]<<" "<<p2_E1[i];}
|
||||
if(PSFType_E1[i]==10){out<<" "<<p1_E1[i]<<" "<<p2_E1[i]<<" "<<p3_E1[i];}
|
||||
if(PSFType_E1[i]==40 || PSFType_E1[i]==41){out<<np_E1; for(G4int j=0;j<np_E1;j++){out<<" "<<x_E1[j]<<" "<<y_E1[j];} }
|
||||
out<<std::endl;
|
||||
}
|
||||
out<<nR_M1<<std::endl;
|
||||
for(G4int i=0;i<nR_M1;i++){
|
||||
out<<" "<<PSFType_M1[i]<<" "<<E_M1[i]<<" "<<G_M1[i]<<" "<<s_M1[i];
|
||||
if(PSFType_M1[i]==7){out<<" "<<p1_M1[i];}
|
||||
if(PSFType_M1[i]==8){out<<" "<<p1_M1[i]<<" "<<p2_M1[i];}
|
||||
if(PSFType_M1[i]==9){out<<" "<<p1_M1[i]<<" "<<p2_M1[i];}
|
||||
if(PSFType_M1[i]==10){out<<" "<<p1_M1[i]<<" "<<p2_M1[i]<<" "<<p3_M1[i];}
|
||||
if(PSFType_M1[i]==40 || PSFType_M1[i]==41){out<<np_M1; for(G4int j=0;j<np_M1;j++){out<<" "<<x_M1[j]<<" "<<y_M1[j];}}
|
||||
out<<std::endl;
|
||||
}
|
||||
out<<nR_E2<<std::endl;
|
||||
for(G4int i=0;i<nR_E2;i++){
|
||||
out<<" "<<PSFType_E2[i]<<" "<<E_E2[i]<<" "<<G_E2[i]<<" "<<s_E2[i];
|
||||
if(PSFType_E2[i]==7){out<<" "<<p1_E2[i];}
|
||||
if(PSFType_E2[i]==8){out<<" "<<p1_E2[i]<<" "<<p2_E2[i];}
|
||||
if(PSFType_E2[i]==9){out<<" "<<p1_E2[i]<<" "<<p2_E2[i];}
|
||||
if(PSFType_E2[i]==10){out<<" "<<p1_E2[i]<<" "<<p2_E2[i]<<" "<<p3_E2[i];}
|
||||
if(PSFType_E2[i]==40 || PSFType_E2[i]==41){out<<np_E2; for(G4int j=0;j<np_E2;j++){out<<" "<<x_E2[j]<<" "<<y_E2[j];}}
|
||||
out<<std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
G4double G4NuDEXPSF::EvaluateFunction(G4double xval,G4int np,G4double* x,G4double* y){
|
||||
|
||||
if(xval<x[0]){return y[0];}
|
||||
if(xval>x[np-1]){return y[np-1];}
|
||||
|
||||
G4double m,b;
|
||||
G4int i_eval=np-1;
|
||||
for(G4int i=1;i<np;i++){
|
||||
if(x[i]>=xval){
|
||||
i_eval=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m=(y[i_eval]-y[i_eval-1])/(x[i_eval]-x[i_eval-1]);
|
||||
b=y[i_eval]-m*x[i_eval];
|
||||
|
||||
return m*xval+b;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// Author: E.Mendoza
|
||||
//
|
||||
// Creation date: May 2024
|
||||
//
|
||||
// Modifications:
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// NuDEX code (https://doi.org/10.1016/j.nima.2022.167894)
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include "G4NuDEXRandom.hh"
|
||||
|
||||
#if COMPILATIONTYPE == 1
|
||||
//==============================================================================
|
||||
G4NuDEXRandom::G4NuDEXRandom(unsigned int seed){
|
||||
theRandom=new TRandom2(seed);
|
||||
}
|
||||
G4NuDEXRandom::~G4NuDEXRandom(){
|
||||
delete theRandom;
|
||||
}
|
||||
void G4NuDEXRandom::SetSeed(unsigned int seed){
|
||||
theRandom->SetSeed(seed);
|
||||
}
|
||||
unsigned int G4NuDEXRandom::GetSeed(){
|
||||
return theRandom->GetSeed();
|
||||
}
|
||||
G4double G4NuDEXRandom::Uniform(G4double Xmin,G4double Xmax){
|
||||
return theRandom->Uniform(Xmin,Xmax);
|
||||
}
|
||||
unsigned int G4NuDEXRandom::Integer(unsigned int IntegerMax){
|
||||
return theRandom->Integer(IntegerMax);
|
||||
}
|
||||
G4double G4NuDEXRandom::Exp(G4double tau){
|
||||
return theRandom->Exp(tau);
|
||||
}
|
||||
G4double G4NuDEXRandom::Gaus(G4double mean,G4double sigma){
|
||||
return theRandom->Gaus(mean,sigma);
|
||||
}
|
||||
G4int G4NuDEXRandom::Poisson(G4double mean){
|
||||
return theRandom->Poisson(mean);
|
||||
}
|
||||
//==============================================================================
|
||||
void NuDEXException(const char* originOfException, const char* exceptionCode,const char* ){
|
||||
std::cout<<" ############## Error in "<<originOfException<<", line "<<exceptionCode<<" ##############"<<std::endl; exit(1);
|
||||
}
|
||||
//==============================================================================
|
||||
|
||||
#elif COMPILATIONTYPE == 2
|
||||
//==============================================================================
|
||||
G4NuDEXRandom::G4NuDEXRandom(unsigned int seed){
|
||||
theEngine=new CLHEP::HepJamesRandom(seed);
|
||||
theRandFlat=new CLHEP::RandFlat(theEngine);
|
||||
theRandExponential=new CLHEP::RandExponential(theEngine);
|
||||
theRandGauss=new CLHEP::RandGauss(theEngine);
|
||||
theRandPoisson=new CLHEP::RandPoisson(theEngine);
|
||||
}
|
||||
G4NuDEXRandom::~G4NuDEXRandom(){
|
||||
|
||||
//delete theRandFlat;
|
||||
//delete theRandExponential;
|
||||
//delete theRandGauss;
|
||||
//delete theRandPoisson;
|
||||
//delete theEngine;
|
||||
|
||||
}
|
||||
void G4NuDEXRandom::SetSeed(unsigned int seed){
|
||||
theEngine->setSeed(seed);
|
||||
theRandGauss->setF(false);
|
||||
}
|
||||
unsigned int G4NuDEXRandom::GetSeed(){
|
||||
return (unsigned int)theEngine->getSeed();
|
||||
}
|
||||
G4double G4NuDEXRandom::Uniform(G4double Xmin,G4double Xmax){
|
||||
return theRandFlat->fire(Xmin,Xmax);
|
||||
}
|
||||
unsigned int G4NuDEXRandom::Integer(unsigned int IntegerMax){
|
||||
return (unsigned int)theRandFlat->fireInt(IntegerMax); //bikerful!!!
|
||||
}
|
||||
G4double G4NuDEXRandom::Exp(G4double tau){
|
||||
return theRandExponential->fire(tau);
|
||||
}
|
||||
G4double G4NuDEXRandom::Gaus(G4double mean,G4double sigma){
|
||||
return theRandGauss->fire(mean,sigma);
|
||||
}
|
||||
G4long G4NuDEXRandom::Poisson(G4double mean){
|
||||
return theRandPoisson->fire(mean);
|
||||
}
|
||||
//==============================================================================
|
||||
void NuDEXException(const char* originOfException, const char* exceptionCode,const char* description){
|
||||
G4Exception(originOfException,exceptionCode,FatalException,description);
|
||||
}
|
||||
//==============================================================================
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user