Import Geant4 11.2.0 source tree

This commit is contained in:
Gabriele Cosmo
2023-12-08 10:43:34 +01:00
parent dd1f179cda
commit 860a2b92bf
3962 changed files with 139318 additions and 164259 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,817 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// 081120 Add Update by T. Koi
//
// 230307 Skyrme-QMD parameters added by Y-H. Sato and A. Haga
// 230307 "CalDensityProfile" and "CalChargeDensityProfile" functions added by Y-H. Sato and A. Haga
// 230307 "GetSingleEnergy" and "GetTotalEnergy" functions added by Y-H. Sato and A. Haga
#include <map>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <CLHEP/Random/Stat.h>
#include "G4LightIonQMDMeanField.hh"
#include "G4LightIonQMDParameters.hh"
#include "G4Exp.hh"
#include "G4Pow.hh"
#include "G4PhysicalConstants.hh"
#include "Randomize.hh"
G4LightIonQMDMeanField::G4LightIonQMDMeanField()
{
G4LightIonQMDParameters* parameters = G4LightIonQMDParameters::GetInstance();
wl = parameters->Get_wl();
cl = parameters->Get_cl();
rho0 = parameters->Get_rho0();
hbc = parameters->Get_hbc();
gamm = parameters->Get_gamm();
eta = parameters->Get_eta(); // Skyrme-QMD
kappas = parameters->Get_kappas(); // Skyrme-QMD
cpw = parameters->Get_cpw();
cph = parameters->Get_cph();
cpc = parameters->Get_cpc();
c0 = parameters->Get_c0();
c3 = parameters->Get_c3();
cs = parameters->Get_cs();
g0 = parameters->Get_g0(); // Skyrme-QMD
g0iso = parameters->Get_g0iso(); // Skyrme-QMD
gtau0 = parameters->Get_gtau0(); // Skyrme-QMD
// distance
c0w = 1.0/4.0/wl;
c0sw = std::sqrt( c0w );
clw = 2.0 / std::sqrt ( 4.0 * pi * wl );
// graduate
c0g = - c0 / ( 2.0 * wl );
c3g = - c3 / ( 4.0 * wl ) * gamm;
csg = - cs / ( 2.0 * wl );
pag = gamm - 1;
pag_tau = eta - 1; // Skyrme-QMD
cg0 = - g0 / ( 2.0 * wl ); // Skyrme-QMD
cgtau0 = - gtau0 / ( 4.0 * wl ) * eta; // Skyrme-QMD
system = nullptr; // will be set through SetSystem method
}
void G4LightIonQMDMeanField::SetSystem ( G4QMDSystem* aSystem )
{
system = aSystem;
G4int n = system->GetTotalNumberOfParticipant();
pp2.clear();
rr2.clear();
rbij.clear();
rha.clear();
rhe.clear();
rhc.clear();
rr2.resize( n );
pp2.resize( n );
rbij.resize( n );
rha.resize( n );
rhe.resize( n );
rhc.resize( n );
for ( G4int i = 0 ; i < n ; ++i )
{
rr2[i].resize( n );
pp2[i].resize( n );
rbij[i].resize( n );
rha[i].resize( n );
rhe[i].resize( n );
rhc[i].resize( n );
}
ffr.clear();
ffp.clear();
rh3d.clear();
rh3d_tau.clear(); // Skyrme-QMD
ffr.resize( n );
ffp.resize( n );
rh3d.resize( n );
rh3d_tau.resize( n ); // Skyrme-QMD
Cal2BodyQuantities();
}
void G4LightIonQMDMeanField::SetNucleus ( G4LightIonQMDNucleus* aNucleus )
{
SetSystem( aNucleus );
G4double totalPotential = GetTotalPotential();
aNucleus->SetTotalPotential( totalPotential );
aNucleus->CalEnergyAndAngularMomentumInCM();
}
void G4LightIonQMDMeanField::Cal2BodyQuantities()
{
if ( system->GetTotalNumberOfParticipant() < 2 ) { return; }
for ( G4int j = 1 ; j < system->GetTotalNumberOfParticipant() ; ++j )
{
G4ThreeVector rj = system->GetParticipant( j )->GetPosition();
G4LorentzVector p4j = system->GetParticipant( j )->Get4Momentum();
for ( G4int i = 0 ; i < j ; ++i )
{
G4ThreeVector ri = system->GetParticipant( i )->GetPosition();
G4LorentzVector p4i = system->GetParticipant( i )->Get4Momentum();
G4ThreeVector rij = ri - rj;
G4ThreeVector pij = (p4i - p4j).v();
G4LorentzVector p4ij = p4i - p4j;
G4ThreeVector bij = ( p4i + p4j ).boostVector();
G4double gammaij = ( p4i + p4j ).gamma();
G4double eij = ( p4i + p4j ).e();
G4double rbrb = rij*bij;
G4double rij2 = rij*rij;
G4double pij2 = pij*pij;
rbrb = irelcr * rbrb;
G4double gamma2_ij = gammaij*gammaij;
rr2[i][j] = rij2 + gamma2_ij * rbrb*rbrb;
rr2[j][i] = rr2[i][j];
rbij[i][j] = gamma2_ij * rbrb;
rbij[j][i] = - rbij[i][j];
pp2[i][j] = pij2
+ irelcr * ( - G4Pow::GetInstance()->powN ( p4i.e() - p4j.e() , 2 )
+ gamma2_ij * G4Pow::GetInstance()->powN ( ( ( p4i.m2() - p4j.m2() ) / eij ) , 2 ) );
pp2[j][i] = pp2[i][j];
// Gauss term
G4double expa1 = - rr2[i][j] * c0w;
G4double rh1;
if ( expa1 > epsx )
{
rh1 = G4Exp( expa1 );
}
else
{
rh1 = 0.0;
}
G4int ibry = system->GetParticipant(i)->GetBaryonNumber();
G4int jbry = system->GetParticipant(j)->GetBaryonNumber();
rha[i][j] = ibry*jbry*rh1;
rha[j][i] = rha[i][j];
// Coulomb terms
G4double rrs2 = rr2[i][j] + epscl;
G4double rrs = std::sqrt ( rrs2 );
G4int icharge = system->GetParticipant(i)->GetChargeInUnitOfEplus();
G4int jcharge = system->GetParticipant(j)->GetChargeInUnitOfEplus();
G4double xerf = 0.0;
// T. K. add this protection. 5.8 is good enough for double
if ( rrs*c0sw < 5.8 )
{
#if defined WIN32-VC
xerf = CLHEP::HepStat::erf ( rrs*c0sw );
#else
xerf = std::erf ( rrs*c0sw );
#endif
}
else
{
xerf = 1.0;
}
G4double erfij = xerf/rrs;
rhe[i][j] = icharge*jcharge * erfij;
rhe[j][i] = rhe[i][j];
rhc[i][j] = icharge*jcharge * ( - erfij + clw * rh1 ) / rrs2;
rhc[j][i] = rhc[i][j];
} // i
} // j
}
void G4LightIonQMDMeanField::Cal2BodyQuantities( G4int i )
{
G4ThreeVector ri = system->GetParticipant( i )->GetPosition();
G4LorentzVector p4i = system->GetParticipant( i )->Get4Momentum();
for ( G4int j = 0 ; j < system->GetTotalNumberOfParticipant() ; ++j )
{
if ( j == i ) { continue; }
G4ThreeVector rj = system->GetParticipant( j )->GetPosition();
G4LorentzVector p4j = system->GetParticipant( j )->Get4Momentum();
G4ThreeVector rij = ri - rj;
G4ThreeVector pij = (p4i - p4j).v();
G4LorentzVector p4ij = p4i - p4j;
G4ThreeVector bij = ( p4i + p4j ).boostVector();
G4double gammaij = ( p4i + p4j ).gamma();
G4double eij = ( p4i + p4j ).e();
G4double rbrb = rij*bij;
G4double rij2 = rij*rij;
G4double pij2 = pij*pij;
rbrb = irelcr * rbrb;
G4double gamma2_ij = gammaij*gammaij;
rr2[i][j] = rij2 + gamma2_ij * rbrb*rbrb;
rr2[j][i] = rr2[i][j];
rbij[i][j] = gamma2_ij * rbrb;
rbij[j][i] = - rbij[i][j];
pp2[i][j] = pij2
+ irelcr * ( - G4Pow::GetInstance()->powN ( p4i.e() - p4j.e() , 2 )
+ gamma2_ij * G4Pow::GetInstance()->powN ( ( ( p4i.m2() - p4j.m2() ) / eij ) , 2 ) );
pp2[j][i] = pp2[i][j];
// Gauss term
G4double expa1 = - rr2[i][j] * c0w;
G4double rh1;
if ( expa1 > epsx )
{
rh1 = G4Exp( expa1 );
}
else
{
rh1 = 0.0;
}
G4int ibry = system->GetParticipant(i)->GetBaryonNumber();
G4int jbry = system->GetParticipant(j)->GetBaryonNumber();
rha[i][j] = ibry*jbry*rh1;
rha[j][i] = rha[i][j];
// Coulomb terms
G4double rrs2 = rr2[i][j] + epscl;
G4double rrs = std::sqrt ( rrs2 );
G4int icharge = system->GetParticipant(i)->GetChargeInUnitOfEplus();
G4int jcharge = system->GetParticipant(j)->GetChargeInUnitOfEplus();
G4double xerf = 0.0;
// T. K. add this protection. 5.8 is good enough for double
if ( rrs*c0sw < 5.8 )
{
#if defined WIN32-VC
xerf = CLHEP::HepStat::erf ( rrs*c0sw );
#else
xerf = std::erf ( rrs*c0sw );
#endif
}
else
{
xerf = 1.0;
}
G4double erfij = xerf/rrs;
rhe[i][j] = icharge*jcharge * erfij;
rhe[j][i] = rhe[i][j];
rhc[i][j] = icharge*jcharge * ( - erfij + clw * rh1 ) / rrs2;
rhc[j][i] = rhc[i][j];
}
}
void G4LightIonQMDMeanField::CalGraduate()
{
ffr.resize( system->GetTotalNumberOfParticipant() );
ffp.resize( system->GetTotalNumberOfParticipant() );
rh3d.resize( system->GetTotalNumberOfParticipant() );
rh3d_tau.resize( system->GetTotalNumberOfParticipant() ); // Skyrme-QMD
for ( G4int i = 0 ; i < system->GetTotalNumberOfParticipant() ; ++i )
{
G4double rho3 = 0.0;
for ( G4int j = 0 ; j < system->GetTotalNumberOfParticipant() ; ++j )
{
rho3 += rha[j][i];
}
rh3d[i] = G4Pow::GetInstance()->powA ( rho3 , pag );
rh3d_tau[i] = G4Pow::GetInstance()->powA ( rho3 , pag_tau ); // Skyrme-QMD
}
for ( G4int i = 0 ; i < system->GetTotalNumberOfParticipant() ; ++i )
{
G4ThreeVector ri = system->GetParticipant( i )->GetPosition();
G4LorentzVector p4i = system->GetParticipant( i )->Get4Momentum();
G4ThreeVector betai = p4i.v()/p4i.e();
// R-JQMD
G4double Vi = GetPotential( i );
G4double p_zero = std::sqrt( p4i.e()*p4i.e() + 2*p4i.m()*Vi);
G4ThreeVector betai_R = p4i.v()/p_zero;
G4double mi_R = p4i.m()/p_zero;
ffr[i] = betai_R;
ffp[i] = G4ThreeVector( 0.0 );
for ( G4int j = 0 ; j < system->GetTotalNumberOfParticipant() ; ++j )
{
G4ThreeVector rj = system->GetParticipant( j )->GetPosition();
G4LorentzVector p4j = system->GetParticipant( j )->Get4Momentum();
G4double eij = p4i.e() + p4j.e();
G4int icharge = system->GetParticipant(i)->GetChargeInUnitOfEplus();
G4int jcharge = system->GetParticipant(j)->GetChargeInUnitOfEplus();
G4int inuc = system->GetParticipant(i)->GetNuc();
G4int jnuc = system->GetParticipant(j)->GetNuc();
G4double fsij = 3.0/(2*wl) - rr2[j][i]/(2*wl)/(2*wl); // Add for Skyrme-QMD
G4double ccpp = c0g * rha[j][i]
+ c3g * rha[j][i] * ( rh3d[j] + rh3d[i] )
+ cg0 * rha[j][i]/wl
+ cg0 * rha[j][i] * fsij
+ cgtau0 * rha[j][i] * ( rh3d_tau[j] + rh3d_tau[i] )
+ csg * rha[j][i] * jnuc * inuc
* ( 1. - 2. * std::abs( jcharge - icharge ) )
* (1. - kappas * fsij + kappas / wl)
+ cl * rhc[j][i];
ccpp *= mi_R;
G4double grbb = - rbij[j][i];
G4double ccrr = grbb * ccpp / eij;
G4ThreeVector rij = ri - rj;
G4ThreeVector betaij = ( p4i + p4j ).v()/eij;
G4ThreeVector cij = betaij - betai;
ffr[i] = ffr[i] + 2*ccrr* ( rij + grbb*cij );
ffp[i] = ffp[i] - 2*ccpp* ( rij + grbb*betaij );
}
}
}
G4double G4LightIonQMDMeanField::GetPotential( G4int i )
{
G4int n = system->GetTotalNumberOfParticipant();
G4double rhoa = 0.0;
G4double rho3 = 0.0;
G4double fsij_rhoa = 0.0; // Skyrme-QMD
//G4double fsij_rhos = 0.0; // Skyrme-QMD
G4double rho3_tau = 0.0; // Skyrme-QMD
G4double rhos = 0.0;
G4double rhoc = 0.0;
G4int icharge = system->GetParticipant(i)->GetChargeInUnitOfEplus();
G4int inuc = system->GetParticipant(i)->GetNuc();
for ( G4int j = 0 ; j < n ; ++j )
{
G4int jcharge = system->GetParticipant(j)->GetChargeInUnitOfEplus();
G4int jnuc = system->GetParticipant(j)->GetNuc();
G4double fsij = 3.0/(2*wl) - rr2[j][i]/(2*wl)/(2*wl); // Add for Skyrme-QMD
rhoa += rha[j][i];
fsij_rhoa += fsij * rha[j][i]; // Skyrme-QMD
rhoc += rhe[j][i];
rhos += rha[j][i] * jnuc * inuc
* ( 1. - 2. * std::abs( jcharge - icharge ) ) // Skyrme-QMD
* (1. - kappas * fsij); // Skyrme-QMD
}
rho3 = G4Pow::GetInstance()->powA ( rhoa , gamm );
rho3_tau = G4Pow::GetInstance()->powA ( rhoa , eta );
G4double potential = c0 * rhoa
+ c3 * rho3
+ g0 * fsij_rhoa // Skyrme-QMD
//+ g0iso * fsij_rhos // Skyrme-QMD
+ gtau0 * rho3_tau // Skyrme-QMD
+ cs * rhos
+ cl * rhoc;
return potential;
}
G4double G4LightIonQMDMeanField::GetTotalPotential()
{
G4int n = system->GetTotalNumberOfParticipant();
std::vector < G4double > rhoa ( n , 0.0 );
std::vector < G4double > rho3 ( n , 0.0 );
std::vector < G4double > rho3_tau ( n , 0.0 ); // Skyrme-QMD
//std::vector < G4double > fsij_rhos ( n , 0.0 ); // Skyrme-QMD
std::vector < G4double > fsij_rhoa ( n , 0.0 ); // Skyrme-QMD
std::vector < G4double > rhos ( n , 0.0 );
std::vector < G4double > rhoc ( n , 0.0 );
for ( G4int i = 0 ; i < n ; ++i )
{
G4int icharge = system->GetParticipant(i)->GetChargeInUnitOfEplus();
G4int inuc = system->GetParticipant(i)->GetNuc();
for ( G4int j = 0 ; j < n ; ++j )
{
G4int jcharge = system->GetParticipant(j)->GetChargeInUnitOfEplus();
G4int jnuc = system->GetParticipant(j)->GetNuc();
G4double fsij = 3.0/(2*wl) - rr2[j][i]/(2*wl)/(2*wl); // Add for Skyrme-QMD
rhoa[i] += rha[j][i];
fsij_rhoa[i] += fsij * rha[j][i]; // Skyrme-QMD
rhoc[i] += rhe[j][i];
rhos[i] += rha[j][i] * jnuc * inuc
//* ( 1 - 2 * std::abs ( jcharge - icharge ) );
* ( 1. - 2. * std::abs( jcharge - icharge ) ) // Skyrme-QMD
* (1. - kappas * fsij); // Skyrme-QMD
//fsij_rhos[i] += fsij * rha[j][i] * jnuc * inuc
//* ( 1. - 2. * std::abs( jcharge - icharge ) ) // Skyrme-QMD
//* (1. - kappas * fsij); // Skyrme-QMD
}
rho3[i] = G4Pow::GetInstance()->powA ( rhoa[i] , gamm );
rho3_tau[i] = G4Pow::GetInstance()->powA ( rhoa[i] , eta );
}
G4double potential = c0 * std::accumulate( rhoa.cbegin() , rhoa.cend() , 0.0 )
+ c3 * std::accumulate( rho3.cbegin() , rho3.cend() , 0.0 )
+ g0 * std::accumulate( fsij_rhoa.cbegin() , fsij_rhoa.cend() , 0.0 )
//+ g0iso * std::accumulate( fsij_rhos.cbegin() , fsij_rhos.cend() , 0.0 )
+ gtau0 * std::accumulate( rho3_tau.cbegin() , rho3_tau.cend() , 0.0 )
+ cs * std::accumulate( rhos.cbegin() , rhos.cend() , 0.0 )
+ cl * std::accumulate( rhoc.cbegin() , rhoc.cend() , 0.0 );
return potential;
}
G4double G4LightIonQMDMeanField::GetSingleEnergy( G4int j )
{
G4LorentzVector p4j = system->GetParticipant( j )->Get4Momentum();
G4double emass = p4j.m();
G4double ekinal2 = p4j.e()*p4j.e();
G4double esingle = std::sqrt(ekinal2 + 2*emass*GetPotential(j));
return esingle;
}
G4double G4LightIonQMDMeanField::GetTotalEnergy()
{
G4int n = system->GetTotalNumberOfParticipant();
G4double etotal = 0.0;
for ( int j = 0 ; j < n ; j++ )
{
G4LorentzVector p4j = system->GetParticipant( j )->Get4Momentum();
G4double emass = p4j.m();
G4double ekinal2 = p4j.e()*p4j.e();
etotal += std::sqrt(ekinal2 + 2*emass*GetPotential(j));
}
return etotal;
}
G4double G4LightIonQMDMeanField::calPauliBlockingFactor( G4int i )
{
// i is supposed beyond total number of Participant()
G4double pf = 0.0;
G4int icharge = system->GetParticipant(i)->GetChargeInUnitOfEplus();
for ( G4int j = 0 ; j < system->GetTotalNumberOfParticipant() ; ++j )
{
G4int jcharge = system->GetParticipant(j)->GetChargeInUnitOfEplus();
G4int jnuc = system->GetParticipant(j)->GetNuc();
if ( jcharge == icharge && jnuc == 1 )
{
G4double expa = -rr2[i][j]*cpw;
if ( expa > epsx )
{
expa = expa - pp2[i][j]*cph;
if ( expa > epsx )
{
pf = pf + G4Exp ( expa );
}
}
}
}
return ( pf - 1.0 ) * cpc;
}
G4bool G4LightIonQMDMeanField::IsPauliBlocked( G4int i )
{
G4bool result = false;
if ( system->GetParticipant( i )->GetNuc() == 1 )
{
G4double pf = calPauliBlockingFactor( i );
G4double rand = G4UniformRand();
if ( pf > rand ) { result = true; }
}
return result;
}
void G4LightIonQMDMeanField::DoPropagation( G4double dt )
{
G4double cc2 = 1.0;
G4double cc1 = 1.0 - cc2;
G4double cc3 = 1.0 / 2.0 / cc2;
G4double dt3 = dt * cc3;
G4double dt1 = dt * ( cc1 - cc3 );
G4double dt2 = dt * cc2;
CalGraduate();
G4int n = system->GetTotalNumberOfParticipant();
// 1st Step
std::vector< G4ThreeVector > f0r, f0p;
f0r.resize( n );
f0p.resize( n );
for ( G4int i = 0 ; i < n ; ++i )
{
G4ThreeVector ri = system->GetParticipant( i )->GetPosition();
G4ThreeVector p3i = system->GetParticipant( i )->GetMomentum();
ri += dt3* ffr[i];
p3i += dt3* ffp[i];
f0r[i] = ffr[i];
f0p[i] = ffp[i];
system->GetParticipant( i )->SetPosition( ri );
system->GetParticipant( i )->SetMomentum( p3i );
// we do not need set total momentum by ourselvs
}
// 2nd Step
Cal2BodyQuantities();
CalGraduate();
for ( G4int i = 0 ; i < n ; ++i )
{
G4ThreeVector ri = system->GetParticipant( i )->GetPosition();
G4ThreeVector p3i = system->GetParticipant( i )->GetMomentum();
ri += dt1* f0r[i] + dt2* ffr[i];
p3i += dt1* f0p[i] + dt2* ffp[i];
system->GetParticipant( i )->SetPosition( ri );
system->GetParticipant( i )->SetMomentum( p3i );
// we do not need set total momentum by ourselvs
}
Cal2BodyQuantities();
}
std::vector< G4LightIonQMDNucleus* > G4LightIonQMDMeanField::DoClusterJudgment()
{
Cal2BodyQuantities();
G4double cpf2 = G4Pow::GetInstance()->A23 ( 1.5 * pi*pi * G4Pow::GetInstance()->powA ( 4.0 * pi * wl , -1.5 ) ) * hbc * hbc;
G4double rcc2 = rclds*rclds;
G4int n = system->GetTotalNumberOfParticipant();
std::vector < G4double > rhoa;
rhoa.resize ( n );
for ( G4int i = 0 ; i < n ; ++i )
{
rhoa[i] = 0.0;
if ( system->GetParticipant( i )->GetBaryonNumber() == 1 )
{
for ( G4int j = 0 ; j < n ; ++j )
{
if ( system->GetParticipant( j )->GetBaryonNumber() == 1 )
rhoa[i] += rha[i][j];
}
}
rhoa[i] = G4Pow::GetInstance()->A13 ( rhoa[i] + 1 );
}
// identification of the cluster
std::vector < G4bool > is_already_belong_some_cluster;
// cluster_id participant_id
std::multimap < G4int , G4int > comb_map;
std::multimap < G4int , G4int > assign_map;
assign_map.clear();
std::vector < G4int > mascl;
std::vector < G4int > num;
mascl.resize ( n );
num.resize ( n );
is_already_belong_some_cluster.resize ( n );
std::vector < G4int > is_assigned_to ( n , -1 );
std::multimap < G4int , G4int > clusters;
for ( G4int i = 0 ; i < n ; ++i )
{
mascl[i] = 1;
num[i] = 1;
is_already_belong_some_cluster[i] = false;
}
G4int ichek = 1;
G4int id = 0;
G4int cluster_id = -1;
for ( G4int i = 0 ; i < n-1 ; ++i )
{
G4bool hasThisCompany = false;
if ( system->GetParticipant( i )->GetBaryonNumber() == 1 )
{
G4int j1 = i + 1;
for ( G4int j = j1 ; j < n ; ++j )
{
std::vector < G4int > cluster_participants;
if ( system->GetParticipant( j )->GetBaryonNumber() == 1 )
{
G4double rdist2 = rr2[ i ][ j ];
G4double pdist2 = pp2[ i ][ j ];
G4double pcc2 = cpf2
* ( rhoa[ i ] + rhoa[ j ] )
* ( rhoa[ i ] + rhoa[ j ] );
// Check phase space: close enough?
if ( rdist2 < rcc2 && pdist2 < pcc2 )
{
if ( is_assigned_to [ j ] == -1 )
{
if ( is_assigned_to [ i ] == -1 )
{
if ( clusters.size() != 0 )
{
id = clusters.rbegin()->first + 1;
}
else
{
id = 0;
}
clusters.insert ( std::multimap<G4int,G4int>::value_type ( id , i ) );
is_assigned_to [ i ] = id;
clusters.insert ( std::multimap<G4int,G4int>::value_type ( id , j ) );
is_assigned_to [ j ] = id;
}
else
{
clusters.insert ( std::multimap<G4int,G4int>::value_type ( is_assigned_to [ i ] , j ) );
is_assigned_to [ j ] = is_assigned_to [ i ];
}
}
else
{
// j is already belong to some cluster
if ( is_assigned_to [ i ] == -1 )
{
clusters.insert ( std::multimap<G4int,G4int>::value_type ( is_assigned_to [ j ] , i ) );
is_assigned_to [ i ] = is_assigned_to [ j ];
}
else
{
// i has companion
if ( is_assigned_to [ i ] != is_assigned_to [ j ] )
{
// move companions to the cluster
std::multimap< G4int , G4int > clusters_tmp;
G4int target_cluster_id;
if ( is_assigned_to [ i ] > is_assigned_to [ j ] )
{
target_cluster_id = is_assigned_to [ i ];
}
else
{
target_cluster_id = is_assigned_to [ j ];
}
for ( auto it = clusters.cbegin() ; it != clusters.cend() ; ++it )
{
if ( it->first == target_cluster_id )
{
is_assigned_to [ it->second ] = is_assigned_to [ j ];
clusters_tmp.insert ( std::multimap<G4int,G4int>::value_type ( is_assigned_to [ j ] , it->second ) );
}
else
{
clusters_tmp.insert ( std::multimap<G4int,G4int>::value_type ( it->first , it->second ) );
}
}
clusters = clusters_tmp;
}
}
}
comb_map.insert( std::multimap<G4int,G4int>::value_type ( i , j ) );
cluster_participants.push_back ( j );
if ( assign_map.find( cluster_id ) == assign_map.end() )
{
is_already_belong_some_cluster[i] = true;
assign_map.insert ( std::multimap<G4int,G4int>::value_type ( cluster_id , i ) );
hasThisCompany = true;
}
assign_map.insert ( std::multimap<G4int,G4int>::value_type ( cluster_id , j ) );
is_already_belong_some_cluster[j] = true;
}
if ( ichek == i )
{
++ichek;
}
}
}
}
if ( hasThisCompany == true ) { ++cluster_id; }
}
// sort
// Heavy cluster comes first
// size cluster_id
std::multimap< G4int , G4int > sorted_cluster_map;
for ( G4int i = 0 ; i <= id ; ++i ) // << "<=" because id is highest cluster nubmer.
{
sorted_cluster_map.insert ( std::multimap<G4int,G4int>::value_type ( (G4int) clusters.count( i ) , i ) );
}
// create nucleus from divided clusters
std::vector < G4LightIonQMDNucleus* > result;
for ( auto it = sorted_cluster_map.crbegin(); it != sorted_cluster_map.crend(); ++it )
{
if ( it->first != 0 )
{
G4LightIonQMDNucleus* nucleus = new G4LightIonQMDNucleus();
for ( auto itt = clusters.cbegin(); itt != clusters.cend(); ++itt )
{
if ( it->second == itt->first )
{
nucleus->SetParticipant( system->GetParticipant ( itt->second ) );
}
}
result.push_back( nucleus );
}
}
// delete participants from current system
for ( auto it = result.cbegin(); it != result.cend(); ++it )
{
system->SubtractSystem ( *it );
}
return result;
}
void G4LightIonQMDMeanField::Update()
{
SetSystem( system );
}
@@ -0,0 +1,404 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// 081024 G4NucleiPropertiesTable:: to G4NucleiProperties::
//
// 230309 Skyrme-QMD parameters added by Y-H. Sato and A. Haga
// 230309 Total energy evaluated by Lorentz covariant version by Y-H. Sato and A. Haga
#include <numeric>
#include "G4LightIonQMDNucleus.hh"
#include "G4Pow.hh"
#include "G4SystemOfUnits.hh"
#include "G4Proton.hh"
#include "G4Neutron.hh"
#include "G4NucleiProperties.hh"
#include "G4HadronicException.hh"
#include "G4LightIonQMDParameters.hh" // 20230309
#include "G4PhysicalConstants.hh" // 20230309
#include <cmath> // 20230309
#include <CLHEP/Random/Stat.h> // 20230309
G4LightIonQMDNucleus::G4LightIonQMDNucleus()
{
G4LightIonQMDParameters* parameters = G4LightIonQMDParameters::GetInstance();
hbc = parameters->Get_hbc();
jj = 0; // will be calcualted in CalEnergyAndAngularMomentumInCM;
potentialEnergy = 0.0; // will be set through set method
excitationEnergy = 0.0;
// Following Parameters are added (20230309)
wl = parameters->Get_wl();
cl = parameters->Get_cl();
rho0 = parameters->Get_rho0();
gamm = parameters->Get_gamm();
eta = parameters->Get_eta(); // Skyrme-QMD
kappas = parameters->Get_kappas(); // Skyrme-QMD
cpw = parameters->Get_cpw();
cph = parameters->Get_cph();
cpc = parameters->Get_cpc();
c0 = parameters->Get_c0();
c3 = parameters->Get_c3();
cs = parameters->Get_cs();
g0 = parameters->Get_g0(); // Skyrme-QMD
g0iso = parameters->Get_g0iso(); // Skyrme-QMD
gtau0 = parameters->Get_gtau0(); // Skyrme-QMD
// distance
c0w = 1.0/4.0/wl;
//c3w = 1.0/4.0/wl; //no need
c0sw = std::sqrt( c0w );
clw = 2.0 / std::sqrt ( 4.0 * pi * wl );
// graduate
c0g = - c0 / ( 2.0 * wl );
c3g = - c3 / ( 4.0 * wl ) * gamm;
csg = - cs / ( 2.0 * wl );
pag = gamm - 1;
pag_tau = eta - 1; // Skyrme-QMD
cg0 = - g0 / ( 2.0 * wl ); // Skyrme-QMD
cgtau0 = - gtau0 / ( 4.0 * wl ) * eta; // Skyrme-QMD
}
//G4LightIonQMDNucleus::~G4LightIonQMDNucleus()
//{
// ;
//}
G4LorentzVector G4LightIonQMDNucleus::Get4Momentum()
{
G4LorentzVector p( 0 );
std::vector< G4QMDParticipant* >::iterator it;
for ( it = participants.begin() ; it != participants.end() ; it++ )
p += (*it)->Get4Momentum();
return p;
}
G4int G4LightIonQMDNucleus::GetMassNumber()
{
G4int A = 0;
std::vector< G4QMDParticipant* >::iterator it;
for ( it = participants.begin() ; it != participants.end() ; it++ )
{
if ( (*it)->GetDefinition() == G4Proton::Proton()
|| (*it)->GetDefinition() == G4Neutron::Neutron() )
A++;
}
if ( A == 0 ) {
throw G4HadronicException(__FILE__, __LINE__, "G4LightIonQMDNucleus has the mass number of 0!");
}
return A;
}
G4int G4LightIonQMDNucleus::GetAtomicNumber()
{
G4int Z = 0;
std::vector< G4QMDParticipant* >::iterator it;
for ( it = participants.begin() ; it != participants.end() ; it++ )
{
if ( (*it)->GetDefinition() == G4Proton::Proton() )
Z++;
}
return Z;
}
G4double G4LightIonQMDNucleus::GetNuclearMass()
{
G4double mass = G4NucleiProperties::GetNuclearMass( GetMassNumber() , GetAtomicNumber() );
if ( mass == 0.0 )
{
G4int Z = GetAtomicNumber();
G4int A = GetMassNumber();
G4int N = A - Z;
// Weizsacker-Bethe
G4double Av = 16*MeV;
G4double As = 17*MeV;
G4double Ac = 0.7*MeV;
G4double Asym = 23*MeV;
G4double BE = Av * A
- As * G4Pow::GetInstance()->A23 ( G4double ( A ) )
- Ac * Z*Z/G4Pow::GetInstance()->A13 ( G4double ( A ) )
- Asym * ( N - Z )* ( N - Z ) / A;
mass = Z * G4Proton::Proton()->GetPDGMass()
+ N * G4Neutron::Neutron()->GetPDGMass()
- BE;
}
return mass;
}
void G4LightIonQMDNucleus::CalEnergyAndAngularMomentumInCM()
{
//G4cout << "CalEnergyAndAngularMomentumInCM " << this->GetAtomicNumber() << " " << GetMassNumber() << G4endl;
G4double gamma = Get4Momentum().gamma();
G4ThreeVector beta = Get4Momentum().v()/ Get4Momentum().e();
G4ThreeVector pcm0( 0.0 ) ;
G4int n = GetTotalNumberOfParticipant();
pcm.resize( n );
for ( G4int i= 0; i < n ; i++ )
{
G4ThreeVector p_i = GetParticipant( i )->GetMomentum();
G4double trans = gamma / ( gamma + 1.0 ) * p_i * beta;
pcm[i] = p_i - trans*beta;
pcm0 += pcm[i];
}
pcm0 = pcm0 / double ( n );
//G4cout << "pcm0 " << pcm0 << G4endl;
for ( G4int i= 0; i < n ; i++ )
{
pcm[i] += -pcm0;
//G4cout << "pcm " << i << " " << pcm[i] << G4endl;
}
G4double tmass = 0;
G4ThreeVector rcm0( 0.0 ) ;
rcm.resize( n );
es.resize( n );
// binding energy should be evaluated with a relativistic version: 20230308 by Y-H. Sato and A. Haga
for ( G4int i= 0; i < n ; i++ )
{
G4ThreeVector ri = GetParticipant( i )->GetPosition();
G4double trans = gamma / ( gamma + 1.0 ) * ri * beta;
G4double nucpote = GetNuclPotential( i );
es[i] = std::sqrt ( G4Pow::GetInstance()->powN ( GetParticipant( i )->GetMass() , 2 ) + pcm[i]*pcm[i] + 2.0*GetParticipant( i )->GetMass()*nucpote) - GetParticipant( i )->GetMass(); //R-JQMD
rcm[i] = ri + trans*beta;
rcm0 += rcm[i]*es[i];
tmass += es[i];
}
rcm0 = rcm0/tmass;
for ( G4int i= 0; i < n ; i++ )
{
rcm[i] += -rcm0;
//G4cout << "rcm " << i << " " << rcm[i] << G4endl;
}
// Angular momentum
G4ThreeVector rl ( 0.0 );
for ( G4int i= 0; i < n ; i++ )
{
rl += rcm[i].cross ( pcm[i] );
}
// DHW: move hbc outside of sqrt to get correct units
// jj = int ( std::sqrt ( rl*rl / hbc ) + 0.5 );
jj = int (std::sqrt(rl*rl)/hbc + 0.5);
// kinetic energy per nucleon in CM
/*
G4double totalMass = 0.0;
for ( G4int i= 0; i < n ; i++ )
{
// following two lines are equivalent
//totalMass += GetParticipant( i )->GetDefinition()->GetPDGMass()/GeV;
totalMass += GetParticipant( i )->GetMass();
}
*/
//G4double kineticEnergyPerNucleon = ( std::accumulate ( es.begin() , es.end() , 0.0 ) - totalMass )/n;
// Total (not per nucleion ) Binding Energy
// relativistic version Y-H. Sato and A. Haga 20230309
G4double bindingEnergy = ( std::accumulate ( es.begin() , es.end() , 0.0 ) );
//G4cout << "n " << n << "totalpote " << totalpote << " " << potentialEnergy << " " << bindingEnergy << G4endl;
//G4cout << "KineticEnergyPerNucleon in GeV " << kineticEnergyPerNucleon << G4endl;
//G4cout << "KineticEnergySum in GeV " << std::accumulate ( es.begin() , es.end() , 0.0 ) - totalMass << G4endl;
//G4cout << "PotentialEnergy in GeV " << potentialEnergy << G4endl;
//G4cout << "BindingEnergy in GeV " << bindingEnergy << G4endl;
//G4cout << "G4BindingEnergy in GeV " << G4NucleiProperties::GetBindingEnergy( GetAtomicNumber() , GetMassNumber() )/GeV << G4endl;
excitationEnergy = bindingEnergy + G4NucleiProperties::GetBindingEnergy( GetMassNumber() , GetAtomicNumber() )/GeV;
if ( excitationEnergy < 0 ) excitationEnergy = 0.0;
}
// Get potential with a relativistic version added by Y-H. Sato and A. Haga 20230309
G4double G4LightIonQMDNucleus::GetNuclPotential( G4int i )
{
epsx = -20.0;
epscl = 0.0001; // coulomb term
irelcr = 1;
G4int n = GetTotalNumberOfParticipant();
G4double rhoa = 0.0;
G4double rho3 = 0.0;
G4double fsij_rhoa = 0.0; // Skyrme-QMD
// G4double fsij_rhos = 0.0; // Skyrme-QMD
G4double rho3_tau = 0.0; // Skyrme-QMD
G4double rhos = 0.0;
G4double rhoc = 0.0;
G4int icharge = GetParticipant(i)->GetChargeInUnitOfEplus();
G4int inuc = GetParticipant(i)->GetNuc();
G4int ibry = GetParticipant(i)->GetBaryonNumber();
G4ThreeVector ri = GetParticipant( i )->GetPosition();
G4LorentzVector p4i = GetParticipant( i )->Get4Momentum();
for ( G4int j = 0 ; j < n ; j ++ )
{
G4double cef = 1.0;
if (i == j)
{
cef = 0.0;
}
G4int jcharge = GetParticipant(j)->GetChargeInUnitOfEplus();
G4int jnuc = GetParticipant(j)->GetNuc();
G4int jbry = GetParticipant(j)->GetBaryonNumber();
G4ThreeVector rj = GetParticipant( j )->GetPosition();
G4LorentzVector p4j = GetParticipant( j )->Get4Momentum();
G4ThreeVector rij = ri - rj;
G4ThreeVector pij = (p4i - p4j).v();
G4LorentzVector p4ij = p4i - p4j;
G4ThreeVector bij = ( p4i + p4j ).boostVector();
G4double gammaij = ( p4i + p4j ).gamma();
//G4double eij = ( p4i + p4j ).e();
G4double rbrb = rij*bij;
// G4double bij2 = bij*bij;
G4double rij2 = rij*rij;
//G4double pij2 = pij*pij;
rbrb = irelcr * rbrb;
G4double gamma2_ij = gammaij*gammaij;
G4double rr2 = rij2 + gamma2_ij * rbrb*rbrb;
G4double expa1 = - (rij2 + gamma2_ij * rbrb*rbrb) * c0w;
G4double rh1;
if ( expa1 > epsx )
{
rh1 = G4Exp( expa1 );
}
else
{
rh1 = 0.0;
}
G4double rrs2 = (rij2 + gamma2_ij * rbrb*rbrb) + epscl;
G4double rrs = std::sqrt ( rrs2 );
G4double xerf = 0.0;
// T. K. add this protection. 5.8 is good enough for double
if ( rrs*c0sw < 5.8 ) {
//erf = G4RandStat::erf ( rrs*c0sw );
//Restore to CLHEP for avoiding compilation error in MT
//erf = CLHEP::HepStat::erf ( rrs*c0sw );
//Use cmath
#if defined WIN32-VC
xerf = CLHEP::HepStat::erf ( rrs*c0sw );
#else
xerf = std::erf ( rrs*c0sw );
#endif
} else {
xerf = 1.0;
}
G4double erfij = xerf/rrs;
G4double fsij = 3.0/(2*wl) - rr2/(2*wl)/(2*wl); // Add for Skyrme-QMD
rhoa += ibry*jbry*rh1*cef;
fsij_rhoa += fsij * ibry*jbry*rh1*cef; // Skyrme-QMD
rhoc += icharge*jcharge * erfij * cef;
rhos += ibry*jbry*rh1 * jnuc * inuc * cef
* ( 1 - 2 * std::abs ( jcharge - icharge ) )
* (1. - kappas * fsij);
//G4cout << i << " " << j << " " << ( - erfij ) << " " << clw << G4endl;
}
rho3 = G4Pow::GetInstance()->powA ( rhoa , gamm );
rho3_tau = G4Pow::GetInstance()->powA ( rhoa , eta );
G4double potential = c0 * rhoa
+ c3 * rho3
+ g0 * fsij_rhoa // Skyrme-QMD
// + g0iso * fsij_rhos // Skyrme-QMD
+ gtau0 * rho3_tau // Skyrme-QMD
+ cs * rhos
+ cl * rhoc;
//G4cout << "n " << n << " " << rho3 << G4endl;
return potential;
}
@@ -0,0 +1,159 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// Parameters comes from JQMD
// Niita et al., JAERI-Data/Code 99-042
//
// 230307 Skyrme-QMD parameters added by Y-H. Sato and A. Haga
#include "G4LightIonQMDParameters.hh"
#include "G4Pow.hh"
#include "G4PhysicalConstants.hh"
G4ThreadLocal G4LightIonQMDParameters* G4LightIonQMDParameters::parameters = NULL;
G4LightIonQMDParameters::G4LightIonQMDParameters()
{
G4Pow* pow=G4Pow::GetInstance();
wl = 1.26; // width of wave packet [fm]
hbc = 0.19732857; // h-bar c in GeVfm
//Pauli
cpw = 1.0 / 2.0 / wl;
cph = 2.0 * wl / (hbc*hbc);
cpc = 4.0;
epsx = -20.0 ;
// JQMD
/*
rho0 = 0.168; // satulation density
G4double rpot = 1.0/3.0;
G4double ebinm = -16.0; // bounding energy [MeV]
G4double ebin = ebinm * 0.001;
G4double pfer = hbc * pow->A13 ( 3./2. *pi*pi * rho0 );
G4double rmass = 0.938;
G4double efer = pfer*pfer / 2. / rmass;
G4double t3 = 8. / 3. / rpot / pow->powA( rho0 , ( 1.+rpot ) ) * ( efer / 5. - ebin );
G4double t0 = -16./15. * efer / rho0 - ( 1.+rpot ) * t3 * pow->powA( rho0 , rpot );
G4double aaa = 3./4. * t0 * rho0;
G4double bbb = 3./8. * t3 * ( 2.+rpot ) * pow->powA( rho0 , ( 1.+rpot ) );
G4double esymm = 25 * 0.001; // symetric potential 25 [MeV] -> GeV
gamm = rpot + 1.0;
*/
// Skyrme-QMD
// Ref. Y. Zhang and Z. Li, Elliptic flow and system size dependence of transition energies at intermediate energies, Phys.Rev. C74 (2006) 014602.
// ImQMD-SLy4
/*
rho0 = 0.159546;
G4double aaa = -297.82 * 0.001;
G4double bbb = 219.21 * 0.001;
gamm = 7.0/6;
eta = 5.0/3;
kappas = 0.08;
g0 = 24.569/(2 * rho0 * pow->powA( 4 * pi * wl , 1.5 )) * 0.001;
g0iso = 4.557/(rho0 * pow->powA( 4 * pi * wl , 1.5 )) * 0.001;
gtau0 = 9.70/(pow->powA( rho0 , eta ) * pow->powA ( (4.0*pi*wl) , (1.5*eta) )) * 0.001;
G4double esymm = 32 * 0.001;
*/
// ImQMD-SkMstar
//rho0 = 0.165;
rho0 = 0.1603; // satulation density
G4double aaa = -318.0 * 0.001;
G4double bbb = 249.5 * 0.001;
gamm = 7.0/6;
eta = 5.0/3;
kappas = 0.08;
g0 = 21.86/(2 * rho0 * pow->powA( 4 * pi * wl , 1.5 )) * 0.001;
//g0iso = -5.485/(rho0 * pow->powA( 4 * pi * wl , 1.5 )) * 0.001; -> kappas
gtau0 = 5.9357/(pow->powA( rho0 , eta ) * pow->powA ( (4.0*pi*wl) , (1.5*eta) )) * 0.001;
G4double esymm = 32 * 0.001;
// ImQMD-SIII
/*
rho0 = 0.1452; // satulation density
G4double aaa = -122.921 * 0.001;
G4double bbb = 55.343 * 0.001;
gamm = 2;
eta = 5.0/3;
kappas = 0.08;
g0 = 18.286/(2 * rho0 * pow->powA( 4 * pi * wl , 1.5 )) * 0.001;
//g0iso = -5.485/(rho0 * pow->powA( 4 * pi * wl , 1.5 )) * 0.001; -> kappas
gtau0 = 6.439/(pow->powA( rho0 , eta ) * pow->powA ( (4.0*pi*wl) , (1.5*eta) )) * 0.001;
G4double esymm = 28.17 * 0.001;
*/
// Local Potenials
c0 = aaa / ( rho0 * pow->powA( 4 * pi * wl , 1.5 ) * 2.0 );
c3 = bbb / ( pow->powA( rho0 , gamm ) * pow->powA ( (4.0*pi*wl) , (1.5*gamm) ) * ( gamm+1.0) );
cs = esymm / ( rho0 * pow->powA( (4.0*pi*wl) , 1.5 ) * 2.0 );
G4double ccoul = 0.001439767;
cl = ccoul/2.0 * 1; // Include Coulomb interaction
//cl = ccoul/2.0 * 0; // Not Include Coulomb interaction
// GroundStateNucleus
cdp = 1.0 / pow->powA ( ( 4.0 * pi * wl ) , 1.5 );
c0p = c0 * 2.0;
c3p = c3 * ( gamm + 1.0 );
csp = cs * 2.0;
clp = cl * 2.0;
g0p = g0 * 2.0; // Skyrme-QMD
g0isop = g0iso * 2.0; // Skyrme-QMD
gtau0p = gtau0 * ( eta + 1.0 ); // Skyrme-QMD
}
G4LightIonQMDParameters::~G4LightIonQMDParameters()
{
;
}
@@ -0,0 +1,878 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// 080505 Fixed and changed sampling method of impact parameter by T. Koi
// 080602 Fix memory leaks by T. Koi
// 080612 Delete unnecessary dependency and unused functions
// Change criterion of reaction by T. Koi
// 081107 Add UnUseGEM (then use the default channel of G4Evaporation)
// UseFrag (chage criterion of a inelastic reaction)
// Fix bug in nucleon projectiles by T. Koi
// 090122 Be8 -> Alpha + Alpha
// 090331 Change member shenXS and genspaXS object to pointer
// 091119 Fix for incidence of neutral particles
//
// 230306 Fix in the judgement of elasticLike_system for nucleon-nucleon, pion-nucleon collistion
// in line 450 by Y-H. Sato and A. Haga.
// 230306 Fix for nucleon deplication
// added system->Clear() in line 522 by Y-H. Sato and A. Haga.
// 230306 Allowing to simlate nucleon-nucleon, pion-nucleon scattering
// pion is accepted in the Ratherford parameter setting by Y-H. Sato and A. Haga.
//
#include "G4LightIonQMDReaction.hh"
#include "G4LightIonQMDNucleus.hh"
#include "G4LightIonQMDGroundStateNucleus.hh"
#include "G4Pow.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4NistManager.hh"
#include "G4CrossSectionDataSetRegistry.hh"
#include "G4BGGPionElasticXS.hh"
#include "G4BGGPionInelasticXS.hh"
#include "G4VCrossSectionDataSet.hh"
#include "G4CrossSectionInelastic.hh"
#include "G4ComponentGGNuclNuclXsc.hh"
#include "G4PhysicsModelCatalog.hh"
// Fpr inelastic cross section check
#include "G4NuclearRadii.hh"
#include "G4HadronNucleonXsc.hh"
// test.csv (writting reaction data (particle, position, momentum))
#include <iostream>
#include <fstream>
using std::endl; // ***
using std::ofstream; // ***
// -- test.csv
G4LightIonQMDReaction::G4LightIonQMDReaction()
: G4HadronicInteraction("LightIonQMDModel")
, system ( NULL )
, deltaT ( 1 ) // in fsec (c=1)
, maxTime ( 100 ) // will have maxTime-th time step
, envelopF ( 1.05 ) // 10% for Peripheral reactions
, gem ( true )
, frag ( false )
, secID( -1 )
{
G4cout << "G4LightIonQMDReaction::G4LightIonQMDReaction" << G4endl;
G4cout << "Recommended Energy of LightIonQMD: 30MeV/u - 500MeV/u" << G4endl;
theXS = new G4CrossSectionInelastic( new G4ComponentGGNuclNuclXsc );
pipElNucXS = new G4BGGPionElasticXS(G4PionPlus::PionPlus() );
pipElNucXS->BuildPhysicsTable(*(G4PionPlus::PionPlus() ) );
pimElNucXS = new G4BGGPionElasticXS(G4PionMinus::PionMinus() );
pimElNucXS->BuildPhysicsTable(*(G4PionMinus::PionMinus() ) );
pipInelNucXS = new G4BGGPionInelasticXS(G4PionPlus::PionPlus() );
pipInelNucXS->BuildPhysicsTable(*(G4PionPlus::PionPlus() ) );
pimInelNucXS = new G4BGGPionInelasticXS(G4PionMinus::PionMinus() );
pimInelNucXS->BuildPhysicsTable(*(G4PionMinus::PionMinus() ) );
meanField = new G4LightIonQMDMeanField();
collision = new G4LightIonQMDCollision();
excitationHandler = new G4ExcitationHandler();
setEvaporationCh();
coulomb_collision_gamma_proj = 0.0;
coulomb_collision_rx_proj = 0.0;
coulomb_collision_rz_proj = 0.0;
coulomb_collision_px_proj = 0.0;
coulomb_collision_pz_proj = 0.0;
coulomb_collision_gamma_targ = 0.0;
coulomb_collision_rx_targ = 0.0;
coulomb_collision_rz_targ = 0.0;
coulomb_collision_px_targ = 0.0;
coulomb_collision_pz_targ = 0.0;
secID = G4PhysicsModelCatalog::GetModelID( "model_QMDModel" );
}
G4LightIonQMDReaction::~G4LightIonQMDReaction()
{
delete excitationHandler;
delete collision;
delete meanField;
}
G4HadFinalState* G4LightIonQMDReaction::ApplyYourself( const G4HadProjectile & projectile , G4Nucleus & target )
{
//G4cout << "G4LightIonQMDReaction::ApplyYourself" << G4endl;
theParticleChange.Clear();
system = new G4QMDSystem;
G4int proj_Z = 0;
G4int proj_A = 0;
const G4ParticleDefinition* proj_pd = ( const G4ParticleDefinition* ) projectile.GetDefinition();
if ( proj_pd->GetParticleType() == "nucleus" )
{
proj_Z = proj_pd->GetAtomicNumber();
proj_A = proj_pd->GetAtomicMass();
}
else
{
proj_Z = (int)( proj_pd->GetPDGCharge()/eplus );
proj_A = 1;
}
//G4int targ_Z = int ( target.GetZ() + 0.5 );
//G4int targ_A = int ( target.GetN() + 0.5 );
//migrate to integer A and Z (GetN_asInt returns number of neutrons in the nucleus since this)
G4int targ_Z = target.GetZ_asInt();
G4int targ_A = target.GetA_asInt();
const G4ParticleDefinition* targ_pd = G4IonTable::GetIonTable()->GetIon( targ_Z , targ_A , 0.0 );
//G4NistManager* nistMan = G4NistManager::Instance();
// G4Element* G4NistManager::FindOrBuildElement( targ_Z );
const G4DynamicParticle* proj_dp = new G4DynamicParticle ( proj_pd , projectile.Get4Momentum() );
//const G4Element* targ_ele = nistMan->FindOrBuildElement( targ_Z );
//G4double aTemp = projectile.GetMaterial()->GetTemperature();
// Glauber-Gribov nucleus-nucleus cross section does not have GetIsoCrossSection,
// therefore call GetElementCrossSection instead.
//G4double xs_0 = theXS->GetIsoCrossSection ( proj_dp , targ_Z , targ_A );
G4double xs_0 = theXS->GetElementCrossSection( proj_dp , targ_Z , projectile.GetMaterial() );
// When the projectile is a pion
if (proj_pd == G4PionPlus::PionPlus() ) {
xs_0 = pipElNucXS->GetElementCrossSection(proj_dp, targ_Z, projectile.GetMaterial() ) +
pipInelNucXS->GetElementCrossSection(proj_dp, targ_Z, projectile.GetMaterial() );
} else if (proj_pd == G4PionMinus::PionMinus() ) {
xs_0 = pimElNucXS->GetElementCrossSection(proj_dp, targ_Z, projectile.GetMaterial() ) +
pimInelNucXS->GetElementCrossSection(proj_dp, targ_Z, projectile.GetMaterial() );
}
//G4double xs_0 = genspaXS->GetCrossSection ( proj_dp , targ_ele , aTemp );
//G4double xs_0 = theXS->GetCrossSection ( proj_dp , targ_ele , aTemp );
//110822
G4double bmax_0 = std::sqrt( xs_0 / pi );
//std::cout << "bmax_0 in fm (fermi) " << bmax_0/fermi << std::endl;
//delete proj_dp;
G4bool elastic = true;
std::vector< G4LightIonQMDNucleus* > nucleuses; // Secondary nuceluses
G4ThreeVector boostToReac; // ReactionSystem (CM or NN);
G4ThreeVector boostBackToLAB; // Reaction System to LAB;
G4LorentzVector targ4p( G4ThreeVector( 0.0 ) , targ_pd->GetPDGMass()/GeV );
G4ThreeVector boostLABtoCM = targ4p.findBoostToCM( proj_dp->Get4Momentum()/GeV ); // CM of target and proj;
G4double p1 = proj_dp->GetMomentum().mag()/GeV/proj_A;
G4double m1 = proj_dp->GetDefinition()->GetPDGMass()/GeV/proj_A;
G4double e1 = std::sqrt( p1*p1 + m1*m1 );
G4double e2 = targ_pd->GetPDGMass()/GeV/targ_A;
G4double beta_nn = -p1 / ( e1+e2 );
G4ThreeVector boostLABtoNN ( 0. , 0. , beta_nn ); // CM of NN;
G4double beta_nncm = ( - boostLABtoCM.beta() + boostLABtoNN.beta() ) / ( 1 - boostLABtoCM.beta() * boostLABtoNN.beta() ) ;
//std::cout << targ4p << std::endl;
//std::cout << proj_dp->Get4Momentum()<< std::endl;
//std::cout << beta_nncm << std::endl;
G4ThreeVector boostNNtoCM( 0. , 0. , beta_nncm ); //
G4ThreeVector boostCMtoNN( 0. , 0. , -beta_nncm ); //
boostToReac = boostLABtoNN;
boostBackToLAB = -boostLABtoNN;
delete proj_dp;
G4int icounter = 0;
G4int icounter_max = 1024;
while ( elastic ) // Loop checking, 11.03.2015, T. Koi
{
icounter++;
if ( icounter > icounter_max ) {
G4cout << "Loop-counter exceeded the threshold value at " << __LINE__ << "th line of " << __FILE__ << "." << G4endl;
break;
}
// impact parameter
//G4double bmax = 1.05*(bmax_0/fermi); // 10% for Peripheral reactions
G4double bmax = envelopF*(bmax_0/fermi);
G4double b = bmax * std::sqrt ( G4UniformRand() );
//071112
//G4double b = 0;
//G4double b = bmax;
//G4double b = bmax/1.05 * 0.7 * G4UniformRand();
//G4cout << "G4QMDRESULT bmax_0 = " << bmax_0/fermi << " fm, bmax = " << bmax << " fm , b = " << b << " fm " << G4endl;
G4double plab = projectile.GetTotalMomentum()/GeV;
G4double elab = ( projectile.GetKineticEnergy() + proj_pd->GetPDGMass() + targ_pd->GetPDGMass() )/GeV;
calcOffSetOfCollision( b , proj_pd , targ_pd , plab , elab , bmax , boostCMtoNN );
// Projectile
G4LorentzVector proj4pLAB = projectile.Get4Momentum()/GeV;
G4LightIonQMDGroundStateNucleus* proj(NULL);
if ( projectile.GetDefinition()->GetParticleType() == "nucleus"
|| projectile.GetDefinition()->GetParticleName() == "proton"
|| projectile.GetDefinition()->GetParticleName() == "neutron" )
{
proj_Z = proj_pd->GetAtomicNumber();
proj_A = proj_pd->GetAtomicMass();
proj = new G4LightIonQMDGroundStateNucleus( proj_Z , proj_A );
//proj->ShowParticipants();
meanField->SetSystem ( proj );
if ( proj_A != 1 )
{
proj->SetTotalPotential( meanField->GetTotalPotential() );
proj->CalEnergyAndAngularMomentumInCM();
}
}
// Target
//G4int iz = int ( target.GetZ() );
//G4int ia = int ( target.GetN() );
//migrate to integer A and Z (GetN_asInt returns number of neutrons in the nucleus since this)
G4int iz = int ( target.GetZ_asInt() );
G4int ia = int ( target.GetA_asInt() );
G4LightIonQMDGroundStateNucleus* targ = new G4LightIonQMDGroundStateNucleus( iz , ia );
meanField->SetSystem (targ );
if ( ia != 1 )
{
targ->SetTotalPotential( meanField->GetTotalPotential() );
targ->CalEnergyAndAngularMomentumInCM();
}
//G4LorentzVector targ4p( G4ThreeVector( 0.0 ) , targ->GetNuclearMass()/GeV );
// Boost Vector to CM
//boostToCM = targ4p.findBoostToCM( proj4pLAB );
// Target
for ( G4int i = 0 ; i < targ->GetTotalNumberOfParticipant() ; i++ )
{
G4ThreeVector p0 = targ->GetParticipant( i )->GetMomentum();
G4ThreeVector r0 = targ->GetParticipant( i )->GetPosition();
G4ThreeVector p ( p0.x() + coulomb_collision_px_targ
, p0.y()
, p0.z() * coulomb_collision_gamma_targ + coulomb_collision_pz_targ );
G4ThreeVector r ( r0.x() + coulomb_collision_rx_targ
, r0.y()
, r0.z() / coulomb_collision_gamma_targ + coulomb_collision_rz_targ );
system->SetParticipant( new G4QMDParticipant( targ->GetParticipant( i )->GetDefinition() , p , r ) );
system->GetParticipant( i )->SetTarget();
}
G4LorentzVector proj4pCM = CLHEP::boostOf ( proj4pLAB , boostToReac );
G4LorentzVector targ4pCM = CLHEP::boostOf ( targ4p , boostToReac );
// Projectile
//G4cout << "proj : " << proj << G4endl;
//if ( proj != NULL )
if ( proj_A != 1 )
{
// projectile is nucleus
for ( G4int i = 0 ; i < proj->GetTotalNumberOfParticipant() ; i++ )
{
G4ThreeVector p0 = proj->GetParticipant( i )->GetMomentum();
G4ThreeVector r0 = proj->GetParticipant( i )->GetPosition();
G4ThreeVector p ( p0.x() + coulomb_collision_px_proj
, p0.y()
, p0.z() * coulomb_collision_gamma_proj + coulomb_collision_pz_proj );
G4ThreeVector r ( r0.x() + coulomb_collision_rx_proj
, r0.y()
, r0.z() / coulomb_collision_gamma_proj + coulomb_collision_rz_proj );
system->SetParticipant( new G4QMDParticipant( proj->GetParticipant( i )->GetDefinition() , p , r ) );
system->GetParticipant ( i + targ->GetTotalNumberOfParticipant() )->SetProjectile();
}
}
else
{
// projectile is particle
// avoid multiple set in "elastic" loop
//G4cout << "system Total Participants : " << system->GetTotalNumberOfParticipant() << ", target : " << targ->GetTotalNumberOfParticipant() << G4endl;
if ( system->GetTotalNumberOfParticipant() == targ->GetTotalNumberOfParticipant() )
{
G4int i = targ->GetTotalNumberOfParticipant();
G4ThreeVector p0( 0 );
G4ThreeVector r0( 0 );
G4ThreeVector p ( p0.x() + coulomb_collision_px_proj
, p0.y()
, p0.z() * coulomb_collision_gamma_proj + coulomb_collision_pz_proj );
G4ThreeVector r ( r0.x() + coulomb_collision_rx_proj
, r0.y()
, r0.z() / coulomb_collision_gamma_proj + coulomb_collision_rz_proj );
system->SetParticipant( new G4QMDParticipant( (G4ParticleDefinition*)projectile.GetDefinition() , p , r ) );
// This is not important becase only 1 projectile particle.
system->GetParticipant ( i )->SetProjectile();
}
}
//system->ShowParticipants();
delete targ;
delete proj;
meanField->SetSystem ( system );
collision->SetMeanField ( meanField );
// Time Evolution
//std::cout << "Start time evolution " << std::endl;
//system->ShowParticipants();
for ( G4int i = 0 ; i < maxTime ; i++ )
{
//G4cout << " do Paropagate " << i << " th time step. " << G4endl;
meanField->DoPropagation( deltaT );
//system->ShowParticipants();
collision->CalKinematicsOfBinaryCollisions( deltaT );
//if ( i / 10 * 10 == i )
//{
//G4cout << i << " th time step. " << G4endl;
//system->ShowParticipants();
//}
//system->ShowParticipants();
}
//system->ShowParticipants();
//std::cout << "Doing Cluster Judgment " << std::endl;
nucleuses = meanField->DoClusterJudgment();
// Elastic Judgment
G4int numberOfSecondary = int ( nucleuses.size() ) + system->GetTotalNumberOfParticipant();
G4int sec_a_Z = 0;
G4int sec_a_A = 0;
const G4ParticleDefinition* sec_a_pd = NULL;
G4int sec_b_Z = 0;
G4int sec_b_A = 0;
const G4ParticleDefinition* sec_b_pd = NULL;
if ( numberOfSecondary == 2 )
{
G4bool elasticLike_system = false;
if ( nucleuses.size() == 2 )
{
sec_a_Z = nucleuses[0]->GetAtomicNumber();
sec_a_A = nucleuses[0]->GetMassNumber();
sec_b_Z = nucleuses[1]->GetAtomicNumber();
sec_b_A = nucleuses[1]->GetMassNumber();
if ( ( sec_a_Z == proj_Z && sec_a_A == proj_A && sec_b_Z == targ_Z && sec_b_A == targ_A )
|| ( sec_a_Z == targ_Z && sec_a_A == targ_A && sec_b_Z == proj_Z && sec_b_A == proj_A ) )
{
elasticLike_system = true;
}
}
else if ( nucleuses.size() == 1 )
{
sec_a_Z = nucleuses[0]->GetAtomicNumber();
sec_a_A = nucleuses[0]->GetMassNumber();
sec_b_pd = system->GetParticipant( 0 )->GetDefinition();
if ( ( sec_a_Z == proj_Z && sec_a_A == proj_A && sec_b_pd == targ_pd )
|| ( sec_a_Z == targ_Z && sec_a_A == targ_A && sec_b_pd == proj_pd ) )
{
elasticLike_system = true;
}
}
else
{
sec_a_pd = system->GetParticipant( 0 )->GetDefinition();
sec_b_pd = system->GetParticipant( 1 )->GetDefinition();
if ( ( sec_a_pd == proj_pd && sec_b_pd == targ_pd )
|| ( sec_a_pd == targ_pd && sec_b_pd == proj_pd ) )
{
elasticLike_system = true;
}
// QMD should be inelastic collision, so that nucleon-nucleon collision should also be inelastic in this phase. by Y-H. S and A. H, Mar. 6, 2023.
if ( (proj_pd->GetParticleName() == "proton" && targ_pd->GetParticleName() == "proton")
|| (proj_pd->GetParticleName() == "neutron" && targ_pd->GetParticleName() == "proton")
|| (proj_pd->GetParticleName() == "pi+" && targ_pd->GetParticleName() == "proton")
|| (proj_pd->GetParticleName() == "pi-" && targ_pd->GetParticleName() == "proton"))
{
elasticLike_system = false;
//G4cout << "elasticLike_system = false proton NOCollision " << system->GetNOCollision() << G4endl;
if ( system->GetNOCollision() == 1 || icounter+900 > icounter_max) elastic = false;
}
// Addition -- end
}
if ( elasticLike_system == true )
{
G4bool elasticLike_energy = true;
// Cal ExcitationEnergy
for ( G4int i = 0 ; i < int ( nucleuses.size() ) ; i++ )
{
//meanField->SetSystem( nucleuses[i] );
meanField->SetNucleus( nucleuses[i] );
//nucleuses[i]->SetTotalPotential( meanField->GetTotalPotential() );
//nucleuses[i]->CalEnergyAndAngularMomentumInCM();
if ( nucleuses[i]->GetExcitationEnergy()*GeV > 1.0*MeV ) elasticLike_energy = false;
}
// Check Collision
G4bool withCollision = true;
if ( system->GetNOCollision() == 0 ) withCollision = false;
// Final judegement for Inelasitc or Elastic;
//
// ElasticLike without Collision
//if ( elasticLike_energy == true && withCollision == false ) elastic = true; // ielst = 0
// ElasticLike with Collision
//if ( elasticLike_energy == true && withCollision == true ) elastic = true; // ielst = 1
// InelasticLike without Collision
//if ( elasticLike_energy == false ) elastic = false; // ielst = 2
if ( frag == true )
if ( elasticLike_energy == false ) elastic = false;
// InelasticLike with Collision
if ( elasticLike_energy == false && withCollision == true ) elastic = false; // ielst = 3
}
}
else
{
// numberOfSecondary != 2
elastic = false;
}
//071115
//G4cout << elastic << G4endl;
// if elastic is true try again from sampling of impact parameter
if ( elastic == true )
{
// delete this nucleues
for ( std::vector< G4LightIonQMDNucleus* >::iterator
it = nucleuses.begin() ; it != nucleuses.end() ; it++ )
{
delete *it;
}
nucleuses.clear();
// system->Clear() should be included here. Otherwise, the nucleon is repeatedly regstered if the nucleon is the projectile. by Y-H. S. and A. H, Mar. 6, 2023.
system->Clear();
}
}
// Statical Decay Phase
for ( std::vector< G4LightIonQMDNucleus* >::iterator it
= nucleuses.begin() ; it != nucleuses.end() ; it++ )
{
/*
G4cout << "G4QMDRESULT "
<< (*it)->GetAtomicNumber()
<< " "
<< (*it)->GetMassNumber()
<< " "
<< (*it)->Get4Momentum()
<< " "
<< (*it)->Get4Momentum().vect()
<< " "
<< (*it)->Get4Momentum().restMass()
<< " "
<< (*it)->GetNuclearMass()/GeV
<< G4endl;
*/
meanField->SetNucleus ( *it );
if ( (*it)->GetAtomicNumber() == 0 // neutron cluster
|| (*it)->GetAtomicNumber() == (*it)->GetMassNumber() ) // proton cluster
{
// push back system
for ( G4int i = 0 ; i < (*it)->GetTotalNumberOfParticipant() ; i++ )
{
G4QMDParticipant* aP = new G4QMDParticipant( ( (*it)->GetParticipant( i ) )->GetDefinition() , ( (*it)->GetParticipant( i ) )->GetMomentum() , ( (*it)->GetParticipant( i ) )->GetPosition() );
system->SetParticipant ( aP );
}
continue;
}
G4double nucleus_e = std::sqrt ( G4Pow::GetInstance()->powN ( (*it)->GetNuclearMass()/GeV , 2 ) + G4Pow::GetInstance()->powN ( (*it)->Get4Momentum().vect().mag() , 2 ) );
G4LorentzVector nucleus_p4CM ( (*it)->Get4Momentum().vect() , nucleus_e );
// std::cout << "G4QMDRESULT nucleus deltaQ " << deltaQ << std::endl;
G4int ia = (*it)->GetMassNumber();
G4int iz = (*it)->GetAtomicNumber();
G4LorentzVector lv ( G4ThreeVector( 0.0 ) , (*it)->GetExcitationEnergy()*GeV + G4IonTable::GetIonTable()->GetIonMass( iz , ia ) );
G4Fragment* aFragment = new G4Fragment( ia , iz , lv );
G4ReactionProductVector* rv;
rv = excitationHandler->BreakItUp( *aFragment );
G4bool notBreak = true;
for ( G4ReactionProductVector::iterator itt
= rv->begin() ; itt != rv->end() ; itt++ )
{
notBreak = false;
// Secondary from this nucleus (*it)
const G4ParticleDefinition* pd = (*itt)->GetDefinition();
G4LorentzVector p4 ( (*itt)->GetMomentum()/GeV , (*itt)->GetTotalEnergy()/GeV ); //in nucleus(*it) rest system
G4LorentzVector p4_CM = CLHEP::boostOf( p4 , -nucleus_p4CM.findBoostToCM() ); // Back to CM
G4LorentzVector p4_LAB = CLHEP::boostOf( p4_CM , boostBackToLAB ); // Back to LAB
//090122
//theParticleChange.AddSecondary( dp );
if ( !( pd->GetAtomicNumber() == 4 && pd->GetAtomicMass() == 8 ) )
{
//G4cout << "pd out of notBreak loop : " << pd->GetParticleName() << G4endl;
G4DynamicParticle* dp = new G4DynamicParticle( pd , p4_LAB*GeV );
theParticleChange.AddSecondary( dp );
}
else
{
//Be8 -> Alpha + Alpha + Q
G4ThreeVector randomized_direction( G4UniformRand() , G4UniformRand() , G4UniformRand() );
randomized_direction = randomized_direction.unit();
G4double q_decay = (*itt)->GetMass() - 2*G4Alpha::Alpha()->GetPDGMass();
G4double p_decay = std::sqrt ( G4Pow::GetInstance()->powN(G4Alpha::Alpha()->GetPDGMass()+q_decay/2,2) - G4Pow::GetInstance()->powN(G4Alpha::Alpha()->GetPDGMass() , 2 ) );
G4LorentzVector p4_a1 ( p_decay*randomized_direction , G4Alpha::Alpha()->GetPDGMass()+q_decay/2 ); //in Be8 rest system
G4LorentzVector p4_a1_Be8 = CLHEP::boostOf ( p4_a1/GeV , -p4.findBoostToCM() );
G4LorentzVector p4_a1_CM = CLHEP::boostOf ( p4_a1_Be8 , -nucleus_p4CM.findBoostToCM() );
G4LorentzVector p4_a1_LAB = CLHEP::boostOf ( p4_a1_CM , boostBackToLAB );
G4LorentzVector p4_a2 ( -p_decay*randomized_direction , G4Alpha::Alpha()->GetPDGMass()+q_decay/2 ); //in Be8 rest system
G4LorentzVector p4_a2_Be8 = CLHEP::boostOf ( p4_a2/GeV , -p4.findBoostToCM() );
G4LorentzVector p4_a2_CM = CLHEP::boostOf ( p4_a2_Be8 , -nucleus_p4CM.findBoostToCM() );
G4LorentzVector p4_a2_LAB = CLHEP::boostOf ( p4_a2_CM , boostBackToLAB );
G4DynamicParticle* dp1 = new G4DynamicParticle( G4Alpha::Alpha() , p4_a1_LAB*GeV );
G4DynamicParticle* dp2 = new G4DynamicParticle( G4Alpha::Alpha() , p4_a2_LAB*GeV );
theParticleChange.AddSecondary( dp1 );
theParticleChange.AddSecondary( dp2 );
}
//090122
/*
G4cout
<< "Regist Secondary "
<< (*itt)->GetDefinition()->GetParticleName()
<< " "
<< (*itt)->GetMomentum()/GeV
<< " "
<< (*itt)->GetKineticEnergy()/GeV
<< " "
<< (*itt)->GetMass()/GeV
<< " "
<< (*itt)->GetTotalEnergy()/GeV
<< " "
<< (*itt)->GetTotalEnergy()/GeV * (*itt)->GetTotalEnergy()/GeV
- (*itt)->GetMomentum()/GeV * (*itt)->GetMomentum()/GeV
<< " "
<< nucleus_p4CM.findBoostToCM()
<< " "
<< p4
<< " "
<< p4_CM
<< " "
<< p4_LAB
<< G4endl;
*/
}
if ( notBreak == true )
{
const G4ParticleDefinition* pd = G4IonTable::GetIonTable()->GetIon( (*it)->GetAtomicNumber() , (*it)->GetMassNumber(), (*it)->GetExcitationEnergy()*GeV );
//G4cout << "pd in notBreak loop : " << pd->GetParticleName() << G4endl;
G4LorentzVector p4_CM = nucleus_p4CM;
G4LorentzVector p4_LAB = CLHEP::boostOf( p4_CM , boostBackToLAB ); // Back to LAB
G4DynamicParticle* dp = new G4DynamicParticle( pd , p4_LAB*GeV );
theParticleChange.AddSecondary( dp );
}
for ( G4ReactionProductVector::iterator itt
= rv->begin() ; itt != rv->end() ; itt++ )
{
delete *itt;
}
delete rv;
delete aFragment;
}
for ( G4int i = 0 ; i < system->GetTotalNumberOfParticipant() ; i++ )
{
// Secondary particles
const G4ParticleDefinition* pd = system->GetParticipant( i )->GetDefinition();
G4LorentzVector p4_CM = system->GetParticipant( i )->Get4Momentum();
G4LorentzVector p4_LAB = CLHEP::boostOf( p4_CM , boostBackToLAB );
G4DynamicParticle* dp = new G4DynamicParticle( pd , p4_LAB*GeV );
theParticleChange.AddSecondary( dp );
//G4cout << "In the last theParticleChange loop : " << pd->GetParticleName() << G4endl;
/*
G4cout << "G4QMDRESULT "
<< "r" << i << " " << system->GetParticipant ( i ) -> GetPosition() << " "
<< "p" << i << " " << system->GetParticipant ( i ) -> Get4Momentum()
<< G4endl;
*/
}
for ( std::vector< G4LightIonQMDNucleus* >::iterator it
= nucleuses.begin() ; it != nucleuses.end() ; it++ )
{
delete *it; // delete nulceuse
}
nucleuses.clear();
system->Clear();
delete system;
theParticleChange.SetStatusChange( stopAndKill );
for (G4int i = 0; i < G4int(theParticleChange.GetNumberOfSecondaries() ); i++)
{
//G4cout << "Particle : " << theParticleChange.GetSecondary(i)->GetParticle()->GetParticleDefinition()->GetParticleName() << G4endl;
//G4cout << "KEnergy : " << theParticleChange.GetSecondary(i)->GetParticle()->GetKineticEnergy() << G4endl;
//G4cout << "modelID : " << theParticleChange.GetSecondary(i)->GetCreatorModelID() << G4endl;
theParticleChange.GetSecondary(i)->SetCreatorModelID(secID);
}
return &theParticleChange;
}
void G4LightIonQMDReaction::calcOffSetOfCollision( G4double b ,
const G4ParticleDefinition* pd_proj ,
const G4ParticleDefinition* pd_targ ,
G4double ptot , G4double etot , G4double bmax , G4ThreeVector boostToCM )
{
G4double mass_proj = pd_proj->GetPDGMass()/GeV;
G4double mass_targ = pd_targ->GetPDGMass()/GeV;
G4double stot = std::sqrt ( etot*etot - ptot*ptot );
G4double pstt = std::sqrt ( ( stot*stot - ( mass_proj + mass_targ ) * ( mass_proj + mass_targ )
) * ( stot*stot - ( mass_proj - mass_targ ) * ( mass_proj - mass_targ ) ) )
/ ( 2.0 * stot );
G4double pzcc = pstt;
G4double eccm = stot - ( mass_proj + mass_targ );
G4int zp = 1;
G4int ap = 1;
if ( pd_proj->GetParticleType() == "nucleus" )
{
zp = pd_proj->GetAtomicNumber();
ap = pd_proj->GetAtomicMass();
}
else
{
// proton, neutron, mesons
zp = int ( pd_proj->GetPDGCharge()/eplus + 0.5 );
// ap = 1;
}
G4int zt = pd_targ->GetAtomicNumber();
G4int at = pd_targ->GetAtomicMass();
// Check the ramx0 value
//G4double rmax0 = 8.0; // T.K dicide parameter value // for low energy
G4double rmax0 = bmax + 4.0;
G4double rmax = std::sqrt( rmax0*rmax0 + b*b );
G4double ccoul = 0.001439767;
G4double pcca = 1.0 - double ( zp * zt ) * ccoul / eccm / rmax - ( b / rmax )*( b / rmax );
G4double pccf = std::sqrt( pcca );
//Fix for neutral particles
G4double aas1 = 0.0;
G4double bbs = 0.0;
if ( zp != 0 )
{
G4double aas = 2.0 * eccm * b / double ( zp * zt ) / ccoul;
bbs = 1.0 / std::sqrt ( 1.0 + aas*aas );
aas1 = ( 1.0 + aas * b / rmax ) * bbs;
}
G4double cost = 0.0;
G4double sint = 0.0;
G4double thet1 = 0.0;
G4double thet2 = 0.0;
if ( 1.0 - aas1*aas1 <= 0 || 1.0 - bbs*bbs <= 0.0 )
{
cost = 1.0;
sint = 0.0;
}
else
{
G4double aat1 = aas1 / std::sqrt ( 1.0 - aas1*aas1 );
G4double aat2 = bbs / std::sqrt ( 1.0 - bbs*bbs );
thet1 = std::atan ( aat1 );
thet2 = std::atan ( aat2 );
// TK enter to else block
G4double theta = thet1 - thet2;
cost = std::cos( theta );
sint = std::sin( theta );
}
G4double rzpr = -rmax * cost * ( mass_targ ) / ( mass_proj + mass_targ );
G4double rzta = rmax * cost * ( mass_proj ) / ( mass_proj + mass_targ );
G4double rxpr = rmax / 2.0 * sint;
G4double rxta = -rxpr;
G4double pzpc = pzcc * ( cost * pccf + sint * b / rmax );
G4double pxpr = pzcc * ( -sint * pccf + cost * b / rmax );
G4double pztc = - pzpc;
G4double pxta = - pxpr;
G4double epc = std::sqrt ( pzpc*pzpc + pxpr*pxpr + mass_proj*mass_proj );
G4double etc = std::sqrt ( pztc*pztc + pxta*pxta + mass_targ*mass_targ );
G4double pzpr = pzpc;
G4double pzta = pztc;
G4double epr = epc;
G4double eta = etc;
// CM -> NN
G4double gammacm = boostToCM.gamma();
//G4double betacm = -boostToCM.beta();
G4double betacm = boostToCM.z();
pzpr = pzpc + betacm * gammacm * ( gammacm / ( 1. + gammacm ) * pzpc * betacm + epc );
pzta = pztc + betacm * gammacm * ( gammacm / ( 1. + gammacm ) * pztc * betacm + etc );
epr = gammacm * ( epc + betacm * pzpc );
eta = gammacm * ( etc + betacm * pztc );
//G4double betpr = pzpr / epr;
//G4double betta = pzta / eta;
G4double gammpr = epr / ( mass_proj );
G4double gammta = eta / ( mass_targ );
pzta = pzta / double ( at );
pxta = pxta / double ( at );
pzpr = pzpr / double ( ap );
pxpr = pxpr / double ( ap );
G4double zeroz = 0.0;
rzpr = rzpr -zeroz;
rzta = rzta -zeroz;
// Set results
coulomb_collision_gamma_proj = gammpr;
coulomb_collision_rx_proj = rxpr;
coulomb_collision_rz_proj = rzpr;
coulomb_collision_px_proj = pxpr;
coulomb_collision_pz_proj = pzpr;
coulomb_collision_gamma_targ = gammta;
coulomb_collision_rx_targ = rxta;
coulomb_collision_rz_targ = rzta;
coulomb_collision_px_targ = pxta;
coulomb_collision_pz_targ = pzta;
}
void G4LightIonQMDReaction::setEvaporationCh()
{
//fEvaporation - 8 default channels
//fCombined - 8 default + 60 GEM
//fGEM - 2 default + 66 GEM
G4DeexChannelType ctype = gem ? fGEM : fCombined;
excitationHandler->SetDeexChannelsType(ctype);
}
void G4LightIonQMDReaction::ModelDescription(std::ostream& outFile) const
{
outFile << "Lorentz covarianted Quantum Molecular Dynamics model for nucleus (particle) vs nucleus reactions\n";
}
@@ -568,8 +568,6 @@ std::vector< G4QMDNucleus* > G4QMDMeanField::DoClusterJudgment()
}
// identification of the cluster
std::map < G4int , std::vector < G4int > > cluster_map;
std::vector < G4bool > is_already_belong_some_cluster;
// cluster_id participant_id
@@ -669,11 +667,11 @@ std::vector< G4QMDNucleus* > G4QMDMeanField::DoClusterJudgment()
if ( it->first == target_cluster_id )
{
is_assigned_to [ it->second ] = is_assigned_to [ j ];
clusters_tmp.insert ( std::multimap<G4int,G4int>::value_type ( is_assigned_to [ j ] , it->second ) );
clusters_tmp.insert(std::multimap<G4int,G4int>::value_type(is_assigned_to[j], it->second));
}
else
{
clusters_tmp.insert ( std::multimap<G4int,G4int>::value_type ( it->first , it->second ) );
clusters_tmp.insert(std::multimap<G4int,G4int>::value_type(it->first, it->second));
}
}
clusters = clusters_tmp;
@@ -699,12 +697,6 @@ std::vector< G4QMDNucleus* > G4QMDMeanField::DoClusterJudgment()
++ichek;
}
}
if ( cluster_participants.size() > 0 )
{
// cluster , participant
cluster_map.insert ( std::pair(i, cluster_participants) );
}
}
}
if ( hasThisCompany == true ) { ++cluster_id; }
@@ -77,13 +77,7 @@ G4QMDReaction::G4QMDReaction()
meanField = new G4QMDMeanField();
collision = new G4QMDCollision();
excitationHandler = new G4ExcitationHandler;
excitationHandler->SetDeexChannelsType( fCombined );
//fEvaporation - 8 default channels
//fCombined - 8 default + 60 GEM
//fGEM - 2 default + 66 GEM
evaporation = new G4Evaporation;
excitationHandler->SetEvaporation( evaporation );
excitationHandler = new G4ExcitationHandler();
setEvaporationCh();
coulomb_collision_gamma_proj = 0.0;
@@ -104,7 +98,6 @@ G4QMDReaction::G4QMDReaction()
G4QMDReaction::~G4QMDReaction()
{
delete evaporation;
delete excitationHandler;
delete collision;
delete meanField;
@@ -837,16 +830,13 @@ G4double ptot , G4double etot , G4double bmax , G4ThreeVector boostToCM )
}
void G4QMDReaction::setEvaporationCh()
{
if ( gem == true )
evaporation->SetGEMChannel();
else
evaporation->SetDefaultChannel();
//fEvaporation - 8 default channels
//fCombined - 8 default + 60 GEM
//fGEM - 2 default + 66 GEM
G4DeexChannelType ctype = gem ? fGEM : fCombined;
excitationHandler->SetDeexChannelsType(ctype);
}
void G4QMDReaction::ModelDescription(std::ostream& outFile) const