Import Geant4 10.7.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2020-06-26 10:23:25 +02:00
parent c02c370437
commit 67ba86d073
1871 changed files with 174422 additions and 131884 deletions
@@ -57,13 +57,13 @@ class G4BFieldIntegrationDriver : public G4VIntegrationDriver
virtual G4bool AccurateAdvance(G4FieldTrack& track,
G4double hstep,
G4double eps,
G4double eps,
G4double hinitial = 0) override
{
return fCurrDriver->AccurateAdvance(track, hstep, eps, hinitial);
}
virtual G4bool DoesReIntegrate() override
virtual G4bool DoesReIntegrate() const override
{
return fCurrDriver->DoesReIntegrate();
}
@@ -130,6 +130,15 @@ class G4BFieldIntegrationDriver : public G4VIntegrationDriver
fLargeStepDriver->OnStartTracking();
}
virtual void StreamInfo( std::ostream& os ) const override
{
os << "Small Step Driver Info: " << std::endl;
fSmallStepDriver->StreamInfo(os);
os << "Large Step Driver Info: " << std::endl;
fLargeStepDriver->StreamInfo(os);
}
// Write out the parameters / state of the driver
void PrintStatistics() const;
private:
@@ -72,7 +72,7 @@ class G4IntegrationDriver<G4BulirschStoer>:
virtual void OnComputeStep() override {};
virtual G4bool DoesReIntegrate() override { return false; } /// ????
virtual G4bool DoesReIntegrate() const override { return false; } /// ????
virtual G4bool AccurateAdvance( G4FieldTrack& track,
G4double stepLen,
@@ -114,6 +114,9 @@ class G4IntegrationDriver<G4BulirschStoer>:
virtual const G4MagIntegratorStepper* GetStepper() const override;
virtual G4MagIntegratorStepper* GetStepper() override;
virtual void StreamInfo( std::ostream& os ) const override;
// Write out the parameters / state of the driver
private:
G4int GetNumberOfVarialbles() const;
@@ -425,3 +425,10 @@ G4IntegrationDriver<G4BulirschStoer>::GetStepper()
{
return nullptr;
}
void
G4IntegrationDriver<G4BulirschStoer>::StreamInfo( std::ostream& os ) const
{
os << "State of G4IntegrationDriver<G4BulirschStoer>: " << std::endl;
os << " Method is implemented, but gives no information. " << std::endl;
}
@@ -115,6 +115,9 @@ class G4ChordFinder
void OnComputeStep();
friend std::ostream&
operator<<( std::ostream& os, const G4ChordFinder& cf);
protected: // .........................................................
void PrintDchordTrial(G4int noTrials,
@@ -74,6 +74,9 @@ class G4ChordFinderDelegate
G4double GetLastStepEstimateUnc();
void SetLastStepEstimateUnc(G4double stepEst);
void StreamDelegateInfo( std::ostream& os ) const;
// Write out the parameters / state of the driver
private:
Driver& GetDriver();
@@ -392,3 +392,23 @@ void G4ChordFinderDelegate<T>::TestChordPrint(G4int noTrials,
G4cout << " nextStepTrial = " << std::setw(10) << nextStepTrial << G4endl;
G4cout.precision(oldprec);
}
template <class T>
void G4ChordFinderDelegate<T>::StreamDelegateInfo( std::ostream& os ) const
{
// Write out the parameters / state of the driver
os << "State of G4ChordFinderDelegate: " << std::endl;
os << "--Parameters: " << std::endl;
os << " First Fraction = " << fFirstFraction << std::endl;
os << " Last Fraction = " << fFractionLast << std::endl;
os << " Fract Next est = " << fFractionNextEstimate << std::endl;
os << "--State (fungible): " << std::endl;
os << " Maximum No Trials (seen) = " << fmaxTrials << std::endl;
os << " LastStepEstimate (Unconstrained) = " << fLastStepEstimate_Unconstrained
<< std::endl;
// os << " Statistics NOT printed. " << std::endl;
os << "--Statistics: trials= " << fTotalNoTrials
<< " calls= " << fNoCalls << std::endl;
}
@@ -0,0 +1,68 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// G4DriverReporter
//
// Class description:
//
// Auxiliary class to print information from integration drivers
// Can be used by different types of drivers.
// Authors: J.Apostolakis - January/March 2020
// -------------------------------------------------------------------
#ifndef G4DRIVERREPORTER_HH
#define G4DRIVERREPORTER_HH
#include "G4FieldTrack.hh"
class G4DriverReporter
{
public:
static void PrintStatus(const G4double* StartArr,
G4double xstart,
const G4double* CurrentArr,
G4double xcurrent,
G4double requestStep,
unsigned int subStepNo,
unsigned int noIntegrationVariables);
static void PrintStatus(const G4FieldTrack& StartFT,
const G4FieldTrack& CurrentFT,
G4double requestStep,
unsigned int subStepNo);
static void PrintStat_Aux(const G4FieldTrack& aFieldTrack,
G4double requestStep,
G4double actualStep,
G4int subStepNo,
G4double subStepSize,
G4double dotVelocities);
private:
// G4int fVerboseLevel; // Verbose output for debugging
// unsigned int fNoIntegrationVariables);
};
#endif
@@ -66,7 +66,7 @@ class G4FSALIntegrationDriver
virtual void OnComputeStep() override {}
virtual G4bool DoesReIntegrate() override { return true; }
virtual G4bool DoesReIntegrate() const override { return true; }
virtual G4bool AccurateAdvance( G4FieldTrack& track,
G4double hstep,
@@ -86,6 +86,9 @@ class G4FSALIntegrationDriver
virtual void SetVerboseLevel(G4int newLevel) override;
virtual G4int GetVerboseLevel() const override;
virtual void StreamInfo( std::ostream& os ) const override;
// Write out the parameters / state of the driver
// Accessors
G4double GetMinimumStep() const;
@@ -334,3 +334,20 @@ G4FSALIntegrationDriver<T>::AdvanceChordLimited(G4FieldTrack& track,
return ChordFinderDelegate::AdvanceChordLimitedImpl(track, hstep,
eps, chordDistance);
}
template <class T>
void G4FSALIntegrationDriver<T>::StreamInfo( std::ostream& os ) const
{
// Write out the parameters / state of the driver
os << "State of G4IntegrationDriver: " << std::endl;
os << "--Base state (G4RKIntegrationDriver): " << std::endl;
Base::StreamInfo( os );
os << "--Own state (G4IntegrationDriver<>): " << std::endl;
os << " fMinimumStep = " << fMinimumStep << std::endl;
os << " Smallest Fraction = " << fSmallestFraction << std::endl;
os << " verbose level = " << fVerboseLevel << std::endl;
os << " Reintegrates = " << DoesReIntegrate() << std::endl;
os << "--Chord Finder Delegate state: " << std::endl;
ChordFinderDelegate::StreamDelegateInfo( os );
}
@@ -79,6 +79,10 @@ class G4FieldTrack
inline G4FieldTrack& operator= ( const G4FieldTrack& rStVec );
// Copy constructor & Assignment operator
inline G4FieldTrack(G4FieldTrack&& from);
inline G4FieldTrack& operator=(G4FieldTrack&& from);
// Move constructor & operator
inline void UpdateState( const G4ThreeVector& pPosition,
G4double LaboratoryTimeOfFlight,
const G4ThreeVector& pMomentumDirection,
@@ -78,6 +78,51 @@ G4FieldTrack& G4FieldTrack::operator= ( const G4FieldTrack& rStVec )
return *this;
}
inline
G4FieldTrack::G4FieldTrack(G4FieldTrack&& from)
: fDistanceAlongCurve( from.fDistanceAlongCurve),
fKineticEnergy( from.fKineticEnergy ),
fRestMass_c2( from.fRestMass_c2),
fLabTimeOfFlight( from.fLabTimeOfFlight ),
fProperTimeOfFlight( from.fProperTimeOfFlight ),
fChargeState( from.fChargeState )
{
SixVector[0]= from.SixVector[0];
SixVector[1]= from.SixVector[1];
SixVector[2]= from.SixVector[2];
SixVector[3]= from.SixVector[3];
SixVector[4]= from.SixVector[4];
SixVector[5]= from.SixVector[5];
fPolarization = std::move( from.fPolarization );
fMomentumDir = std::move( from.fMomentumDir );
}
inline
G4FieldTrack& G4FieldTrack::operator=(G4FieldTrack&& from)
{
if (&from == this) return *this;
SixVector[0]= from.SixVector[0];
SixVector[1]= from.SixVector[1];
SixVector[2]= from.SixVector[2];
SixVector[3]= from.SixVector[3];
SixVector[4]= from.SixVector[4];
SixVector[5]= from.SixVector[5];
fDistanceAlongCurve = from.fDistanceAlongCurve;
fKineticEnergy = from.fKineticEnergy;
fRestMass_c2 = from.fRestMass_c2;
fLabTimeOfFlight = from.fLabTimeOfFlight;
fProperTimeOfFlight = from.fProperTimeOfFlight;
fChargeState = from.fChargeState;
fPolarization = std::move( from.fPolarization );
fMomentumDir = std::move( from.fMomentumDir );
return *this;
}
inline
G4FieldTrack::~G4FieldTrack()
{
@@ -67,12 +67,12 @@ class G4IntegrationDriver : public G4RKIntegrationDriver<T>,
virtual void OnStartTracking() override;
virtual void OnComputeStep() override {}
virtual G4bool DoesReIntegrate() override { return true; }
virtual G4bool DoesReIntegrate() const override { return true; }
virtual G4bool AccurateAdvance(G4FieldTrack& track,
G4double hstep,
G4double eps, // Requested y_err/hstep
G4double hinitial = 0) override;
G4double hinitial = 0 ) override;
// Integrates ODE from current s (s=s0) to s=s0+h with accuracy eps.
// On output track is replaced by value at end of interval.
// The concept is similar to the odeint routine from NRC p.721-722.
@@ -87,6 +87,9 @@ class G4IntegrationDriver : public G4RKIntegrationDriver<T>,
virtual void SetVerboseLevel(G4int newLevel) override;
virtual G4int GetVerboseLevel() const override;
virtual void StreamInfo( std::ostream& os ) const override;
// Write out the parameters / state of the driver
// Accessors
//
G4double GetMinimumStep() const;
@@ -383,3 +383,20 @@ void G4IntegrationDriver<T>::IncrementQuickAdvanceCalls()
{
++fNoQuickAvanceCalls;
}
template <class T>
void G4IntegrationDriver<T>::StreamInfo( std::ostream& os ) const
{
// Write out the parameters / state of the driver
os << "State of G4IntegrationDriver: " << std::endl;
os << "--Base state (G4RKIntegrationDriver): " << std::endl;
Base::StreamInfo( os );
os << "--Own state (G4IntegrationDriver<>): " << std::endl;
os << " fMinimumStep = " << fMinimumStep << std::endl;
os << " Smallest Fraction = " << fSmallestFraction << std::endl;
os << " verbose level = " << fVerboseLevel << std::endl;
os << " Reintegrates = " << DoesReIntegrate() << std::endl;
os << "--Chord Finder Delegate state: " << std::endl;
ChordFinderDelegate::StreamDelegateInfo( os );
}
@@ -0,0 +1,443 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// G4IntegrationDriver inline implementation
//
// Author: Dmitry Sorokin, Google Summer of Code 2017
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4FieldUtils.hh"
#include "G4DriverReporter.hh"
template <class T>
G4IntegrationDriver<T>::
G4IntegrationDriver ( G4double hminimum, T* pStepper,
G4int numComponents, G4int statisticsVerbose )
: G4RKIntegrationDriver<T>(pStepper),
fMinimumStep(hminimum),
fSmallestFraction(1e-12),
fVerboseLevel(statisticsVerbose),
fNoQuickAvanceCalls(0),
fNoAccurateAdvanceCalls(0),
fNoAccurateAdvanceBadSteps(0),
fNoAccurateAdvanceGoodSteps(0)
{
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;
}
#endif
}
template <class T>
G4double G4IntegrationDriver<T>::AdvanceChordLimited(G4FieldTrack& track,
G4double stepMax,
G4double epsStep,
G4double chordDistance)
{
return ChordFinderDelegate::AdvanceChordLimitedImpl(track, stepMax, epsStep,
chordDistance);
}
template <class T>
void G4IntegrationDriver<T>::OnStartTracking()
{
ChordFinderDelegate::ResetStepEstimate();
}
// Runge-Kutta driver with adaptive stepsize control. Integrate starting
// values at y_current over hstep x2 with accuracy eps.
// On output ystart is replaced by values at the end of the integration
// interval. RightHandSide is the right-hand side of ODE system.
// The source is similar to odeint routine from NRC p.721-722 .
//
template <class T>
G4bool G4IntegrationDriver<T>::
AccurateAdvance(G4FieldTrack& track, G4double hstep,
G4double eps, G4double hinitial)
{
++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)
{
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 dydx[G4FieldTrack::ncompSVEC];
G4bool succeeded = true, lastStepSucceeded;
G4int noFullIntegr = 0, noSmallIntegr = 0;
G4double y[G4FieldTrack::ncompSVEC];
track.DumpToArray(y);
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;
}
#ifdef G4DEBUG_FIELD
if (fVerboseLevel > 3)
G4cout << "IDriver::AccurAdv called. "
<< " Input: hstep = " << hstep << " hinitial= " << hinitial
<< " , current: h = " << h << G4endl;
#endif
G4double curveLength = startCurveLength;
for (G4int nstp = 0; nstp < Base::GetMaxNoSteps(); ++nstp)
{
const G4ThreeVector StartPos =
field_utils::makeVector(y, field_utils::Value3D::Position);
#ifdef G4DEBUG_FIELD
const int nvar= Base::GetStepper()->GetNumberOfVariables();
G4double xStepStart= curveLength; // Initial: track.GetCurveLength();
G4double yStepStart[G4FieldTrack::ncompSVEC];
for (int i=0; i<nvar; ++i) { yStepStart[i] = y[i]; }
// G4FieldTrack yFldTrkStart( StartPos,
// field_utils::makeVector(y, field_utils::Value3D::Momentum),
// ... );
// G4FieldTrack yFldTrkStart('0');
// yFldTrkStart.LoadFromArray(y, Base::GetStepper()->GetNumberOfVariables());
// yFldTrkStart.SetCurveLength(curveLength);
G4cout << "----- Iteration = " << nstp << G4endl; // + 1
#endif
Base::GetStepper()->RightHandSide(y, dydx);
if (h > GetMinimumStep())
{
OneGoodStep(y, dydx, curveLength, h, eps, hdid, hnext);
lastStepSucceeded = (hdid == h);
#ifdef G4DEBUG_FIELD
G4cout << "IntegrationDriver -- after OneGoodStep / requesting step = " << h << G4endl;
G4DriverReporter::PrintStatus( yStepStart, xStepStart, y, curveLength, h, nstp+1, nvar); // Only
#endif
}
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);
lastStepSucceeded = (dyerr <= eps);
}
if (lastStepSucceeded) { ++noFullIntegr; }
else { ++noSmallIntegr; }
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
// to ensure accuracy and adjust stepsize. Input are dependent variable
// array y[0,...,5] and its derivative dydx[0,...,5] at the
// starting value of the independent variable x . Also input are stepsize
// to be attempted htry, and the required accuracy eps. On output y and x
// are replaced by their new values, hdid is the stepsize that was actually
// accomplished, and hnext is the estimated next stepsize.
// This is similar to the function rkqs from the book:
// Numerical Recipes in C: The Art of Scientific Computing (NRC), Second
// Edition, by William H. Press, Saul A. Teukolsky, William T.
// Vetterling, and Brian P. Flannery (Cambridge University Press 1992),
// 16.2 Adaptive StepSize Control for Runge-Kutta, p. 719
//
template <class T>
void G4IntegrationDriver<T>::OneGoodStep(G4double y[], // InOut
const G4double dydx[],
G4double& curveLength, // InOut
G4double htry,
G4double eps_rel_max,
G4double& hdid, // Out
G4double& hnext) // Out
{
G4double error2 = DBL_MAX;
G4double yerr[G4FieldTrack::ncompSVEC], ytemp[G4FieldTrack::ncompSVEC];
G4double h = htry;
static G4ThreadLocal G4int tot_no_trials = 0;
const G4int max_trials = 100;
for (G4int iter = 0; iter < max_trials; ++iter)
{
tot_no_trials++;
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;
}
}
hnext = Base::GrowStepSize2(h, error2);
curveLength += (hdid = h);
field_utils::copy(y, ytemp, Base::GetStepper()->GetNumberOfVariables());
}
template <class T>
G4bool G4IntegrationDriver<T>::QuickAdvance(G4FieldTrack& track, // INOUT
const G4double dydx[],
G4double hstep,
G4double& dchord_step,
G4double& dyerr)
{
++fNoQuickAvanceCalls;
G4double yIn[G4FieldTrack::ncompSVEC],
yOut[G4FieldTrack::ncompSVEC],
yError[G4FieldTrack::ncompSVEC];
G4FieldTrack startTrack( track ); // For debugging
track.DumpToArray(yIn);
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);
#ifdef G4DEBUG_FIELD
// For debugging
static unsigned int numCall= 0;
G4cout // << "G4IntegratorDriver::"
<< "QuickAdvance call # " << ++numCall << G4endl
<< " Input: hstep= " << hstep << G4endl
<< " track= " << startTrack << G4endl
<< " Output: track= " << track << G4endl
<< " d_chord = " << dchord_step
<< " dyerr = " << dyerr << G4endl;
#endif
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);
}
}
template <class T>
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;
#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
{
++fNoAccurateAdvanceGoodSteps;
}
}
template <class T>
inline G4double G4IntegrationDriver<T>::GetMinimumStep() const
{
return fMinimumStep;
}
template <class T>
void G4IntegrationDriver<T>::SetMinimumStep(G4double minimumStepLength)
{
fMinimumStep = minimumStepLength;
}
template <class T>
G4int G4IntegrationDriver<T>::GetVerboseLevel() const
{
return fVerboseLevel;
}
template <class T>
void G4IntegrationDriver<T>::SetVerboseLevel(G4int newLevel)
{
fVerboseLevel = newLevel;
}
template <class T>
G4double G4IntegrationDriver<T>::GetSmallestFraction() const
{
return fSmallestFraction;
}
template <class T>
void G4IntegrationDriver<T>::IncrementQuickAdvanceCalls()
{
++fNoQuickAvanceCalls;
}
template <class T>
void G4IntegrationDriver<T>::StreamInfo( std::ostream& os ) const
{
// Write out the parameters / state of the driver
os << "State of G4IntegrationDriver: " << std::endl;
os << "--Base state (G4RKIntegrationDriver): " << std::endl;
Base::StreamInfo( os );
os << "--Own state (G4IntegrationDriver<>): " << std::endl;
os << " fMinimumStep = " << fMinimumStep << std::endl;
os << " Smallest Fraction = " << fSmallestFraction << std::endl;
os << " verbose level = " << fVerboseLevel << std::endl;
os << " Reintegrates = " << DoesReIntegrate() << std::endl;
os << "--Chord Finder Delegate state: " << std::endl;
ChordFinderDelegate::StreamDelegateInfo( os );
}
@@ -65,7 +65,7 @@ class G4InterpolationDriver : public G4RKIntegrationDriver<T>
virtual void OnStartTracking() override;
virtual void OnComputeStep() override;
virtual G4bool DoesReIntegrate() override { return false; }
virtual G4bool DoesReIntegrate() const override { return false; }
// Interpolation driver does not recalculate when AccurateAdvance is called
// -- reintegration would require other calls
@@ -80,6 +80,8 @@ class G4InterpolationDriver : public G4RKIntegrationDriver<T>
virtual void SetVerboseLevel(G4int level) override;
virtual G4int GetVerboseLevel() const override;
virtual void StreamInfo( std::ostream& os ) const override;
private:
struct InterpStepper
@@ -388,7 +388,9 @@ G4double G4InterpolationDriver<T>::CalcChordStep(G4double stepTrialOld,
template <class T>
G4bool G4InterpolationDriver<T>::
AccurateAdvance(G4FieldTrack& track, G4double hstep,
G4double /*eps*/, G4double /*hinitial*/)
G4double /*eps*/,
G4double /*hinitial*/
)
{
if (hstep == 0.0)
{
@@ -574,3 +576,24 @@ void G4InterpolationDriver<T>::AccumulateStatistics(G4int noTrials)
}
}
template <class T>
void G4InterpolationDriver<T>::StreamInfo( std::ostream& os ) const
{
os << "State of G4InterpolationDriver: " << std::endl;
os << "--Base state (G4RKIntegrationDriver): " << std::endl;
Base::StreamInfo( os );
os << " fMinimumStep = " << fMinimumStep << std::endl;
// os << " Max number of Steps = " << fMaxNoSteps << std::endl;
// os << " Safety factor = " << safety << std::endl;
// os << " Power - shrink = " << pshrnk << std::endl;
// os << " Power - grow = " << pgrow << std::endl;
// os << " threshold - shrink = " << errorConstraintShrink << std::endl;
// os << " threshold - grow = " << errorConstraintGrow << std::endl;
os << " Max num of Trials = " << fMaxTrials << std::endl;
os << " Fract Next Estimate = " << fFractionNextEstimate << std::endl;
os << " Smallest Curve Fract= " << fSmallestCurveFraction << std::endl;
os << " VerboseLevel = " << fVerboseLevel << std::endl;
os << " KeepLastStepper = " << fKeepLastStepper << std::endl;
}
@@ -63,7 +63,7 @@ class G4MagInt_Driver : public G4VIntegrationDriver,
inline virtual void OnStartTracking() override;
inline virtual void OnComputeStep() override {};
virtual G4bool DoesReIntegrate() override { return true; }
virtual G4bool DoesReIntegrate() const override { return true; }
virtual G4bool AccurateAdvance(G4FieldTrack& y_current,
G4double hstep,
@@ -82,6 +82,9 @@ class G4MagInt_Driver : public G4VIntegrationDriver,
G4double& dyerr) override;
// QuickAdvance just tries one Step - it does not ensure accuracy.
void StreamInfo( std::ostream& os ) const override;
// Write out the parameters / state of the driver
G4bool QuickAdvance(G4FieldTrack& y_posvel, // INOUT
const G4double dydx[],
G4double hstep, // IN
@@ -146,9 +149,18 @@ class G4MagInt_Driver : public G4VIntegrationDriver,
G4double hstepCurrent) override;
// Taking the last step's normalised error, calculate
// a step size for the next step.
// Do not limit the next step's size within a factor of the
// current one.
// Does it limit the next step's size within a factor of the current?
// -- DOES NOT limit for very bad steps
// -- DOES limit for very good (x5)
G4double
ComputeNewStepSize_WithoutReductionLimit(G4double errMaxNorm,
G4double hstepCurrent);
// Taking the last step's normalised error, calculate
// a step size for the next step.
// Do not limit the next step's size within a factor of the
// current one when *reducing* the size, i.e. for badly failing steps.
G4double ComputeNewStepSize_WithinLimits(G4double errMaxNorm, // normalised
G4double hstepCurrent);
// Taking the last step's normalised error, calculate
@@ -55,7 +55,8 @@ class G4NystromRK4 : public G4MagIntegratorStepper
G4NystromRK4(G4Mag_EqRhs* EquationMotion,
G4double distanceConstField = 0.0);
// Can be used only for Magnetic Fields - and for 6 variables (x,p)
~G4NystromRK4() {}
virtual void Stepper(const G4double y[],
const G4double dydx[],
G4double hstep,
@@ -0,0 +1,268 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// G4OldMagIntDriver
//
// Class description:
//
// Provides a driver that talks to the Integrator Stepper, and insures that
// the error is within acceptable bounds.
// V.Grichine, 07.10.1996 - Created
// W.Wander, 28.01.1998 - Added ability for low order integrators
// J.Apostolakis, 08.11.2001 - Respect minimum step in AccurateAdvance
// --------------------------------------------------------------------
#ifndef G4OLD_MAGINT_DRIVER_HH
#define G4OLD_MAGINT_DRIVER_HH
#include "G4VIntegrationDriver.hh"
#include "G4MagIntegratorStepper.hh"
#include "G4ChordFinderDelegate.hh"
class G4OldMagIntDriver : public G4VIntegrationDriver,
public G4ChordFinderDelegate<G4OldMagIntDriver>
{
public: // with description
G4OldMagIntDriver(G4double hminimum,
G4MagIntegratorStepper* pItsStepper,
G4int numberOfComponents = 6,
G4int statisticsVerbosity = 0);
virtual ~G4OldMagIntDriver() override;
// Constructor, destructor.
G4OldMagIntDriver(const G4OldMagIntDriver&) = delete;
G4OldMagIntDriver& operator=(const G4OldMagIntDriver&) = delete;
inline virtual G4double AdvanceChordLimited(G4FieldTrack& track,
G4double stepMax,
G4double epsStep,
G4double chordDistance) override;
inline virtual void OnStartTracking() override;
inline virtual void OnComputeStep() override {};
virtual G4bool DoesReIntegrate() const override { return true; }
virtual G4bool AccurateAdvance(G4FieldTrack& y_current,
G4double hstep,
G4double eps, // Requested y_err/hstep
G4double hinitial = 0.0) override;
// Above drivers for integrator (Runge-Kutta) with stepsize control.
// Integrates ODE starting values y_current
// from current s (s=s0) to s=s0+h with accuracy eps.
// On output ystart is replaced by value at end of interval.
// The concept is similar to the odeint routine from NRC p.721-722.
virtual G4bool QuickAdvance(G4FieldTrack& y_val, // INOUT
const G4double dydx[],
G4double hstep,
G4double& dchord_step,
G4double& dyerr) override;
// QuickAdvance just tries one Step - it does not ensure accuracy.
G4bool QuickAdvance(G4FieldTrack& y_posvel, // INOUT
const G4double dydx[],
G4double hstep, // IN
G4double& dchord_step,
G4double& dyerr_pos_sq,
G4double& dyerr_mom_rel_sq );
// New QuickAdvance that also just tries one Step
// (so also does not ensure accuracy)
// but does return the errors in position and
// momentum (normalised: Delta_Integration(p^2)/(p^2) )
inline G4double GetHmin() const;
inline G4double Hmin() const; // Obsolete
inline G4double GetSafety() const;
inline G4double GetPshrnk() const;
inline G4double GetPgrow() const;
inline G4double GetErrcon() const;
virtual void GetDerivatives(const G4FieldTrack& y_curr, // INput
G4double dydx[]) const override; // OUTput
virtual void GetDerivatives(const G4FieldTrack& track,
G4double dydx[],
G4double field[]) const override;
// Accessors
virtual G4EquationOfMotion* GetEquationOfMotion() override;
virtual void SetEquationOfMotion(G4EquationOfMotion* equation) override;
virtual void RenewStepperAndAdjust(G4MagIntegratorStepper* pItsStepper) override;
// Sets a new stepper pItsStepper for this driver. Then it calls
// ReSetParameters to reset its parameters accordingly.
inline void ReSetParameters(G4double new_safety = 0.9);
// i) sets the exponents (pgrow & pshrnk),
// using the current Stepper's order,
// ii) sets the safety
// ii) calculates "errcon" according to the above values.
inline void SetSafety(G4double valS);
inline void SetPshrnk(G4double valPs);
inline void SetPgrow (G4double valPg);
inline void SetErrcon(G4double valEc);
// When setting safety or pgrow, errcon will be set to a compatible value.
inline G4double ComputeAndSetErrcon();
virtual const G4MagIntegratorStepper* GetStepper() const override;
virtual G4MagIntegratorStepper* GetStepper() override;
void OneGoodStep(G4double ystart[], // Like old RKF45step()
const G4double dydx[],
G4double& x,
G4double htry,
G4double eps, // memb variables ?
G4double& hdid,
G4double& hnext ) ;
// This takes one Step that is as large as possible while
// satisfying the accuracy criterion of:
// yerr < eps * |y_end-y_start|
virtual G4double ComputeNewStepSize(G4double errMaxNorm, // normalised
G4double hstepCurrent) override;
// Taking the last step's normalised error, calculate
// a step size for the next step.
// Do not limit the next step's size within a factor of the
// current one.
void StreamInfo( std::ostream& os ) const override;
G4double ComputeNewStepSize_WithinLimits(G4double errMaxNorm, // normalised
G4double hstepCurrent);
// Taking the last step's normalised error, calculate
// a step size for the next step.
// Limit the next step's size within a range around the current one.
inline G4int GetMaxNoSteps() const;
inline void SetMaxNoSteps(G4int val);
// Modify and Get the Maximum number of Steps that can be
// taken for the integration of a single segment -
// (i.e. a single call to AccurateAdvance).
public: // without description
inline void SetHmin(G4double newval);
virtual void SetVerboseLevel(G4int newLevel) override;
virtual G4int GetVerboseLevel() const override;
inline G4double GetSmallestFraction() const;
void SetSmallestFraction( G4double val );
protected: // without description
void WarnSmallStepSize(G4double hnext, G4double hstep,
G4double h, G4double xDone,
G4int noSteps);
void WarnTooManyStep(G4double x1start, G4double x2end, G4double xCurrent);
void WarnEndPointTooFar(G4double endPointDist,
G4double hStepSize ,
G4double epsilonRelative,
G4int debugFlag);
// Issue warnings for undesirable situations
void PrintStatus(const G4double* StartArr,
G4double xstart,
const G4double* CurrentArr,
G4double xcurrent,
G4double requestStep,
G4int subStepNo);
void PrintStatus(const G4FieldTrack& StartFT,
const G4FieldTrack& CurrentFT,
G4double requestStep,
G4int subStepNo);
void PrintStat_Aux(const G4FieldTrack& aFieldTrack,
G4double requestStep,
G4double actualStep,
G4int subStepNo,
G4double subStepSize,
G4double dotVelocities);
// Verbose output for debugging
void PrintStatisticsReport();
// Report on the number of steps, maximum errors etc.
#ifdef QUICK_ADV_TWO
G4bool QuickAdvance( G4double yarrin[], // In
const G4double dydx[],
G4double hstep,
G4double yarrout[], // Out
G4double& dchord_step, // Out
G4double& dyerr ); // in length
#endif
private:
// ---------------------------------------------------------------
// INVARIANTS
G4double fMinimumStep = 0.0;
// Minimum Step allowed in a Step (in absolute units)
G4double fSmallestFraction = 1.0e-12; // Expected range 1e-12 to 5e-15
// Smallest fraction of (existing) curve length - in relative units
// below this fraction the current step will be the last
const G4int fNoIntegrationVariables = 0; // Variables in integration
const G4int fMinNoVars = 12; // Minimum number for FieldTrack
const G4int fNoVars = 0; // Full number of variable
G4int fMaxNoSteps;
G4int fMaxStepBase = 250; // was 5000
// Default maximum number of steps is Base divided by the order of Stepper
G4double safety;
G4double pshrnk; // exponent for shrinking
G4double pgrow; // exponent for growth
G4double errcon;
// Parameters used to grow and shrink trial stepsize.
G4int fStatisticsVerboseLevel = 0;
// ---------------------------------------------------------------
// DEPENDENT Objects
G4MagIntegratorStepper* pIntStepper = nullptr;
// ---------------------------------------------------------------
// STATE
unsigned long fNoTotalSteps=0, fNoBadSteps=0;
unsigned long fNoSmallSteps=0, fNoInitialSmallSteps=0, fNoCalls=0;
G4double fDyerr_max=0.0, fDyerr_mx2=0.0;
G4double fDyerrPos_smTot=0.0, fDyerrPos_lgTot=0.0, fDyerrVel_lgTot=0.0;
G4double fSumH_sm=0.0, fSumH_lg=0.0;
// Step Statistics
G4int fVerboseLevel = 0; // Verbosity level for printing (debug, ..)
// Could be varied during tracking - to help identify issues
using ChordFinderDelegate = G4ChordFinderDelegate<G4OldMagIntDriver>;
};
#include "G4OldMagIntDriver.icc"
#endif
@@ -0,0 +1,152 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// G4OldMagIntDriver inline methods implementation
//
// V.Grichine, 07.10.1996 - Created
// --------------------------------------------------------------------
inline
G4double G4OldMagIntDriver::
AdvanceChordLimited(G4FieldTrack& track, G4double stepMax,
G4double epsStep, G4double chordDistance)
{
return ChordFinderDelegate::AdvanceChordLimitedImpl(track, stepMax,
epsStep, chordDistance);
}
inline
void G4OldMagIntDriver::OnStartTracking()
{
ChordFinderDelegate::ResetStepEstimate();
}
inline
G4double G4OldMagIntDriver::GetHmin() const
{
return fMinimumStep;
}
inline
G4double G4OldMagIntDriver::Hmin() const
{
return fMinimumStep;
}
inline
G4double G4OldMagIntDriver::GetSafety() const
{
return safety;
}
inline
G4double G4OldMagIntDriver::GetPshrnk() const
{
return pshrnk;
}
inline
G4double G4OldMagIntDriver::GetPgrow() const
{
return pgrow;
}
inline
G4double G4OldMagIntDriver::GetErrcon() const
{
return errcon;
}
inline
void G4OldMagIntDriver::SetHmin(G4double newval)
{
fMinimumStep = newval;
}
inline
G4double G4OldMagIntDriver::ComputeAndSetErrcon()
{
errcon = std::pow(max_stepping_increase/GetSafety(),1.0/GetPgrow());
return errcon;
}
inline
void G4OldMagIntDriver::ReSetParameters(G4double new_safety)
{
safety = new_safety;
pshrnk = -1.0 / pIntStepper->IntegratorOrder();
pgrow = -1.0 / (1.0 + pIntStepper->IntegratorOrder());
ComputeAndSetErrcon();
}
inline
void G4OldMagIntDriver::SetSafety(G4double val)
{
safety = val;
ComputeAndSetErrcon();
}
inline
void G4OldMagIntDriver::SetPgrow(G4double val)
{
pgrow = val;
ComputeAndSetErrcon();
}
inline
void G4OldMagIntDriver::SetErrcon(G4double val)
{
errcon = val;
}
inline
G4int G4OldMagIntDriver::GetMaxNoSteps() const
{
return fMaxNoSteps;
}
inline
void G4OldMagIntDriver::SetMaxNoSteps(G4int val)
{
fMaxNoSteps = val;
}
inline
G4int G4OldMagIntDriver::GetVerboseLevel() const
{
return fVerboseLevel;
}
inline
void G4OldMagIntDriver::SetVerboseLevel(G4int newLevel)
{
fVerboseLevel = newLevel;
}
inline
G4double G4OldMagIntDriver::GetSmallestFraction() const
{
return fSmallestFraction;
}
@@ -55,10 +55,10 @@ class G4RKIntegrationDriver : public G4VIntegrationDriver
G4double field[]) const override;
virtual G4double ComputeNewStepSize(G4double errMaxNorm, // normalised error
G4double hstepCurrent) override;
G4double hstepCurrent) override final;
// Taking the last step's normalised error, calculate
// a step size for the next step.
// Do not limit the next step's size within a factor of the current one.
// - Limits the next step's size within a factor of the current one.
virtual G4EquationOfMotion* GetEquationOfMotion() override;
virtual void SetEquationOfMotion(G4EquationOfMotion* equation) override;
@@ -66,6 +66,8 @@ class G4RKIntegrationDriver : public G4VIntegrationDriver
virtual const T* GetStepper() const override;
virtual T* GetStepper() override;
virtual void StreamInfo( std::ostream& os ) const override;
// Accessors.
G4double GetSafety() const;
G4double GetPshrnk() const;
@@ -223,3 +223,15 @@ void G4RKIntegrationDriver<T>::SetEquationOfMotion(G4EquationOfMotion* equation)
{
pIntStepper->SetEquationOfMotion(equation);
}
template <class T>
void G4RKIntegrationDriver<T>::StreamInfo( std::ostream& os ) const
{
os << "State of G4RKIntegrationDriver: " << std::endl;
os << " Max number of Steps = " << fMaxNoSteps << std::endl;
os << " Safety factor = " << safety << std::endl;
os << " Power - shrink = " << pshrnk << std::endl;
os << " Power - grow = " << pgrow << std::endl;
os << " threshold - shrink = " << errorConstraintShrink << std::endl;
os << " threshold - grow = " << errorConstraintGrow << std::endl;
}
@@ -62,7 +62,7 @@ class G4VIntegrationDriver
virtual G4bool AccurateAdvance(G4FieldTrack& track,
G4double hstep,
G4double eps, // Requested y_err/hstep
G4double hinitial = 0) = 0;
G4double hinitial = 0 ) = 0;
virtual void SetEquationOfMotion(G4EquationOfMotion* equation) = 0;
virtual G4EquationOfMotion* GetEquationOfMotion() = 0;
@@ -104,13 +104,19 @@ class G4VIntegrationDriver
G4double hstepCurrent) = 0;
// Taking the last step's normalised error, calculate
// a step size for the next step.
// Do not limit the next step's size within a factor of the current one.
// - Can limit the next step's size within a factor of the current one.
virtual G4bool DoesReIntegrate() = 0;
virtual G4bool DoesReIntegrate() const = 0;
// Whether the driver implementates re-integration
// - original Integration driver will re-start and re-calculate interval => yes
// - Interpolation Driver does not recalculate (it interpolates)
// Basically answer: does this driver *Recalculate* when AccurateAdvance is called ?
virtual void StreamInfo( std::ostream& os ) const = 0;
// Write out the parameters / state of the driver
friend std::ostream& operator<<( std::ostream& os, const G4VIntegrationDriver& id);
protected:
static constexpr G4double max_stepping_increase = 5;