Import Geant4 11.4.0 source tree

This commit is contained in:
Gabriele Cosmo
2025-12-05 08:54:02 +01:00
parent a499fb82e9
commit b4a16de652
6484 changed files with 232674 additions and 221097 deletions
@@ -25,8 +25,8 @@
//
// G4IntegrationDriver inline implementation
//
// Author: Dmitry Sorokin, Google Summer of Code 2017
// Supervision: John Apostolakis, CERN
// Author: Dmitry Sorokin (CERN, Google Summer of Code 2017), 20.10.2017
// Supervision: John Apostolakis (CERN)
// --------------------------------------------------------------------
#include "G4FieldUtils.hh"
@@ -41,30 +41,30 @@ G4IntegrationDriver ( G4double hminimum, T* pStepper,
fMinimumStep(hminimum),
fVerboseLevel(statisticsVerbose)
{
if (numComponents != Base::GetStepper()->GetNumberOfVariables())
{
std::ostringstream message;
message << "Driver's number of integrated components "
<< numComponents
<< " != Stepper's number of components "
<< pStepper->GetNumberOfVariables();
G4Exception("G4IntegrationDriver","GeomField0002",
FatalException, message);
}
if (numComponents != Base::GetStepper()->GetNumberOfVariables())
{
std::ostringstream message;
message << "Driver's number of integrated components "
<< numComponents
<< " != Stepper's number of components "
<< pStepper->GetNumberOfVariables();
G4Exception("G4IntegrationDriver","GeomField0002",
FatalException, message);
}
}
template <class T>
G4IntegrationDriver<T>::~G4IntegrationDriver()
{
#ifdef G4VERBOSE
if (fVerboseLevel > 0)
{
G4cout << "G4Integration Driver Stats: "
<< "#QuickAdvance " << fNoQuickAvanceCalls
<< " - #AccurateAdvance " << fNoAccurateAdvanceCalls << " "
<< "#good steps " << fNoAccurateAdvanceGoodSteps << " "
<< "#bad steps " << fNoAccurateAdvanceBadSteps << G4endl;
}
if (fVerboseLevel > 0)
{
G4cout << "G4Integration Driver Stats: "
<< "#QuickAdvance " << fNoQuickAvanceCalls
<< " - #AccurateAdvance " << fNoAccurateAdvanceCalls << " "
<< "#good steps " << fNoAccurateAdvanceGoodSteps << " "
<< "#bad steps " << fNoAccurateAdvanceBadSteps << G4endl;
}
#endif
}
@@ -74,14 +74,25 @@ G4double G4IntegrationDriver<T>::AdvanceChordLimited(G4FieldTrack& track,
G4double epsStep,
G4double chordDistance)
{
return ChordFinderDelegate::AdvanceChordLimitedImpl(track, stepMax, epsStep,
chordDistance);
return ChordFinderDelegate::AdvanceChordLimitedImpl(track, stepMax, epsStep,
chordDistance);
}
template <class T>
void G4IntegrationDriver<T>::OnStartTracking()
{
ChordFinderDelegate::ResetStepEstimate();
ChordFinderDelegate::ResetStepEstimate();
}
template <class T>
void G4IntegrationDriver<T>::OnComputeStep(const G4FieldTrack*)
{
}
template <class T>
G4bool G4IntegrationDriver<T>::DoesReIntegrate() const
{
return true;
}
// Runge-Kutta driver with adaptive stepsize control. Integrate starting
@@ -95,110 +106,110 @@ G4bool G4IntegrationDriver<T>::
AccurateAdvance(G4FieldTrack& track, G4double hstep,
G4double eps, G4double hinitial)
{
++fNoAccurateAdvanceCalls;
++fNoAccurateAdvanceCalls;
if (hstep == 0.0)
{
std::ostringstream message;
message << "Proposed step is zero; hstep = " << hstep << " !";
G4Exception("G4IntegrationDriver::AccurateAdvance()",
"GeomField1001", JustWarning, message);
return true;
}
if (hstep == 0.0)
{
std::ostringstream message;
message << "Proposed step is zero; hstep = " << hstep << " !";
G4Exception("G4IntegrationDriver::AccurateAdvance()",
"GeomField1001", JustWarning, message);
return true;
}
if (hstep < 0)
{
std::ostringstream message;
message << "Invalid run condition." << G4endl
<< "Proposed step is negative; hstep = " << hstep << "."
<< G4endl
<< "Requested step cannot be negative! Aborting event.";
G4Exception("G4IntegrationDriver::AccurateAdvance()",
"GeomField0003", EventMustBeAborted, message);
return false;
}
if (hstep < 0)
{
std::ostringstream message;
message << "Invalid run condition." << G4endl
<< "Proposed step is negative; hstep = " << hstep << "."
<< G4endl
<< "Requested step cannot be negative! Aborting event.";
G4Exception("G4IntegrationDriver::AccurateAdvance()",
"GeomField0003", EventMustBeAborted, message);
return false;
}
G4double hnext, hdid;
G4double hnext, hdid;
G4double dydx[G4FieldTrack::ncompSVEC];
G4bool succeeded = true;
G4double dydx[G4FieldTrack::ncompSVEC];
G4bool succeeded = true;
G4double y[G4FieldTrack::ncompSVEC];
track.DumpToArray(y);
G4double y[G4FieldTrack::ncompSVEC];
track.DumpToArray(y);
const G4double startCurveLength = track.GetCurveLength();
const G4double endCurveLength = startCurveLength + hstep;
const G4double hThreshold =
const G4double startCurveLength = track.GetCurveLength();
const G4double endCurveLength = startCurveLength + hstep;
const G4double hThreshold =
std::min(eps * hstep, fSmallestFraction * startCurveLength);
G4double h = hstep;
if (hinitial > CLHEP::perMillion * hstep && hinitial < hstep)
{
h = hinitial;
}
G4double h = hstep;
if (hinitial > CLHEP::perMillion * hstep && hinitial < hstep)
{
h = hinitial;
}
G4double curveLength = startCurveLength;
G4double curveLength = startCurveLength;
for (G4int nstp = 0; nstp < Base::GetMaxNoSteps(); ++nstp)
{
const G4ThreeVector StartPos =
field_utils::makeVector(y, field_utils::Value3D::Position);
for (G4int nstp = 0; nstp < Base::GetMaxNoSteps(); ++nstp)
{
const G4ThreeVector StartPos =
field_utils::makeVector(y, field_utils::Value3D::Position);
Base::GetStepper()->RightHandSide(y, dydx);
Base::GetStepper()->RightHandSide(y, dydx);
if (h > GetMinimumStep())
{
OneGoodStep(y, dydx, curveLength, h, eps, hdid, hnext);
}
else
{
G4FieldTrack yFldTrk('0');
G4double dchord_step, dyerr, dyerr_len;
yFldTrk.LoadFromArray(y, Base::GetStepper()->GetNumberOfVariables());
yFldTrk.SetCurveLength(curveLength);
QuickAdvance(yFldTrk, dydx, h, dchord_step, dyerr_len);
yFldTrk.DumpToArray(y);
if (h == 0.0)
{
G4Exception("G4IntegrationDriver::AccurateAdvance()",
"GeomField0003", FatalException,
"Integration Step became Zero!");
}
dyerr = dyerr_len / h;
hdid = h;
curveLength += hdid;
hnext = Base::ComputeNewStepSize(dyerr / eps, h);
}
const G4ThreeVector EndPos =
field_utils::makeVector(y, field_utils::Value3D::Position);
CheckStep(EndPos, StartPos, hdid);
// Avoid numerous small last steps
if (h < hThreshold || curveLength >= endCurveLength)
{
break;
}
h = std::max(hnext, GetMinimumStep());
if (curveLength + h > endCurveLength)
{
h = endCurveLength - curveLength;
}
if (h > GetMinimumStep())
{
OneGoodStep(y, dydx, curveLength, h, eps, hdid, hnext);
}
// Have we reached the end ?
// --> a better test might be x-endCurveLength > an_epsilon
succeeded = (curveLength >= endCurveLength);
// If it was a "forced" last step
else
{
G4FieldTrack yFldTrk('0');
G4double dchord_step, dyerr, dyerr_len;
yFldTrk.LoadFromArray(y, Base::GetStepper()->GetNumberOfVariables());
yFldTrk.SetCurveLength(curveLength);
track.LoadFromArray(y, Base::GetStepper()->GetNumberOfVariables());
track.SetCurveLength(curveLength);
QuickAdvance(yFldTrk, dydx, h, dchord_step, dyerr_len);
return succeeded;
yFldTrk.DumpToArray(y);
if (h == 0.0)
{
G4Exception("G4IntegrationDriver::AccurateAdvance()",
"GeomField0003", FatalException,
"Integration Step became Zero!");
}
dyerr = dyerr_len / h;
hdid = h;
curveLength += hdid;
hnext = Base::ComputeNewStepSize(dyerr / eps, h);
}
const G4ThreeVector EndPos =
field_utils::makeVector(y, field_utils::Value3D::Position);
CheckStep(EndPos, StartPos, hdid);
// Avoid numerous small last steps
if (h < hThreshold || curveLength >= endCurveLength)
{
break;
}
h = std::max(hnext, GetMinimumStep());
if (curveLength + h > endCurveLength)
{
h = endCurveLength - curveLength;
}
}
// Have we reached the end ?
// --> a better test might be x-endCurveLength > an_epsilon
succeeded = (curveLength >= endCurveLength);
// If it was a "forced" last step
track.LoadFromArray(y, Base::GetStepper()->GetNumberOfVariables());
track.SetCurveLength(curveLength);
return succeeded;
}
// Driver for one Runge-Kutta Step with monitoring of local truncation error
@@ -224,46 +235,46 @@ void G4IntegrationDriver<T>::OneGoodStep(G4double y[], // InOut
G4double& hnext) // Out
{
G4double error2 = DBL_MAX;
G4double error2 = DBL_MAX;
G4double yerr[G4FieldTrack::ncompSVEC], ytemp[G4FieldTrack::ncompSVEC];
G4double yerr[G4FieldTrack::ncompSVEC], ytemp[G4FieldTrack::ncompSVEC];
G4double h = htry;
G4double h = htry;
const G4int max_trials = 100;
const G4int max_trials = 100;
for (G4int iter = 0; iter < max_trials; ++iter)
{
Base::GetStepper()->Stepper(y, dydx, h, ytemp, yerr);
error2 = field_utils::relativeError2(y, yerr, std::max(h, fMinimumStep),
for (G4int iter = 0; iter < max_trials; ++iter)
{
Base::GetStepper()->Stepper(y, dydx, h, ytemp, yerr);
error2 = field_utils::relativeError2(y, yerr, std::max(h, fMinimumStep),
eps_rel_max);
if (error2 <= 1.0)
{
break;
}
h = Base::ShrinkStepSize2(h, error2);
G4double xnew = curveLength + h;
if(xnew == curveLength)
{
std::ostringstream message;
message << "Stepsize underflow in Stepper !" << G4endl
<< "- Step's start x=" << curveLength
<< " and end x= " << xnew
<< " are equal !! " << G4endl
<< " Due to step-size= " << h
<< ". Note that input step was " << htry;
G4Exception("G4IntegrationDriver::OneGoodStep()",
"GeomField1001", JustWarning, message);
break;
}
if (error2 <= 1.0)
{
break;
}
hnext = Base::GrowStepSize2(h, error2);
curveLength += (hdid = h);
h = Base::ShrinkStepSize2(h, error2);
field_utils::copy(y, ytemp, Base::GetStepper()->GetNumberOfVariables());
G4double xnew = curveLength + h;
if(xnew == curveLength)
{
std::ostringstream message;
message << "Stepsize underflow in Stepper !" << G4endl
<< "- Step's start x=" << curveLength
<< " and end x= " << xnew
<< " are equal !! " << G4endl
<< " Due to step-size= " << h
<< ". Note that input step was " << htry;
G4Exception("G4IntegrationDriver::OneGoodStep()",
"GeomField1001", JustWarning, message);
break;
}
}
hnext = Base::GrowStepSize2(h, error2);
curveLength += (hdid = h);
field_utils::copy(y, ytemp, Base::GetStepper()->GetNumberOfVariables());
}
template <class T>
@@ -273,40 +284,22 @@ G4bool G4IntegrationDriver<T>::QuickAdvance(G4FieldTrack& track, // INOUT
G4double& dchord_step,
G4double& dyerr)
{
++fNoQuickAvanceCalls;
++fNoQuickAvanceCalls;
G4double yIn[G4FieldTrack::ncompSVEC],
yOut[G4FieldTrack::ncompSVEC],
yError[G4FieldTrack::ncompSVEC];
G4double yIn[G4FieldTrack::ncompSVEC],
yOut[G4FieldTrack::ncompSVEC],
yError[G4FieldTrack::ncompSVEC];
track.DumpToArray(yIn);
track.DumpToArray(yIn);
Base::GetStepper()->Stepper(yIn, dydx, hstep, yOut, yError);
Base::GetStepper()->Stepper(yIn, dydx, hstep, yOut, yError);
dchord_step = Base::GetStepper()->DistChord();
dyerr = field_utils::absoluteError(yOut, yError, hstep);
track.LoadFromArray(yOut, Base::GetStepper()->GetNumberOfVariables());
track.SetCurveLength(track.GetCurveLength() + hstep);
dchord_step = Base::GetStepper()->DistChord();
dyerr = field_utils::absoluteError(yOut, yError, hstep);
track.LoadFromArray(yOut, Base::GetStepper()->GetNumberOfVariables());
track.SetCurveLength(track.GetCurveLength() + hstep);
return true;
}
template <class T>
void G4IntegrationDriver<T>::SetSmallestFraction(G4double newFraction)
{
if (newFraction > 1.e-16 && newFraction < 1e-8)
{
fSmallestFraction = newFraction;
}
else
{
std::ostringstream message;
message << "Smallest Fraction not changed. " << G4endl
<< " Proposed value was " << newFraction << G4endl
<< " Value must be between 1.e-8 and 1.e-16";
G4Exception("G4IntegrationDriver::SetSmallestFraction()",
"GeomField1001", JustWarning, message);
}
return true;
}
template <class T>
@@ -314,67 +307,86 @@ void G4IntegrationDriver<T>::CheckStep(const G4ThreeVector& posIn,
const G4ThreeVector& posOut,
G4double hdid)
{
const G4double endPointDist = (posOut - posIn).mag();
if (endPointDist >= hdid * (1. + CLHEP::perMillion))
{
++fNoAccurateAdvanceBadSteps;
const G4double endPointDist = (posOut - posIn).mag();
if (endPointDist >= hdid * (1. + CLHEP::perMillion))
{
++fNoAccurateAdvanceBadSteps;
#ifdef G4DEBUG_FIELD
// Issue a warning only for gross differences -
// we understand how small difference occur.
if (endPointDist >= hdid * (1. + perThousand))
{
G4Exception("G4IntegrationDriver::CheckStep()",
"GeomField1002", JustWarning,
"endPointDist >= hdid!");
}
#endif
}
else
// Issue a warning only for gross differences -
// we understand how small difference occur.
if (endPointDist >= hdid * (1. + perThousand))
{
++fNoAccurateAdvanceGoodSteps;
G4Exception("G4IntegrationDriver::CheckStep()",
"GeomField1002", JustWarning,
"endPointDist >= hdid!");
}
#endif
}
else
{
++fNoAccurateAdvanceGoodSteps;
}
}
template <class T>
inline G4double G4IntegrationDriver<T>::GetMinimumStep() const
{
return fMinimumStep;
return fMinimumStep;
}
template <class T>
void G4IntegrationDriver<T>::SetMinimumStep(G4double minimumStepLength)
{
fMinimumStep = minimumStepLength;
fMinimumStep = minimumStepLength;
}
template <class T>
G4int G4IntegrationDriver<T>::GetVerboseLevel() const
{
return fVerboseLevel;
return fVerboseLevel;
}
template <class T>
void G4IntegrationDriver<T>::SetVerboseLevel(G4int newLevel)
{
fVerboseLevel = newLevel;
fVerboseLevel = newLevel;
}
template <class T>
G4double G4IntegrationDriver<T>::GetSmallestFraction() const
{
return fSmallestFraction;
return fSmallestFraction;
}
template <class T>
void G4IntegrationDriver<T>::SetSmallestFraction(G4double newFraction)
{
if (newFraction > 1.e-16 && newFraction < 1e-8)
{
fSmallestFraction = newFraction;
}
else
{
std::ostringstream message;
message << "Smallest Fraction not changed. " << G4endl
<< " Proposed value was " << newFraction << G4endl
<< " Value must be between 1.e-8 and 1.e-16";
G4Exception("G4IntegrationDriver::SetSmallestFraction()",
"GeomField1001", JustWarning, message);
}
}
template <class T>
void G4IntegrationDriver<T>::IncrementQuickAdvanceCalls()
{
++fNoQuickAvanceCalls;
++fNoQuickAvanceCalls;
}
template <class T>
void G4IntegrationDriver<T>::StreamInfo( std::ostream& os ) const
{
// Write out the parameters / state of the driver
// Write out the parameters / state of the driver
os << "State of G4IntegrationDriver: " << std::endl;
os << "--Base state (G4RKIntegrationDriver): " << std::endl;
Base::StreamInfo( os );