950 lines
36 KiB
C++
950 lines
36 KiB
C++
//
|
|
// ********************************************************************
|
|
// * License and Disclaimer *
|
|
// * *
|
|
// * The Geant4 software is copyright of the Copyright Holders of *
|
|
// * the Geant4 Collaboration. It is provided under the terms and *
|
|
// * conditions of the Geant4 Software License, included in the file *
|
|
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
|
// * include a list of copyright holders. *
|
|
// * *
|
|
// * Neither the authors of this software system, nor their employing *
|
|
// * institutes,nor the agencies providing financial support for this *
|
|
// * work make any representation or warranty, express or implied, *
|
|
// * regarding this software system or assume any liability for its *
|
|
// * use. Please see the license in the file LICENSE and URL above *
|
|
// * for the full disclaimer and the limitation of liability. *
|
|
// * *
|
|
// * This code implementation is the result of the scientific and *
|
|
// * technical work of the GEANT4 collaboration. *
|
|
// * By using, copying, modifying or distributing the software (or *
|
|
// * any work based on the software) you agree to acknowledge its *
|
|
// * use in resulting scientific publications, and indicate your *
|
|
// * acceptance of all terms of the Geant4 Software license. *
|
|
// ********************************************************************
|
|
//
|
|
//
|
|
// ------------------------------------------------------------
|
|
// GEANT 4 class implementation file
|
|
// ------------------------------------------------------------
|
|
//
|
|
|
|
#include <iomanip>
|
|
|
|
#include "G4PhysicalConstants.hh"
|
|
#include "G4SystemOfUnits.hh"
|
|
#include "G4Field.hh"
|
|
#include "G4FieldManager.hh"
|
|
#include "G4TransportationManager.hh"
|
|
#include "G4GeometryTolerance.hh"
|
|
#include "G4Material.hh"
|
|
#include "G4ErrorPropagatorData.hh"
|
|
#include "G4ErrorFreeTrajState.hh"
|
|
#include "G4ErrorFreeTrajParam.hh"
|
|
#include "G4ErrorSurfaceTrajState.hh"
|
|
#include "G4ErrorMatrix.hh"
|
|
|
|
//------------------------------------------------------------------------
|
|
G4ErrorFreeTrajState::G4ErrorFreeTrajState(const G4String& partName,
|
|
const G4Point3D& pos,
|
|
const G4Vector3D& mom,
|
|
const G4ErrorTrajErr& errmat)
|
|
: G4ErrorTrajState(partName, pos, mom, errmat)
|
|
{
|
|
fTrajParam = G4ErrorFreeTrajParam(pos, mom);
|
|
Init();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
G4ErrorFreeTrajState::G4ErrorFreeTrajState(const G4ErrorSurfaceTrajState& tpSD)
|
|
: G4ErrorTrajState(tpSD.GetParticleType(), tpSD.GetPosition(),
|
|
tpSD.GetMomentum())
|
|
{
|
|
// G4ThreeVector planeNormal = tpSD.GetPlaneNormal();
|
|
// G4double fPt = tpSD.GetMomentum()*planeNormal;//mom projected on normal to
|
|
// plane G4ErrorSurfaceTrajParam tpSDparam = tpSD.GetParameters();
|
|
// G4ThreeVector Psc = fPt * planeNormal +
|
|
// tpSDparam.GetPU()*tpSDparam.GetVectorU() + tpSD.GetPV()*tpSD.GetVectorW();
|
|
|
|
fTrajParam = G4ErrorFreeTrajParam(fPosition, fMomentum);
|
|
Init();
|
|
|
|
//----- Get the error matrix in SC coordinates
|
|
G4ErrorSurfaceTrajParam tpSDparam = tpSD.GetParameters();
|
|
G4double mom = fMomentum.mag();
|
|
G4double mom2 = fMomentum.mag2();
|
|
G4double TVW1 =
|
|
std::sqrt(mom2 / (mom2 + tpSDparam.GetPV() * tpSDparam.GetPV() +
|
|
tpSDparam.GetPW() * tpSDparam.GetPW()));
|
|
G4ThreeVector vTVW(TVW1, tpSDparam.GetPV() / mom * TVW1,
|
|
tpSDparam.GetPW() / mom * TVW1);
|
|
G4Vector3D vectorU = tpSDparam.GetVectorV().cross(tpSDparam.GetVectorW());
|
|
G4Vector3D vTN = vTVW.x() * vectorU + vTVW.y() * tpSDparam.GetVectorV() +
|
|
vTVW.z() * tpSDparam.GetVectorW();
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 5)
|
|
{
|
|
G4double pc2 = std::asin(vTN.z());
|
|
G4double pc3 = std::atan(vTN.y() / vTN.x());
|
|
|
|
G4cout << " CHECK: pc2 " << pc2 << " = " << GetParameters().GetLambda()
|
|
<< " diff " << pc2 - GetParameters().GetLambda() << G4endl;
|
|
G4cout << " CHECK: pc3 " << pc3 << " = " << GetParameters().GetPhi()
|
|
<< " diff " << pc3 - GetParameters().GetPhi() << G4endl;
|
|
}
|
|
#endif
|
|
|
|
//--- Get the unit vectors perp to P
|
|
G4double cosl = std::cos(GetParameters().GetLambda());
|
|
if(cosl < 1.E-30)
|
|
cosl = 1.E-30;
|
|
G4double cosl1 = 1. / cosl;
|
|
G4Vector3D vUN(-vTN.y() * cosl1, vTN.x() * cosl1, 0.);
|
|
G4Vector3D vVN(-vTN.z() * vUN.y(), vTN.z() * vUN.x(), cosl);
|
|
|
|
G4Vector3D vUperp = G4Vector3D(-fMomentum.y(), fMomentum.x(), 0.);
|
|
G4Vector3D vVperp = vUperp.cross(fMomentum);
|
|
vUperp *= 1. / vUperp.mag();
|
|
vVperp *= 1. / vVperp.mag();
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 5)
|
|
{
|
|
G4cout << " CHECK: vUN " << vUN << " = " << vUperp << " diff "
|
|
<< (vUN - vUperp).mag() << G4endl;
|
|
G4cout << " CHECK: vVN " << vVN << " = " << vVperp << " diff "
|
|
<< (vVN - vVperp).mag() << G4endl;
|
|
}
|
|
#endif
|
|
|
|
// get the dot products of vectors perpendicular to direction and vector
|
|
// defining SD plane
|
|
G4double dUU = vUperp * tpSD.GetVectorV();
|
|
G4double dUV = vUperp * tpSD.GetVectorW();
|
|
G4double dVU = vVperp * tpSD.GetVectorV();
|
|
G4double dVV = vVperp * tpSD.GetVectorW();
|
|
|
|
//--- Get transformation first
|
|
G4ErrorMatrix transfM(5, 5, 1);
|
|
//--- Get magnetic field
|
|
const G4Field* field = G4TransportationManager::GetTransportationManager()
|
|
->GetFieldManager()
|
|
->GetDetectorField();
|
|
G4ThreeVector dir = fTrajParam.GetDirection();
|
|
G4double invCosTheta = 1. / std::cos(dir.theta());
|
|
G4cout << " dir=" << dir << " invCosTheta " << invCosTheta << G4endl;
|
|
|
|
if(fCharge != 0 && field)
|
|
{
|
|
G4double pos1[3];
|
|
pos1[0] = fPosition.x() * cm;
|
|
pos1[1] = fPosition.y() * cm;
|
|
pos1[2] = fPosition.z() * cm;
|
|
G4double h1[3];
|
|
field->GetFieldValue(pos1, h1);
|
|
G4ThreeVector HPre = G4ThreeVector(h1[0], h1[1], h1[2]) / tesla * 10.;
|
|
G4double magHPre = HPre.mag();
|
|
G4double invP = 1. / fMomentum.mag();
|
|
G4double magHPreM = magHPre * invP;
|
|
if(magHPre != 0.)
|
|
{
|
|
G4double magHPreM2 = fCharge / magHPre;
|
|
|
|
G4double Q = -magHPreM * c_light;
|
|
G4double sinz = -HPre * vUperp * magHPreM2;
|
|
G4double cosz = HPre * vVperp * magHPreM2;
|
|
|
|
transfM[1][3] = -Q * dir.y() * sinz;
|
|
transfM[1][4] = -Q * dir.z() * sinz;
|
|
transfM[2][3] = -Q * dir.y() * cosz * invCosTheta;
|
|
transfM[2][4] = -Q * dir.z() * cosz * invCosTheta;
|
|
}
|
|
}
|
|
|
|
transfM[0][0] = 1.;
|
|
transfM[1][1] = dir.x() * dVU;
|
|
transfM[1][2] = dir.x() * dVV;
|
|
transfM[2][1] = dir.x() * dUU * invCosTheta;
|
|
transfM[2][2] = dir.x() * dUV * invCosTheta;
|
|
transfM[3][3] = dUU;
|
|
transfM[3][4] = dUV;
|
|
transfM[4][3] = dVU;
|
|
transfM[4][4] = dVV;
|
|
|
|
fError = G4ErrorTrajErr(tpSD.GetError().similarity(transfM));
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 1)
|
|
G4cout << "error matrix SD2SC " << fError << G4endl;
|
|
if(iverbose >= 4)
|
|
G4cout << "G4ErrorFreeTrajState from SD " << *this << G4endl;
|
|
#endif
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void G4ErrorFreeTrajState::Init()
|
|
{
|
|
theTSType = G4eTS_FREE;
|
|
BuildCharge();
|
|
theTransfMat = G4ErrorMatrix(5, 5, 0);
|
|
theFirstStep = true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void G4ErrorFreeTrajState::Dump(std::ostream& out) const { out << *this; }
|
|
|
|
//------------------------------------------------------------------------
|
|
G4int G4ErrorFreeTrajState::Update(const G4Track* aTrack)
|
|
{
|
|
G4int ierr = 0;
|
|
fTrajParam.Update(aTrack);
|
|
UpdatePosMom(aTrack->GetPosition(), aTrack->GetMomentum());
|
|
return ierr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
std::ostream& operator<<(std::ostream& out, const G4ErrorFreeTrajState& ts)
|
|
{
|
|
std::ios::fmtflags orig_flags = out.flags();
|
|
|
|
out.setf(std::ios::fixed, std::ios::floatfield);
|
|
|
|
ts.DumpPosMomError(out);
|
|
|
|
out << " G4ErrorFreeTrajState: Params: " << ts.fTrajParam << G4endl;
|
|
|
|
out.flags(orig_flags);
|
|
|
|
return out;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
G4int G4ErrorFreeTrajState::PropagateError(const G4Track* aTrack)
|
|
{
|
|
G4double stepLengthCm = aTrack->GetStep()->GetStepLength() / cm;
|
|
if(G4ErrorPropagatorData::GetErrorPropagatorData()->GetStage() ==
|
|
G4ErrorStage_Deflation)
|
|
stepLengthCm *= -1.;
|
|
|
|
G4double kCarTolerance =
|
|
G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
|
|
|
|
if(std::fabs(stepLengthCm) <= kCarTolerance / cm)
|
|
return 0;
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << " G4ErrorFreeTrajState::PropagateError " << G4endl;
|
|
G4cout << "G4EP: iverbose=" << iverbose << G4endl;
|
|
#endif
|
|
|
|
// * *** ERROR PROPAGATION ON A HELIX ASSUMING SC VARIABLES
|
|
G4Point3D vposPost = aTrack->GetPosition() / cm;
|
|
G4Vector3D vpPost = aTrack->GetMomentum() / GeV;
|
|
// G4Point3D vposPre = fPosition/cm;
|
|
// G4Vector3D vpPre = fMomentum/GeV;
|
|
G4Point3D vposPre = aTrack->GetStep()->GetPreStepPoint()->GetPosition() / cm;
|
|
G4Vector3D vpPre = aTrack->GetStep()->GetPreStepPoint()->GetMomentum() / GeV;
|
|
// correct to avoid propagation along Z
|
|
if(vpPre.mag() == vpPre.z())
|
|
vpPre.setX(1.E-6 * MeV);
|
|
if(vpPost.mag() == vpPost.z())
|
|
vpPost.setX(1.E-6 * MeV);
|
|
|
|
G4double pPre = vpPre.mag();
|
|
G4double pPost = vpPost.mag();
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
{
|
|
G4cout << "G4EP: vposPre " << vposPre << G4endl << "G4EP: vposPost "
|
|
<< vposPost << G4endl;
|
|
G4cout << "G4EP: vpPre " << vpPre << G4endl << "G4EP: vpPost " << vpPost
|
|
<< G4endl;
|
|
G4cout << " err start step " << fError << G4endl;
|
|
G4cout << "G4EP: stepLengthCm " << stepLengthCm << G4endl;
|
|
}
|
|
#endif
|
|
|
|
if(pPre == 0. || pPost == 0)
|
|
return 2;
|
|
G4double pInvPre = 1. / pPre;
|
|
G4double pInvPost = 1. / pPost;
|
|
G4double deltaPInv = pInvPost - pInvPre;
|
|
if(iverbose >= 2)
|
|
G4cout << "G4EP: pInvPre" << pInvPre << " pInvPost:" << pInvPost
|
|
<< " deltaPInv:" << deltaPInv << G4endl;
|
|
|
|
G4Vector3D vpPreNorm = vpPre * pInvPre;
|
|
G4Vector3D vpPostNorm = vpPost * pInvPost;
|
|
if(iverbose >= 2)
|
|
G4cout << "G4EP: vpPreNorm " << vpPreNorm << " vpPostNorm " << vpPostNorm
|
|
<< G4endl;
|
|
// return if propagation along Z??
|
|
if(1. - std::fabs(vpPreNorm.z()) < kCarTolerance)
|
|
return 4;
|
|
if(1. - std::fabs(vpPostNorm.z()) < kCarTolerance)
|
|
return 4;
|
|
G4double sinpPre =
|
|
std::sin(vpPreNorm.theta()); // cosine perpendicular to pPre = sine pPre
|
|
G4double sinpPost =
|
|
std::sin(vpPostNorm.theta()); // cosine perpendicular to pPost = sine pPost
|
|
G4double sinpPostInv = 1. / std::sin(vpPostNorm.theta());
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << "G4EP: cosl " << sinpPre << " cosl0 " << sinpPost << G4endl;
|
|
#endif
|
|
//* *** DEFINE TRANSFORMATION MATRIX BETWEEN X1 AND X2 FOR
|
|
//* *** NEUTRAL PARTICLE OR FIELDFREE REGION
|
|
G4ErrorMatrix transf(5, 5, 0);
|
|
|
|
transf[3][2] = stepLengthCm * sinpPost;
|
|
transf[4][1] = stepLengthCm;
|
|
for(auto ii = 0; ii < 5; ++ii)
|
|
{
|
|
transf[ii][ii] = 1.;
|
|
}
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
{
|
|
G4cout << "G4EP: transf matrix neutral " << transf;
|
|
}
|
|
#endif
|
|
|
|
// charge X propagation direction
|
|
G4double charge = aTrack->GetDynamicParticle()->GetCharge();
|
|
if(G4ErrorPropagatorData::GetErrorPropagatorData()->GetMode() ==
|
|
G4ErrorMode_PropBackwards)
|
|
{
|
|
charge *= -1.;
|
|
}
|
|
// G4cout << " charge " << charge << G4endl;
|
|
// t check if particle has charge
|
|
// t if( charge == 0 ) goto 45;
|
|
// check if the magnetic field is = 0.
|
|
|
|
// position is from geant4, it is assumed to be in mm (for debugging,
|
|
// eventually it will not be transformed) it is assumed vposPre[] is in cm and
|
|
// pos1[] is in mm.
|
|
G4double pos1[3];
|
|
pos1[0] = vposPre.x() * cm;
|
|
pos1[1] = vposPre.y() * cm;
|
|
pos1[2] = vposPre.z() * cm;
|
|
G4double pos2[3];
|
|
pos2[0] = vposPost.x() * cm;
|
|
pos2[1] = vposPost.y() * cm;
|
|
pos2[2] = vposPost.z() * cm;
|
|
G4double h1[3], h2[3];
|
|
|
|
const G4Field* field = G4TransportationManager::GetTransportationManager()
|
|
->GetFieldManager()
|
|
->GetDetectorField();
|
|
if(!field)
|
|
return 0; // goto 45
|
|
|
|
// calculate transformation except it NEUTRAL PARTICLE OR FIELDFREE REGION
|
|
if(charge != 0. && field)
|
|
{
|
|
field->GetFieldValue(pos1,
|
|
h1); // here pos1[], pos2[] are in mm, not changed
|
|
field->GetFieldValue(pos2, h2);
|
|
G4ThreeVector HPre =
|
|
G4ThreeVector(h1[0], h1[1], h1[2]) / tesla *
|
|
10.; // 10. is to get same dimensions as GEANT3 (kilogauss)
|
|
G4ThreeVector HPost = G4ThreeVector(h2[0], h2[1], h2[2]) / tesla * 10.;
|
|
G4double magHPre = HPre.mag();
|
|
G4double magHPost = HPost.mag();
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
{
|
|
G4cout << "G4EP: h1 = " << h1[0] << ", " << h1[1] << ", " << h1[2]
|
|
<< G4endl;
|
|
G4cout << "G4EP: pos1/mm = " << pos1[0] << ", " << pos1[1] << ", "
|
|
<< pos1[2] << G4endl;
|
|
G4cout << "G4EP: pos2/mm = " << pos2[0] << ", " << pos2[1] << ", "
|
|
<< pos2[2] << G4endl;
|
|
G4cout << "G4EP: B-filed in KGauss HPre " << HPre << G4endl
|
|
<< "G4EP: in KGauss HPost " << HPost << G4endl;
|
|
}
|
|
#endif
|
|
|
|
if(magHPre + magHPost != 0.)
|
|
{
|
|
//* *** CHECK WHETHER H*ALFA/P IS TOO DIFFERENT AT X1 AND X2
|
|
G4double gam;
|
|
if(magHPost != 0.)
|
|
{
|
|
gam = HPost * vpPostNorm / magHPost;
|
|
}
|
|
else
|
|
{
|
|
gam = HPre * vpPreNorm / magHPre;
|
|
}
|
|
|
|
// G4eMagneticLimitsProcess will limit the step, but based on an straight
|
|
// line trajectory
|
|
G4double alphaSqr = 1. - gam * gam;
|
|
G4double diffHSqr = (HPre * pInvPre - HPost * pInvPost).mag2();
|
|
G4double delhp6Sqr = 300. * 300.;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
{
|
|
G4cout << " G4EP: gam " << gam << " alphaSqr " << alphaSqr
|
|
<< " diffHSqr " << diffHSqr << G4endl;
|
|
G4cout << " alpha= " << std::sqrt(alphaSqr) << G4endl;
|
|
}
|
|
#endif
|
|
if(diffHSqr * alphaSqr > delhp6Sqr)
|
|
return 3;
|
|
|
|
//* *** DEFINE AVERAGE MAGNETIC FIELD AND GRADIENT
|
|
G4double pInvAver = 1. / (pInvPre + pInvPost);
|
|
G4double CFACT8 = 2.997925E-4;
|
|
// G4double HAver
|
|
G4ThreeVector vHAverNorm((HPre * pInvPre + HPost * pInvPost) * pInvAver *
|
|
charge * CFACT8);
|
|
G4double HAver = vHAverNorm.mag();
|
|
G4double invHAver = 1. / HAver;
|
|
vHAverNorm *= invHAver;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << " G4EP: HaverNorm " << vHAverNorm << " magHAver " << HAver
|
|
<< " charge " << charge << G4endl;
|
|
#endif
|
|
|
|
G4double pAver = (pPre + pPost) * 0.5;
|
|
G4double QAver = -HAver / pAver;
|
|
G4double thetaAver = QAver * stepLengthCm;
|
|
G4double sinThetaAver = std::sin(thetaAver);
|
|
G4double cosThetaAver = std::cos(thetaAver);
|
|
G4double gamma = vHAverNorm * vpPostNorm;
|
|
G4ThreeVector AN2 = vHAverNorm.cross(vpPostNorm);
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << " G4EP: AN2 " << AN2 << " gamma:" << gamma
|
|
<< " theta=" << thetaAver << G4endl;
|
|
#endif
|
|
G4double AU = 1. / vpPreNorm.perp();
|
|
// t G4ThreeVector vU( vpPreNorm.cross( G4ThreeVector(0.,0.,1.) ) * AU );
|
|
G4ThreeVector vUPre(-AU * vpPreNorm.y(), AU * vpPreNorm.x(), 0.);
|
|
G4ThreeVector vVPre(-vpPreNorm.z() * vUPre.y(), vpPreNorm.z() * vUPre.x(),
|
|
vpPreNorm.x() * vUPre.y() -
|
|
vpPreNorm.y() * vUPre.x());
|
|
|
|
//
|
|
AU = 1. / vpPostNorm.perp();
|
|
// t G4ThreeVector vU( vpPostNorm.cross( G4ThreeVector(0.,0.,1.) ) * AU
|
|
// );
|
|
G4ThreeVector vUPost(-AU * vpPostNorm.y(), AU * vpPostNorm.x(), 0.);
|
|
G4ThreeVector vVPost(
|
|
-vpPostNorm.z() * vUPost.y(), vpPostNorm.z() * vUPost.x(),
|
|
vpPostNorm.x() * vUPost.y() - vpPostNorm.y() * vUPost.x());
|
|
#ifdef G4EVERBOSE
|
|
G4cout << " vpPostNorm " << vpPostNorm << G4endl;
|
|
if(iverbose >= 2)
|
|
G4cout << " G4EP: AU " << AU << " vUPre " << vUPre << " vVPre " << vVPre
|
|
<< " vUPost " << vUPost << " vVPost " << vVPost << G4endl;
|
|
#endif
|
|
G4Point3D deltaPos(vposPre - vposPost);
|
|
|
|
// * *** COMPLETE TRANSFORMATION MATRIX BETWEEN ERRORS AT X1 AND X2
|
|
// * *** FIELD GRADIENT PERPENDICULAR TO TRACK IS PRESENTLY NOT
|
|
// * *** TAKEN INTO ACCOUNT
|
|
|
|
G4double QP = QAver * pAver; // = -HAver
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << " G4EP: QP " << QP << " QAver " << QAver << " pAver " << pAver
|
|
<< G4endl;
|
|
#endif
|
|
G4double ANV =
|
|
-(vHAverNorm.x() * vUPost.x() + vHAverNorm.y() * vUPost.y());
|
|
G4double ANU =
|
|
(vHAverNorm.x() * vVPost.x() + vHAverNorm.y() * vVPost.y() +
|
|
vHAverNorm.z() * vVPost.z());
|
|
G4double OMcosThetaAver = 1. - cosThetaAver;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << "G4EP: OMcosThetaAver " << OMcosThetaAver << " cosThetaAver "
|
|
<< cosThetaAver << " thetaAver " << thetaAver << " QAver "
|
|
<< QAver << " stepLengthCm " << stepLengthCm << G4endl;
|
|
#endif
|
|
G4double TMSINT = thetaAver - sinThetaAver;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << " G4EP: ANV " << ANV << " ANU " << ANU << G4endl;
|
|
#endif
|
|
|
|
G4ThreeVector vHUPre(
|
|
-vHAverNorm.z() * vUPre.y(), vHAverNorm.z() * vUPre.x(),
|
|
vHAverNorm.x() * vUPre.y() - vHAverNorm.y() * vUPre.x());
|
|
#ifdef G4EVERBOSE
|
|
// if( iverbose >= 2 ) G4cout << "G4EP: HUPre(1) " << vHUPre.x() << " "
|
|
// << vHAverNorm.z() << " " << vUPre.y() << G4endl;
|
|
#endif
|
|
G4ThreeVector vHVPre(
|
|
vHAverNorm.y() * vVPre.z() - vHAverNorm.z() * vVPre.y(),
|
|
vHAverNorm.z() * vVPre.x() - vHAverNorm.x() * vVPre.z(),
|
|
vHAverNorm.x() * vVPre.y() - vHAverNorm.y() * vVPre.x());
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << " G4EP: HUPre " << vHUPre << " HVPre " << vHVPre << G4endl;
|
|
#endif
|
|
|
|
//------------------- COMPUTE MATRIX
|
|
//---------- 1/P
|
|
|
|
transf[0][0] =
|
|
1. -
|
|
deltaPInv * pAver *
|
|
(1. + (vpPostNorm.x() * deltaPos.x() + vpPostNorm.y() * deltaPos.y() +
|
|
vpPostNorm.z() * deltaPos.z()) /
|
|
stepLengthCm) +
|
|
2. * deltaPInv * pAver;
|
|
|
|
transf[0][1] =
|
|
-deltaPInv / thetaAver *
|
|
(TMSINT * gamma *
|
|
(vHAverNorm.x() * vVPre.x() + vHAverNorm.y() * vVPre.y() +
|
|
vHAverNorm.z() * vVPre.z()) +
|
|
sinThetaAver *
|
|
(vVPre.x() * vpPostNorm.x() + vVPre.y() * vpPostNorm.y() +
|
|
vVPre.z() * vpPostNorm.z()) +
|
|
OMcosThetaAver *
|
|
(vHVPre.x() * vpPostNorm.x() + vHVPre.y() * vpPostNorm.y() +
|
|
vHVPre.z() * vpPostNorm.z()));
|
|
|
|
transf[0][2] =
|
|
-sinpPre * deltaPInv / thetaAver *
|
|
(TMSINT * gamma *
|
|
(vHAverNorm.x() * vUPre.x() + vHAverNorm.y() * vUPre.y()) +
|
|
sinThetaAver *
|
|
(vUPre.x() * vpPostNorm.x() + vUPre.y() * vpPostNorm.y()) +
|
|
OMcosThetaAver *
|
|
(vHUPre.x() * vpPostNorm.x() + vHUPre.y() * vpPostNorm.y() +
|
|
vHUPre.z() * vpPostNorm.z()));
|
|
|
|
transf[0][3] = -deltaPInv / stepLengthCm *
|
|
(vUPre.x() * vpPostNorm.x() + vUPre.y() * vpPostNorm.y());
|
|
|
|
transf[0][4] = -deltaPInv / stepLengthCm *
|
|
(vVPre.x() * vpPostNorm.x() + vVPre.y() * vpPostNorm.y() +
|
|
vVPre.z() * vpPostNorm.z());
|
|
|
|
// *** Lambda
|
|
transf[1][0] =
|
|
-QP * ANV *
|
|
(vpPostNorm.x() * deltaPos.x() + vpPostNorm.y() * deltaPos.y() +
|
|
vpPostNorm.z() * deltaPos.z()) *
|
|
(1. + deltaPInv * pAver);
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 3)
|
|
G4cout << "ctransf10= " << transf[1][0] << " " << -QP << " " << ANV
|
|
<< " " << vpPostNorm.x() << " " << deltaPos.x() << " "
|
|
<< vpPostNorm.y() << " " << deltaPos.y() << " " << vpPostNorm.z()
|
|
<< " " << deltaPos.z() << " " << deltaPInv << " " << pAver
|
|
<< G4endl;
|
|
#endif
|
|
|
|
transf[1][1] =
|
|
cosThetaAver * (vVPre.x() * vVPost.x() + vVPre.y() * vVPost.y() +
|
|
vVPre.z() * vVPost.z()) +
|
|
sinThetaAver * (vHVPre.x() * vVPost.x() + vHVPre.y() * vVPost.y() +
|
|
vHVPre.z() * vVPost.z()) +
|
|
OMcosThetaAver *
|
|
(vHAverNorm.x() * vVPre.x() + vHAverNorm.y() * vVPre.y() +
|
|
vHAverNorm.z() * vVPre.z()) *
|
|
(vHAverNorm.x() * vVPost.x() + vHAverNorm.y() * vVPost.y() +
|
|
vHAverNorm.z() * vVPost.z()) +
|
|
ANV * (-sinThetaAver *
|
|
(vVPre.x() * vpPostNorm.x() + vVPre.y() * vpPostNorm.y() +
|
|
vVPre.z() * vpPostNorm.z()) +
|
|
OMcosThetaAver * (vVPre.x() * AN2.x() + vVPre.y() * AN2.y() +
|
|
vVPre.z() * AN2.z()) -
|
|
TMSINT * gamma *
|
|
(vHAverNorm.x() * vVPre.x() + vHAverNorm.y() * vVPre.y() +
|
|
vHAverNorm.z() * vVPre.z()));
|
|
|
|
transf[1][2] =
|
|
cosThetaAver * (vUPre.x() * vVPost.x() + vUPre.y() * vVPost.y()) +
|
|
sinThetaAver * (vHUPre.x() * vVPost.x() + vHUPre.y() * vVPost.y() +
|
|
vHUPre.z() * vVPost.z()) +
|
|
OMcosThetaAver *
|
|
(vHAverNorm.x() * vUPre.x() + vHAverNorm.y() * vUPre.y()) *
|
|
(vHAverNorm.x() * vVPost.x() + vHAverNorm.y() * vVPost.y() +
|
|
vHAverNorm.z() * vVPost.z()) +
|
|
ANV * (-sinThetaAver *
|
|
(vUPre.x() * vpPostNorm.x() + vUPre.y() * vpPostNorm.y()) +
|
|
OMcosThetaAver * (vUPre.x() * AN2.x() + vUPre.y() * AN2.y()) -
|
|
TMSINT * gamma *
|
|
(vHAverNorm.x() * vUPre.x() + vHAverNorm.y() * vUPre.y()));
|
|
transf[1][2] = sinpPre * transf[1][2];
|
|
|
|
transf[1][3] = -QAver * ANV *
|
|
(vUPre.x() * vpPostNorm.x() + vUPre.y() * vpPostNorm.y());
|
|
|
|
transf[1][4] = -QAver * ANV *
|
|
(vVPre.x() * vpPostNorm.x() + vVPre.y() * vpPostNorm.y() +
|
|
vVPre.z() * vpPostNorm.z());
|
|
|
|
// *** Phi
|
|
|
|
transf[2][0] =
|
|
-QP * ANU *
|
|
(vpPostNorm.x() * deltaPos.x() + vpPostNorm.y() * deltaPos.y() +
|
|
vpPostNorm.z() * deltaPos.z()) *
|
|
sinpPostInv * (1. + deltaPInv * pAver);
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 3)
|
|
G4cout << "ctransf20= " << transf[2][0] << " " << -QP << " " << ANU
|
|
<< " " << vpPostNorm.x() << " " << deltaPos.x() << " "
|
|
<< vpPostNorm.y() << " " << deltaPos.y() << " " << vpPostNorm.z()
|
|
<< " " << deltaPos.z() << " " << sinpPostInv << " " << deltaPInv
|
|
<< " " << pAver << G4endl;
|
|
#endif
|
|
transf[2][1] =
|
|
cosThetaAver * (vVPre.x() * vUPost.x() + vVPre.y() * vUPost.y()) +
|
|
sinThetaAver * (vHVPre.x() * vUPost.x() + vHVPre.y() * vUPost.y()) +
|
|
OMcosThetaAver *
|
|
(vHAverNorm.x() * vVPre.x() + vHAverNorm.y() * vVPre.y() +
|
|
vHAverNorm.z() * vVPre.z()) *
|
|
(vHAverNorm.x() * vUPost.x() + vHAverNorm.y() * vUPost.y()) +
|
|
ANU * (-sinThetaAver *
|
|
(vVPre.x() * vpPostNorm.x() + vVPre.y() * vpPostNorm.y() +
|
|
vVPre.z() * vpPostNorm.z()) +
|
|
OMcosThetaAver * (vVPre.x() * AN2.x() + vVPre.y() * AN2.y() +
|
|
vVPre.z() * AN2.z()) -
|
|
TMSINT * gamma *
|
|
(vHAverNorm.x() * vVPre.x() + vHAverNorm.y() * vVPre.y() +
|
|
vHAverNorm.z() * vVPre.z()));
|
|
transf[2][1] = sinpPostInv * transf[2][1];
|
|
|
|
transf[2][2] =
|
|
cosThetaAver * (vUPre.x() * vUPost.x() + vUPre.y() * vUPost.y()) +
|
|
sinThetaAver * (vHUPre.x() * vUPost.x() + vHUPre.y() * vUPost.y()) +
|
|
OMcosThetaAver *
|
|
(vHAverNorm.x() * vUPre.x() + vHAverNorm.y() * vUPre.y()) *
|
|
(vHAverNorm.x() * vUPost.x() + vHAverNorm.y() * vUPost.y()) +
|
|
ANU * (-sinThetaAver *
|
|
(vUPre.x() * vpPostNorm.x() + vUPre.y() * vpPostNorm.y()) +
|
|
OMcosThetaAver * (vUPre.x() * AN2.x() + vUPre.y() * AN2.y()) -
|
|
TMSINT * gamma *
|
|
(vHAverNorm.x() * vUPre.x() + vHAverNorm.y() * vUPre.y()));
|
|
transf[2][2] = sinpPostInv * sinpPre * transf[2][2];
|
|
|
|
transf[2][3] = -QAver * ANU *
|
|
(vUPre.x() * vpPostNorm.x() + vUPre.y() * vpPostNorm.y()) *
|
|
sinpPostInv;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 3)
|
|
G4cout << "ctransf23= " << transf[2][3] << " " << -QAver << " " << ANU
|
|
<< " " << vUPre.x() << " " << vpPostNorm.x() << " " << vUPre.y()
|
|
<< " " << vpPostNorm.y() << " " << sinpPostInv << G4endl;
|
|
#endif
|
|
|
|
transf[2][4] = -QAver * ANU *
|
|
(vVPre.x() * vpPostNorm.x() + vVPre.y() * vpPostNorm.y() +
|
|
vVPre.z() * vpPostNorm.z()) *
|
|
sinpPostInv;
|
|
|
|
// *** Yt
|
|
|
|
transf[3][0] = pAver *
|
|
(vUPost.x() * deltaPos.x() + vUPost.y() * deltaPos.y()) *
|
|
(1. + deltaPInv * pAver);
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 3)
|
|
G4cout << "ctransf30= " << transf[3][0] << " " << pAver << " "
|
|
<< vUPost.x() << " " << deltaPos.x() << " " << vUPost.y() << " "
|
|
<< deltaPos.y() << " " << deltaPInv << " " << pAver << G4endl;
|
|
#endif
|
|
|
|
transf[3][1] =
|
|
(sinThetaAver * (vVPre.x() * vUPost.x() + vVPre.y() * vUPost.y()) +
|
|
OMcosThetaAver * (vHVPre.x() * vUPost.x() + vHVPre.y() * vUPost.y()) +
|
|
TMSINT * (vHAverNorm.x() * vUPost.x() + vHAverNorm.y() * vUPost.y()) *
|
|
(vHAverNorm.x() * vVPre.x() + vHAverNorm.y() * vVPre.y() +
|
|
vHAverNorm.z() * vVPre.z())) /
|
|
QAver;
|
|
|
|
transf[3][2] =
|
|
(sinThetaAver * (vUPre.x() * vUPost.x() + vUPre.y() * vUPost.y()) +
|
|
OMcosThetaAver * (vHUPre.x() * vUPost.x() + vHUPre.y() * vUPost.y()) +
|
|
TMSINT * (vHAverNorm.x() * vUPost.x() + vHAverNorm.y() * vUPost.y()) *
|
|
(vHAverNorm.x() * vUPre.x() + vHAverNorm.y() * vUPre.y())) *
|
|
sinpPre / QAver;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 3)
|
|
G4cout << "ctransf32= " << transf[3][2] << " " << sinThetaAver << " "
|
|
<< vUPre.x() << " " << vUPost.x() << " " << vUPre.y() << " "
|
|
<< vUPost.y() << " " << OMcosThetaAver << " " << vHUPre.x()
|
|
<< " " << vUPost.x() << " " << vHUPre.y() << " " << vUPost.y()
|
|
<< " " << TMSINT << " " << vHAverNorm.x() << " " << vUPost.x()
|
|
<< " " << vHAverNorm.y() << " " << vUPost.y() << " "
|
|
<< vHAverNorm.x() << " " << vUPre.x() << " " << vHAverNorm.y()
|
|
<< " " << vUPre.y() << " " << sinpPre << " " << QAver << G4endl;
|
|
#endif
|
|
|
|
transf[3][3] = (vUPre.x() * vUPost.x() + vUPre.y() * vUPost.y());
|
|
|
|
transf[3][4] = (vVPre.x() * vUPost.x() + vVPre.y() * vUPost.y());
|
|
|
|
// *** Zt
|
|
transf[4][0] = pAver *
|
|
(vVPost.x() * deltaPos.x() + vVPost.y() * deltaPos.y() +
|
|
vVPost.z() * deltaPos.z()) *
|
|
(1. + deltaPInv * pAver);
|
|
|
|
transf[4][1] =
|
|
(sinThetaAver * (vVPre.x() * vVPost.x() + vVPre.y() * vVPost.y() +
|
|
vVPre.z() * vVPost.z()) +
|
|
OMcosThetaAver * (vHVPre.x() * vVPost.x() + vHVPre.y() * vVPost.y() +
|
|
vHVPre.z() * vVPost.z()) +
|
|
TMSINT *
|
|
(vHAverNorm.x() * vVPost.x() + vHAverNorm.y() * vVPost.y() +
|
|
vHAverNorm.z() * vVPost.z()) *
|
|
(vHAverNorm.x() * vVPre.x() + vHAverNorm.y() * vVPre.y() +
|
|
vHAverNorm.z() * vVPre.z())) /
|
|
QAver;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 3)
|
|
G4cout << "ctransf41= " << transf[4][1] << " " << sinThetaAver << " "
|
|
<< OMcosThetaAver << " " << TMSINT << " " << vVPre << " "
|
|
<< vVPost << " " << vHVPre << " " << vHAverNorm << " " << QAver
|
|
<< G4endl;
|
|
#endif
|
|
|
|
transf[4][2] =
|
|
(sinThetaAver * (vUPre.x() * vVPost.x() + vUPre.y() * vVPost.y()) +
|
|
OMcosThetaAver * (vHUPre.x() * vVPost.x() + vHUPre.y() * vVPost.y() +
|
|
vHUPre.z() * vVPost.z()) +
|
|
TMSINT *
|
|
(vHAverNorm.x() * vVPost.x() + vHAverNorm.y() * vVPost.y() +
|
|
vHAverNorm.z() * vVPost.z()) *
|
|
(vHAverNorm.x() * vUPre.x() + vHAverNorm.y() * vUPre.y())) *
|
|
sinpPre / QAver;
|
|
|
|
transf[4][3] = (vUPre.x() * vVPost.x() + vUPre.y() * vVPost.y());
|
|
|
|
transf[4][4] = (vVPre.x() * vVPost.x() + vVPre.y() * vVPost.y() +
|
|
vVPre.z() * vVPost.z());
|
|
// if(iverbose >= 3) G4cout <<"ctransf44= " << transf[4][4] <<" "<<
|
|
// vVPre.x() <<" "<<vVPost.x() <<" "<< vVPre.y() <<" "<< vVPost.y() <<"
|
|
// "<< vVPre.z() <<" "<< vVPost.z() << G4endl;
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 1)
|
|
G4cout << "G4EP: transf matrix computed " << transf << G4endl;
|
|
#endif
|
|
/* for( G4int ii=0;ii<5;ii++){
|
|
for( G4int jj=0;jj<5;jj++){
|
|
G4cout << transf[ii][jj] << " ";
|
|
}
|
|
G4cout << G4endl;
|
|
} */
|
|
}
|
|
}
|
|
// end of calculate transformation except it NEUTRAL PARTICLE OR FIELDFREE
|
|
// REGION
|
|
/* if( iverbose >= 1 ) G4cout << "G4EP: transf not updated but initialized "
|
|
<< theFirstStep << G4endl; if( theFirstStep ) { theTransfMat = transf;
|
|
theFirstStep = false;
|
|
}else{
|
|
theTransfMat = theTransfMat * transf;
|
|
if( iverbose >= 1 ) G4cout << "G4EP: transf matrix accumulated" <<
|
|
theTransfMat << G4endl;
|
|
}
|
|
*/
|
|
theTransfMat = transf;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 1)
|
|
G4cout << "G4EP: error matrix before transformation " << fError << G4endl;
|
|
if(iverbose >= 2)
|
|
G4cout << " tf * err " << theTransfMat * fError << G4endl
|
|
<< " transf matrix " << theTransfMat.T() << G4endl;
|
|
#endif
|
|
|
|
fError = fError.similarity(theTransfMat).T();
|
|
//- fError = transf * fError * transf.T();
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 1)
|
|
G4cout << "G4EP: error matrix propagated " << fError << G4endl;
|
|
#endif
|
|
|
|
//? S = B*S*BT S.similarity(B)
|
|
//? R = S
|
|
// not needed * *** TRANSFORM ERROR MATRIX FROM INTERNAL TO EXTERNAL
|
|
// VARIABLES;
|
|
|
|
PropagateErrorMSC(aTrack);
|
|
|
|
PropagateErrorIoni(aTrack);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
G4int G4ErrorFreeTrajState::PropagateErrorMSC(const G4Track* aTrack)
|
|
{
|
|
G4ThreeVector vpPre = aTrack->GetMomentum() / GeV;
|
|
G4double pPre = vpPre.mag();
|
|
G4double pBeta = pPre * pPre / (aTrack->GetTotalEnergy() / GeV);
|
|
G4double stepLengthCm = aTrack->GetStep()->GetStepLength() / cm;
|
|
|
|
G4Material* mate = aTrack->GetVolume()->GetLogicalVolume()->GetMaterial();
|
|
G4double effZ, effA;
|
|
CalculateEffectiveZandA(mate, effZ, effA);
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 4)
|
|
G4cout << "material "
|
|
<< mate->GetName()
|
|
//<< " " << mate->GetZ() << " " << mate->GetA()
|
|
<< " effZ:" << effZ << " effA:" << effA
|
|
<< " dens(g/mole):" << mate->GetDensity() / g * mole
|
|
<< " Radlen/cm:" << mate->GetRadlen() / cm << " nuclLen/cm"
|
|
<< mate->GetNuclearInterLength() / cm << G4endl;
|
|
#endif
|
|
|
|
G4double RI = stepLengthCm / (mate->GetRadlen() / cm);
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 4)
|
|
G4cout << std::setprecision(6) << std::setw(6) << "G4EP:MSC: RI=X/X0 " << RI
|
|
<< " stepLengthCm " << stepLengthCm << " radlen/cm "
|
|
<< (mate->GetRadlen() / cm) << " RI*1.e10:" << RI * 1.e10 << G4endl;
|
|
#endif
|
|
G4double charge = aTrack->GetDynamicParticle()->GetCharge();
|
|
G4double DD = 1.8496E-4 * RI * (charge / pBeta * charge / pBeta);
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 3)
|
|
G4cout << "G4EP:MSC: D*1E6= " << DD * 1.E6 << " pBeta " << pBeta << G4endl;
|
|
#endif
|
|
G4double S1 = DD * stepLengthCm * stepLengthCm / 3.;
|
|
G4double S2 = DD;
|
|
G4double S3 = DD * stepLengthCm / 2.;
|
|
|
|
G4double CLA =
|
|
std::sqrt(vpPre.x() * vpPre.x() + vpPre.y() * vpPre.y()) / pPre;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << std::setw(6) << "G4EP:MSC: RI " << RI << " S1 " << S1 << " S2 "
|
|
<< S2 << " S3 " << S3 << " CLA " << CLA << G4endl;
|
|
#endif
|
|
fError[1][1] += S2;
|
|
fError[1][4] -= S3;
|
|
fError[2][2] += S2 / CLA / CLA;
|
|
fError[2][3] += S3 / CLA;
|
|
fError[3][3] += S1;
|
|
fError[4][4] += S1;
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << "G4EP:MSC: error matrix propagated msc " << fError << G4endl;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void G4ErrorFreeTrajState::CalculateEffectiveZandA(const G4Material* mate,
|
|
G4double& effZ,
|
|
G4double& effA)
|
|
{
|
|
effZ = 0.;
|
|
effA = 0.;
|
|
auto nelem = mate->GetNumberOfElements();
|
|
const G4double* fracVec = mate->GetFractionVector();
|
|
for(G4int ii = 0; ii < (G4int)nelem; ++ii)
|
|
{
|
|
effZ += mate->GetElement(ii)->GetZ() * fracVec[ii];
|
|
effA += mate->GetElement(ii)->GetA() * fracVec[ii] / g * mole;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
G4int G4ErrorFreeTrajState::PropagateErrorIoni(const G4Track* aTrack)
|
|
{
|
|
G4double stepLengthCm = aTrack->GetStep()->GetStepLength() / cm;
|
|
#ifdef G4EVERBOSE
|
|
G4double DEDX2;
|
|
if(stepLengthCm < 1.E-7)
|
|
{
|
|
DEDX2 = 0.;
|
|
}
|
|
#endif
|
|
// * Calculate xi factor (KeV).
|
|
G4Material* mate = aTrack->GetVolume()->GetLogicalVolume()->GetMaterial();
|
|
G4double effZ, effA;
|
|
CalculateEffectiveZandA(mate, effZ, effA);
|
|
|
|
G4double Etot = aTrack->GetTotalEnergy() / GeV;
|
|
G4double beta = aTrack->GetMomentum().mag() / GeV / Etot;
|
|
G4double mass = aTrack->GetDynamicParticle()->GetMass() / GeV;
|
|
G4double gamma = Etot / mass;
|
|
|
|
// * Calculate xi factor (keV).
|
|
G4double XI = 153.5 * effZ * stepLengthCm * (mate->GetDensity() / mg * mole) /
|
|
(effA * beta * beta);
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
{
|
|
G4cout << "G4EP:IONI: XI/keV " << XI << " beta " << beta << " gamma "
|
|
<< gamma << G4endl;
|
|
G4cout << " density " << (mate->GetDensity() / mg * mole) << " effA "
|
|
<< effA << " step " << stepLengthCm << G4endl;
|
|
}
|
|
#endif
|
|
// * Maximum energy transfer to atomic electron (KeV).
|
|
G4double eta = beta * gamma;
|
|
G4double etasq = eta * eta;
|
|
G4double eMass = 0.51099906 / GeV;
|
|
G4double massRatio = eMass / mass;
|
|
G4double F1 = 2 * eMass * etasq;
|
|
G4double F2 = 1. + 2. * massRatio * gamma + massRatio * massRatio;
|
|
G4double Emax = 1.E+6 * F1 / F2; // now in keV
|
|
|
|
// * *** and now sigma**2 in GeV
|
|
G4double dedxSq =
|
|
XI * Emax * (1. - (beta * beta / 2.)) * 1.E-12; // now in GeV^2
|
|
/*The above formula for var(1/p) good for dens scatterers. However, for MIPS
|
|
passing through a gas it leads to overestimation. Further more for incident
|
|
electrons the Emax is almost equal to incident energy. This leads to
|
|
k=Xi/Emax as small as e-6 and gradually the cov matrix explodes.
|
|
|
|
http://www2.pv.infn.it/~rotondi/kalman_1.pdf
|
|
|
|
Since I do not have enough info at the moment to implement Landau &
|
|
sub-Landau models for k=Xi/Emax <0.01 I'll saturate k at this value for now
|
|
*/
|
|
|
|
if(XI / Emax < 0.01)
|
|
dedxSq *=
|
|
XI / Emax * 100; // Quench for low Elos, see above: newVar=odVar *k/0.01
|
|
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << "G4EP:IONI: DEDX^2(GeV^2) " << dedxSq << " emass/GeV: " << eMass
|
|
<< " Emax/keV: " << Emax << " k=Xi/Emax=" << XI / Emax << G4endl;
|
|
|
|
#endif
|
|
|
|
G4double pPre6 =
|
|
(aTrack->GetStep()->GetPreStepPoint()->GetMomentum() / GeV).mag();
|
|
pPre6 = std::pow(pPre6, 6);
|
|
// Apply it to error
|
|
fError[0][0] += Etot * Etot * dedxSq / pPre6;
|
|
#ifdef G4EVERBOSE
|
|
if(iverbose >= 2)
|
|
G4cout << "G4:IONI Etot/GeV: " << Etot << " err_dedx^2/GeV^2: " << dedxSq
|
|
<< " p^6: " << pPre6 << G4endl;
|
|
if(iverbose >= 2)
|
|
G4cout << "G4EP:IONI: error2_from_ionisation "
|
|
<< (Etot * Etot * dedxSq) / pPre6 << G4endl;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|