Import Geant4 10.4.0 source tree

This commit is contained in:
Gabriele Cosmo
2017-12-08 12:52:30 +01:00
parent 98e455a940
commit fc6af9e721
2166 changed files with 276760 additions and 100873 deletions
@@ -68,12 +68,11 @@ class G4BogackiShampine23 : public G4MagIntegratorStepper{
G4double DistChord() const;
G4int IntegratorOrder() const { return 2; }
G4bool isFSAL() const{ return true; }
G4double *getLastDydx();
G4BogackiShampine23(const G4BogackiShampine23&);
G4BogackiShampine23& operator=(const G4BogackiShampine23&);
G4double *getLastDydx();
private:
G4BogackiShampine23(const G4BogackiShampine23&) = delete;
G4BogackiShampine23& operator=(const G4BogackiShampine23&) = delete;
private:
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4ChordFinder.hh 69699 2013-05-13 08:50:30Z gcosmo $
// $Id: G4ChordFinder.hh 107470 2017-11-15 07:14:28Z gcosmo $
//
//
// Class G4ChordFinder
@@ -42,8 +42,10 @@
#ifndef G4CHORDFINDER_HH
#define G4CHORDFINDER_HH
#include "G4MagIntegratorDriver.hh"
#include "G4FieldTrack.hh"
#include "G4VIntegrationDriver.hh"
#include "G4MagIntegratorStepper.hh"
class G4VFSALIntegrationStepper;
// #include "G4VFSALIntegratorSteper.hh"
class G4MagneticField;
@@ -51,11 +53,13 @@ class G4ChordFinder
{
public: // with description
G4ChordFinder( G4MagInt_Driver* pIntegrationDriver );
explicit G4ChordFinder( G4VIntegrationDriver* pIntegrationDriver );
G4ChordFinder( G4MagneticField* itsMagField,
G4double stepMinimum = 1.0e-2, // * mm
G4MagIntegratorStepper* pItsStepper = 0 );
G4MagIntegratorStepper* pItsStepper = nullptr,
// G4bool useHigherEfficiencyStepper = true,
G4bool useFSALstepper = false );
// A constructor that creates defaults for all "children" classes.
virtual ~G4ChordFinder();
@@ -63,7 +67,7 @@ class G4ChordFinder
G4double AdvanceChordLimited( G4FieldTrack& yCurrent,
G4double stepInitial,
G4double epsStep_Relative,
const G4ThreeVector latestSafetyOrigin,
const G4ThreeVector& latestSafetyOrigin,
G4double lasestSafetyRadius);
// Uses ODE solver's driver to find the endpoint that satisfies
// the chord criterion: that d_chord < delta_chord
@@ -89,8 +93,8 @@ class G4ChordFinder
inline G4double GetDeltaChord() const;
inline void SetDeltaChord(G4double newval);
inline void SetIntegrationDriver(G4MagInt_Driver* IntegrationDriver);
inline G4MagInt_Driver* GetIntegrationDriver();
inline void SetIntegrationDriver(G4VIntegrationDriver* IntegrationDriver);
inline G4VIntegrationDriver* GetIntegrationDriver();
// Access and set Driver.
inline void ResetStepEstimate();
@@ -180,10 +184,11 @@ class G4ChordFinder
// DEPENDENT Objects
// ---------------------
G4MagInt_Driver* fIntgrDriver;
G4MagIntegratorStepper* fDriversStepper;
G4bool fAllocatedStepper; // Bookkeeping of dependent object
G4EquationOfMotion* fEquation;
G4VIntegrationDriver* fIntgrDriver;
G4MagIntegratorStepper* fRegularStepperOwned= nullptr;
G4MagIntegratorStepper* fNewFSALStepperOwned= nullptr;
// G4VFSALIntegrationStepper* fOldFSALStepperOwned= nullptr;
G4EquationOfMotion* fEquation;
// STATE information
// --------------------
@@ -24,20 +24,20 @@
// ********************************************************************
//
//
// $Id: G4ChordFinder.icc 69699 2013-05-13 08:50:30Z gcosmo $
// $Id: G4ChordFinder.icc 107059 2017-11-01 14:58:16Z gcosmo $
//
// G4ChordFinder inline implementations
//
// --------------------------------------------------------------------
inline
void G4ChordFinder::SetIntegrationDriver(G4MagInt_Driver* IntegrationDriver)
void G4ChordFinder::SetIntegrationDriver(G4VIntegrationDriver* IntegrationDriver)
{
fIntgrDriver=IntegrationDriver;
}
inline
G4MagInt_Driver* G4ChordFinder::GetIntegrationDriver()
G4VIntegrationDriver* G4ChordFinder::GetIntegrationDriver()
{
return fIntgrDriver;
}
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4ChordFinderSaf.hh 66356 2012-12-18 09:02:32Z gcosmo $
// $Id: G4ChordFinderSaf.hh 107059 2017-11-01 14:58:16Z gcosmo $
//
//
// class G4ChordFinderRad
@@ -43,7 +43,7 @@ class G4ChordFinderSaf : public G4ChordFinder
{
public:
G4ChordFinderSaf(G4MagInt_Driver* pIntegrationDriver);
G4ChordFinderSaf(G4VIntegrationDriver* pIntegrationDriver);
G4ChordFinderSaf( G4MagneticField* theMagField,
G4double stepMinimum,
@@ -29,18 +29,6 @@
// Sponsored by Google in Google Summer of Code 2015.
//
// First version: 26 June 2015
//
// This code is made available subject to the Geant4 license, a copy of
// which is available at
// http://geant4.org/license
// G4DormandPrince745.cc
// Geant4
//
// History
// -----------------------------
// Created by Somnath on 26 June 2015
//
//
///////////////////////////////////////////////////////////////////////////////
#ifndef DORMAND_PRINCE_RK56_H
@@ -48,8 +36,8 @@
#include "G4MagIntegratorStepper.hh"
class G4DormandPrinceRK56 : public G4MagIntegratorStepper{
class G4DormandPrinceRK56 : public G4MagIntegratorStepper
{
public:
//constructor
@@ -23,7 +23,24 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4DormandPrinceRK78.hh
// Description of G4DormandPrinceRK78 class
//
// Implementation of Dormand-Prince 8(7)13M non-FSAL RK method
// Author: Somnath Banerjee
// Supported by Google as part of Google Summer of Code 2015.
// Supervision / code review: John Apostolakis
//
// Implements a 13 stage embedded explicit Runge-Kutta method,
// using a pair of 7th and 8th order formulae
//
// Paper proposing this RK scheme:
// Title: "High order embedded Runge-Kutta formulae",
// Authors: P.J. Prince, J.R. Dormand
// Journal of Computational and Applied Mathematics, Volume 7, Issue 1, 1981,
// Pages 67-75, ISSN 0377-0427,
// Reference: DOI: 10.1016/0771-050X(81)90010-3
// http://dx.doi.org/10.1016/0771-050X(81)90010-3.
// (http://www.sciencedirect.com/science/article/pii/0771050X81900103)
//
// Created by Somnath on 30/06/15.
@@ -28,14 +28,13 @@
//
// Sponsored by Google in Google Summer of Code 2015.
//
// First version: 26 May 2015
//
// History
// -----------------------------
// Created by Somnath on 26 May 2015
//
//
///////////////////////////////////////////////////////////////////////////////
// Created by Somnath Banerjee on 26 May 2015
// Fixes:
// J. Apostolakis - June 2017: Coverity issues
// J. Apostolakis - July 2017: Initialise bi coefficients only once.
////////////////////////////////////////////////////////////////////////
#ifndef G4FSAL_Bogacki_Shampine_45_hh
#define G4FSAL_Bogacki_Shampine_45_hh
@@ -67,22 +66,29 @@ public:
G4double DistChord() const;
G4int IntegratorOrder() const { return 4; }
private :
G4FSALBogackiShampine45(const G4FSALBogackiShampine45&);
G4FSALBogackiShampine45& operator=(const G4FSALBogackiShampine45&);
G4double *ak2, *ak3, *ak4, *ak5, *ak6, *ak7, *ak8,
*ak9, *ak10, *ak11,
*yTemp, *yIn;
private :
G4FSALBogackiShampine45(const G4FSALBogackiShampine45&) = delete;
G4FSALBogackiShampine45& operator=(const G4FSALBogackiShampine45&) = delete;
void PrepareConstants();
// Working arrays -- used during stepping
G4double *ak2, *ak3, *ak4, *ak5, *ak6, *ak7, *ak8, *ak9, *ak10, *ak11,
*DyDx, *yTemp, *yIn;
G4double *pseudoDydx_for_DistChord;
G4double fLastStepLength;
G4double *fLastInitialVector, *fLastFinalVector,
*fLastDyDx, *fMidVector, *fMidError;
*fLastDyDx, *fMidVector, *fMidError;
// for DistChord calculations
G4double b[12]; // Working array for interpolation
G4FSALBogackiShampine45* fAuxStepper;
static bool fPreparedConstants;
// Class constants
static G4double bi[12][7];
};
#endif /* defined( G4FSAL_Bogacki_Shampine_45_hh ) */
@@ -88,15 +88,15 @@ private :
G4FSALDormandPrince745& operator=(const G4FSALDormandPrince745&);
G4double *ak2, *ak3, *ak4, *ak5, *ak6, *ak7,
*ak8, *ak9, //For additional stages in the interpolant
*yTemp, *yIn;
*ak8, *ak9, //For additional stages in the interpolant
*yTemp, *yIn;
//Only for use with DistChord :-
G4double *pseudoDydx_for_DistChord;
G4double fLastStepLength;
G4double *fLastInitialVector, *fLastFinalVector,
*fLastDyDx, *fMidVector, *fMidError;
*fInitialDyDx, *fLastDyDx, *fMidVector, *fMidError;
// for DistChord calculations
G4FSALDormandPrince745* fAuxStepper;
@@ -24,245 +24,168 @@
// ********************************************************************
//
//
// $Id: G4FSALIntegrationDriver.hh 97387 2016-06-02 10:03:42Z gcosmo $
// $Id: G4FSALIntegrationDriver.hh 107164 2017-11-03 12:11:45Z gcosmo $
//
//
// class G4FSALIntegrationDriver
//
// Class description:
//
// Provides a driver that talks to the Integrator Stepper, and insures that
// the error is within acceptable bounds.
// Driver class which controls the integration error of a
// Runge-Kutta stepper with a FSAL property
// History:
// - Created. J.Apostolakis.
// - Created. D.Sorokin
// --------------------------------------------------------------------
#ifndef G4FSALIntegrationDriver_Def
#define G4FSALIntegrationDriver_Def
#ifndef G4FSALIntegrationDriver_HH
#define G4FSALIntegrationDriver_HH
#include "G4Types.hh"
#include "G4FieldTrack.hh"
#include "G4VFSALIntegrationStepper.hh"
#include "G4VIntegrationDriver.hh"
class G4FSALIntegrationDriver
{
public: // with description
template <class T>
class G4FSALIntegrationDriver : public G4VIntegrationDriver {
public:
G4FSALIntegrationDriver(
G4double hminimum,
T* stepper,
G4int numberOfComponents = 6,
G4int statisticsVerbosity = 1);
G4bool AccurateAdvance(G4FieldTrack& y_current,
G4double hstep,
G4double eps, // Requested y_err/hstep
G4double hinitial=0.0); // Suggested 1st interval
// 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 ~G4FSALIntegrationDriver() override;
G4bool QuickAdvance( G4FieldTrack& y_val, // INOUT
G4double dydx[],
G4double hstep, // IN
G4double& dchord_step,
G4double& dyerr ) ;
// QuickAdvance just tries one Step - it does not ensure accuracy.
G4FSALIntegrationDriver(const G4FSALIntegrationDriver &) = delete;
const G4FSALIntegrationDriver& operator =(const G4FSALIntegrationDriver &) = delete;
G4bool QuickAdvance( G4FieldTrack& y_posvel, // INOUT
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) )
// 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.
virtual G4bool AccurateAdvance(
G4FieldTrack& track,
G4double hstep,
G4double eps, // Requested y_err/hstep
G4double hinitial = 0) override; // Suggested 1st interval
G4FSALIntegrationDriver( G4double hminimum,
G4VFSALIntegrationStepper *pItsStepper,
G4int numberOfComponents=6,
G4int statisticsVerbosity=1);
~G4FSALIntegrationDriver();
// Constructor, destructor.
// QuickAdvance just tries one Step - it does not ensure accuracy.
virtual G4bool QuickAdvance(
G4FieldTrack& fieldTrack,
const G4double dydx[],
G4double hstep,
G4double& dchord_step,
G4double& dyerr) override;
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;
inline G4int GetNoTotalSteps() const; //Only for debug purposes
inline void GetDerivatives( const G4FieldTrack &y_curr, // const, INput
G4double dydx[] ); // OUTput
// Accessors.
virtual void GetDerivatives(
const G4FieldTrack &track,
G4double dydx[]) const override;
inline void RenewStepperAndAdjust(G4VFSALIntegrationStepper *pItsStepper);
// Sets a new stepper pItsStepper for this driver. Then it calls
// ReSetParameters to reset its parameters accordingly.
// 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.
virtual G4double ComputeNewStepSize(
G4double errMaxNorm, // normalised error
G4double hstepCurrent) override; // current step size
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.
virtual void SetVerboseLevel(G4int newLevel) override;
virtual G4int GetVerboseLevel() const override;
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.
virtual G4EquationOfMotion* GetEquationOfMotion() override;
virtual void SetEquationOfMotion(G4EquationOfMotion* equation) override;
inline G4double ComputeAndSetErrcon();
virtual const G4MagIntegratorStepper* GetStepper() const override;
virtual G4MagIntegratorStepper* GetStepper() override;
const T* GetStepperOfPreciseType() const; // Get ptr of precise type
T* GetStepperOfPreciseType();
// Accessors.
G4double GetMinimumStep() const;
G4double GetSafety() const;
G4double GetPshrnk() const;
G4double GetPgrow() const;
inline const G4VFSALIntegrationStepper* GetStepper() const;
inline G4VFSALIntegrationStepper* GetStepper();
// Sets a new stepper pItsStepper for this driver. Then it calls
// ReSetParameters to reset its parameters accordingly.
void RenewStepperAndAdjust(T *pItsStepper);
void OneGoodStep( G4double ystart[], // Like old RKF45step()
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|
// i) sets the exponents (pgrow & pshrnk),
// using the current Stepper's order,
// ii) sets the safety
void ReSetParameters(G4double safety = 0.9);
G4double ComputeNewStepSize( G4double errMaxNorm, // normalised error
G4double hstepCurrent); // current step size
// 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.
G4double ComputeNewStepSize_WithinLimits(
G4double errMaxNorm, // normalised error
G4double hstepCurrent); // current step size
// 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.
void SetMinimumStep(G4double newval);
void SetSafety(G4double valS);
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 -
// (ie a single call to AccurateAdvance).
//---------------------------------------------------------------------
//The following has been introduced by [hackabot] for testing purposes only
inline G4int GetTotalNoStepperCalls() const;
//---------------------------------------------------------------------
// This takes one Step that is as large as possible while
// satisfying the accuracy criterion of:
// yerr < eps * |y_end-y_start|
void OneGoodStep(
G4double ystart[],
G4double dydx[],
G4double& curveLength,
G4double htry,
G4double eps,
G4double& hdid,
G4double& hnext);
public: // without description
// Modify and Get the Maximum number of Steps that can be
// taken for the integration of a single segment -
// (ie a single call to AccurateAdvance).
G4int GetMaxNoSteps() const;
void SetMaxNoSteps( G4int val);
inline void SetHmin(G4double newval);
inline void SetVerboseLevel(G4int newLevel);
inline G4double GetVerboseLevel() const;
G4double GetSmallestFraction() const;
void SetSmallestFraction(G4double val);
inline G4double GetSmallestFraction() const;
void SetSmallestFraction( G4double val );
private:
G4double ShrinkStepSize(G4double h, G4double error) const;
G4double GrowStepSize(G4double h, G4double error) const;
void UpdateErrorConstraints();
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:
G4FSALIntegrationDriver(const G4FSALIntegrationDriver&);
G4FSALIntegrationDriver& operator=(const G4FSALIntegrationDriver&);
// Private copy constructor and assignment operator.
private:
// ---------------------------------------------------------------
// INVARIANTS
void CheckStep(
const G4ThreeVector& posIn, const G4ThreeVector& posOut, G4double hdid);
// Minimum Step allowed in a Step (in absolute units)
G4double fMinimumStep;
// Minimum Step allowed in a Step (in absolute units)
G4double fSmallestFraction; // 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; // Number of Variables in integration
const G4int fMinNoVars; // Minimum number for FieldTrack
const G4int fNoVars; // Full number of variable
// Smallest fraction of (existing) curve length - in relative units
// below this fraction the current step will be the last
// Expected range 1e-12 to 5e-15;
G4double fSmallestFraction;
G4int fMaxNoSteps;
static const G4int fMaxStepBase;
// The (default) maximum number of steps is Base
// divided by the order of Stepper
static constexpr G4int fMaxStepBase = 250;
// Parameters used to grow and shrink trial stepsize.
G4double safety;
G4double pshrnk; // exponent for shrinking
G4double pgrow; // exponent for growth
G4double errcon;
// Parameters used to grow and shrink trial stepsize.
static const G4double max_stepping_increase;
static const G4double max_stepping_decrease;
// Maximum stepsize increase/decrease factors.
// muximum error values for shrinking / growing (optimisation).
G4double errorConstraintShrink;
G4double errorConstraintGrow;
G4int fStatisticsVerboseLevel;
// Maximum stepsize increase/decrease factors.
static constexpr G4double max_stepping_increase = 5;
static constexpr G4double max_stepping_decrease = 0.1;
// ---------------------------------------------------------------
// DEPENDENT Objects
G4VFSALIntegrationStepper *pIntStepper;
T* pIntStepper;
// ---------------------------------------------------------------
// STATE
G4int fNoTotalSteps, fNoBadSteps, fNoSmallSteps, fNoInitialSmallSteps;
G4double fDyerr_max, fDyerr_mx2;
G4double fDyerrPos_smTot, fDyerrPos_lgTot, fDyerrVel_lgTot;
G4double fSumH_sm, fSumH_lg;
// Step Statistics
// Step Statistics
unsigned long fNoTotalSteps, fNoBadSteps, fNoGoodSteps;
G4int fVerboseLevel; // Verbosity level for printing (debug, ..)
// Could be varied during tracking - to help identify issues
//For Test Purposes :-
G4int TotalNoStepperCalls;
G4int fNoQuickAvanceCalls;
};
#include "G4FSALIntegrationDriver.icc"
#endif /* G4FSALIntegrationDriver_Def */
#endif
@@ -24,155 +24,437 @@
// ********************************************************************
//
//
// $Id: G4FSALIntegrationDriver.icc 97387 2016-06-02 10:03:42Z gcosmo $
// $Id: G4FSALIntegrationDriver.icc 107495 2017-11-16 13:51:06Z gcosmo $
//
//
// class G4FSALIntegrationDriver
//
// Class description:
//
// Driver class which controls the integration error of a
// Runge-Kutta stepper with a FSAL property
// History:
// - Created. D.Sorokin
// --------------------------------------------------------------------
inline
G4double G4FSALIntegrationDriver::GetHmin() const
#include "globals.hh"
#include "G4GeometryTolerance.hh"
#include "G4FieldTrack.hh"
#include "G4FieldUtils.hh"
#include <cassert>
template <class T>
G4FSALIntegrationDriver<T>::G4FSALIntegrationDriver (
G4double hminimum,
T* pStepper,
G4int numComponents,
G4int statisticsVerbose)
: fSmallestFraction(1e-12),
fNoTotalSteps(0),
fNoBadSteps(0),
fNoGoodSteps(0),
fVerboseLevel(statisticsVerbose),
fNoQuickAvanceCalls(0)
{
return fMinimumStep;
if (numComponents != pStepper->GetNumberOfVariables()) {
std::ostringstream message;
message << "Driver's number of integrated components " << numComponents
<< " != Stepper's number of components " << pStepper->GetNumberOfVariables();
G4Exception("G4FSALIntegrationDriver","001", FatalException, message);
}
RenewStepperAndAdjust(pStepper);
fMinimumStep = hminimum;
fMaxNoSteps = fMaxStepBase / pIntStepper->IntegratorOrder();
}
template <class T>
G4FSALIntegrationDriver<T>::~G4FSALIntegrationDriver()
{
if( fVerboseLevel > 0 )
G4cout << "G4FSALIntegration Driver Stats: "
<< "#QuickAdvance " << fNoQuickAvanceCalls
<< " #AccurateAdvance " << fNoTotalSteps << G4endl;
}
// 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 G4FSALIntegrationDriver<T>::AccurateAdvance(
G4FieldTrack& track,
G4double hstep,
G4double eps,
G4double hinitial)
{
if (hstep < GetMinimumStep()) {
G4double dchord_step = 0, dyerr = 0;
G4double dydx[G4FieldTrack::ncompSVEC];
GetDerivatives(track, dydx);
return QuickAdvance(track, dydx, hstep, dchord_step, dyerr);
}
G4bool succeeded = false;
G4double hnext, hdid;
G4double y[G4FieldTrack::ncompSVEC], dydx[G4FieldTrack::ncompSVEC];
track.DumpToArray(y);
// hstep somtimes is too small. No need to add large curveLength.
G4double curveLength = 0;
G4double endCurveLength = hstep;
G4double h = hstep;
if (hinitial > perMillion * hstep && hinitial < hstep) {
h = hinitial;
}
pIntStepper->RightHandSide(y, dydx);
for (G4int iter = 0; iter < fMaxNoSteps; ++iter) {
const G4ThreeVector StartPos =
field_utils::makeVector(y, field_utils::Value3D::Position);
OneGoodStep(y, dydx, curveLength, h, eps, hdid, hnext);
const G4ThreeVector EndPos =
field_utils::makeVector(y, field_utils::Value3D::Position);
CheckStep(EndPos, StartPos, hdid);
G4double restCurveLength = endCurveLength - curveLength;
if (restCurveLength < GetSmallestFraction() * hstep) {
succeeded = true;
break;
}
h = std::min(hnext, restCurveLength);
}
if (succeeded) {
track.LoadFromArray(y, pIntStepper->GetNumberOfVariables());
track.SetCurveLength(track.GetCurveLength() + curveLength);
}
return succeeded;
}
// Step failed; compute the size of retrial Step.
template <class T>
G4double G4FSALIntegrationDriver<T>::ShrinkStepSize(G4double h, G4double error) const
{
if (error > errorConstraintShrink) {
return max_stepping_decrease * h;
}
return GetSafety() * h * std::pow(error, GetPshrnk());
}
// Compute size of next Step
template<class T>
G4double G4FSALIntegrationDriver<T>::GrowStepSize(G4double h, G4double error) const
{
if (error < errorConstraintGrow) {
return max_stepping_increase * h;
}
return GetSafety() * h * std::pow(error, GetPgrow());
}
// 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 G4FSALIntegrationDriver<T>::OneGoodStep(
G4double y[],
G4double dydx[],
G4double& curveLength, // InOut
G4double htry,
G4double eps_rel_max,
G4double& hdid, // Out
G4double& hnext) // Out
{
G4double error = DBL_MAX;
G4double yError[G4FieldTrack::ncompSVEC],
yOut[G4FieldTrack::ncompSVEC],
dydxOut[G4FieldTrack::ncompSVEC];
// Set stepsize to the initial trial value
G4double hstep = htry;
static G4ThreadLocal G4int tot_no_trials = 0;
const G4int max_trials = 100;
for (G4int iter = 0; iter < max_trials; ++iter) {
++tot_no_trials;
pIntStepper->Stepper(y, dydx, hstep, yOut, yError, dydxOut);
error = field_utils::relativeError(y, yError, hstep, eps_rel_max);
// Step succeeded.
if (error <= 1) {
break;
}
hstep = ShrinkStepSize(hstep, error);
}
hnext = GrowStepSize(hstep, error);
curveLength += (hdid = hstep);
for(G4int k = 0; k < pIntStepper->GetNumberOfVariables(); ++k) {
y[k] = yOut[k];
dydx[k] = dydxOut[k];
}
}
template <class T>
G4bool G4FSALIntegrationDriver<T>::QuickAdvance(
G4FieldTrack& fieldTrack,
const G4double dydxIn[],
G4double hstep,
G4double& dchord_step,
G4double& dyerr)
{
++fNoQuickAvanceCalls;
if (hstep == 0) {
std::ostringstream message;
message << "Proposed step is zero; hstep = " << hstep << " !";
G4Exception("G4FSALIntegrationDriver ::QuickAdvance()",
"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("G4FSALIntegrationDriver ::QuickAdvance()",
"GeomField0003", EventMustBeAborted, message);
return false;
}
G4double yError[G4FieldTrack::ncompSVEC],
yIn[G4FieldTrack::ncompSVEC],
yOut[G4FieldTrack::ncompSVEC],
dydxOut[G4FieldTrack::ncompSVEC];
fieldTrack.DumpToArray(yIn);
pIntStepper->Stepper(yIn, dydxIn, hstep, yOut, yError, dydxOut);
dchord_step = pIntStepper->DistChord();
fieldTrack.LoadFromArray(yOut, pIntStepper->GetNumberOfVariables());
fieldTrack.SetCurveLength(fieldTrack.GetCurveLength() + hstep);
dyerr = field_utils::relativeError(yOut, yError, hstep) * hstep;
return true;
}
template <class T>
G4double G4FSALIntegrationDriver<T>::ComputeNewStepSize(
G4double errMaxNorm, // max error (normalised)
G4double hstepCurrent) // current step size
{
if (errMaxNorm > 1) {
return ShrinkStepSize(hstepCurrent, errMaxNorm);
} else if(errMaxNorm >= 0) {
return GrowStepSize(hstepCurrent, errMaxNorm);
}
G4Exception("G4FSALIntegrationDriver::ConputeNewStepSize", "Field002",
FatalException, "error is negative");
return max_stepping_increase * hstepCurrent;
}
template <class T>
void G4FSALIntegrationDriver<T>::SetSmallestFraction(G4double newFraction)
{
if( newFraction > 1.e-16 && newFraction < 1e-8 ) {
fSmallestFraction = newFraction;
} else {
G4cerr << "Warning: SmallestFraction not changed. " << G4endl
<< " Proposed value was " << newFraction << G4endl
<< " Value must be between 1.e-8 and 1.e-16" << G4endl;
}
}
template <class T>
void G4FSALIntegrationDriver<T>::GetDerivatives(
const G4FieldTrack& track, G4double dydx[]) const
{
G4double y[G4FieldTrack::ncompSVEC];
track.DumpToArray(y);
pIntStepper->RightHandSide(y, dydx);
}
template <class T>
void G4FSALIntegrationDriver<T>::CheckStep(
const G4ThreeVector& posIn, const G4ThreeVector& posOut, G4double hdid)
{
++fNoTotalSteps;
const G4double endPointDist = (posOut - posIn).mag();
if (endPointDist >= hdid * (1. + perMillion)) {
++fNoBadSteps;
// Issue a warning only for gross differences -
// we understand how small difference occur.
if (endPointDist >= hdid * (1. + perThousand)){
G4cout << "WARNING: endPointDist >= hdid!" << G4endl;
}
} else {
++fNoGoodSteps;
}
}
template <class T>
void G4FSALIntegrationDriver<T>::UpdateErrorConstraints()
{
errorConstraintShrink = std::pow(
max_stepping_decrease / GetSafety(), 1. / GetPshrnk());
errorConstraintGrow = std::pow(
max_stepping_increase / GetSafety(), 1. / GetPgrow());
}
template <class T>
inline G4double G4FSALIntegrationDriver<T>::GetMinimumStep() const
{
return fMinimumStep;
}
inline
G4double G4FSALIntegrationDriver::Hmin() const
template <class T>
inline G4double G4FSALIntegrationDriver<T>::GetSafety() const
{
return fMinimumStep;
return safety;
}
inline
G4double G4FSALIntegrationDriver::GetSafety() const
template <class T>
inline G4double G4FSALIntegrationDriver<T>::GetPshrnk() const
{
return safety;
}
inline
G4double G4FSALIntegrationDriver::GetPshrnk() const
{
return pshrnk;
return pshrnk;
}
inline
G4double G4FSALIntegrationDriver::GetPgrow() const
template <class T>
G4double G4FSALIntegrationDriver<T>::GetPgrow() const
{
return pgrow;
}
inline
G4double G4FSALIntegrationDriver::GetErrcon() const
{
return errcon;
return pgrow;
}
inline
void G4FSALIntegrationDriver::SetHmin(G4double newval)
template <class T>
void G4FSALIntegrationDriver<T>::SetMinimumStep(G4double minimumStepLength)
{
fMinimumStep = newval;
fMinimumStep = minimumStepLength;
}
inline
G4double G4FSALIntegrationDriver::ComputeAndSetErrcon()
template <class T>
void G4FSALIntegrationDriver<T>::ReSetParameters(G4double new_safety)
{
errcon = std::pow(max_stepping_increase/GetSafety(),1.0/GetPgrow());
return errcon;
}
inline
void G4FSALIntegrationDriver::ReSetParameters(G4double new_safety)
{
safety = new_safety;
pshrnk = -1.0 / pIntStepper->IntegratorOrder();
pgrow = -1.0 / (1.0 + pIntStepper->IntegratorOrder());
ComputeAndSetErrcon();
safety = new_safety;
pshrnk = -1.0 / pIntStepper->IntegratorOrder();
pgrow = -1.0 / (1.0 + pIntStepper->IntegratorOrder());
UpdateErrorConstraints();
}
inline
void G4FSALIntegrationDriver::SetSafety(G4double val)
template <class T>
void G4FSALIntegrationDriver<T>::SetSafety(G4double val)
{
safety=val;
ComputeAndSetErrcon();
safety = val;
UpdateErrorConstraints();
}
inline
void G4FSALIntegrationDriver::SetPgrow(G4double val)
{
pgrow=val;
ComputeAndSetErrcon();
}
inline
void G4FSALIntegrationDriver::SetErrcon(G4double val)
{
errcon=val;
}
inline
void G4FSALIntegrationDriver::RenewStepperAndAdjust(G4VFSALIntegrationStepper *pItsStepper)
template <class T>
void G4FSALIntegrationDriver<T>::RenewStepperAndAdjust(T* stepper)
{
pIntStepper = pItsStepper;
pIntStepper = stepper;
ReSetParameters();
}
inline
const G4VFSALIntegrationStepper* G4FSALIntegrationDriver::GetStepper() const
template <class T>
const T* G4FSALIntegrationDriver<T>::GetStepperOfPreciseType() const
{
return pIntStepper;
return pIntStepper;
}
inline
G4VFSALIntegrationStepper* G4FSALIntegrationDriver::GetStepper()
template <class T>
T* G4FSALIntegrationDriver<T>::GetStepperOfPreciseType()
{
return pIntStepper;
return pIntStepper;
}
inline
G4int G4FSALIntegrationDriver::GetMaxNoSteps() const
template <class T>
const G4MagIntegratorStepper* G4FSALIntegrationDriver<T>::GetStepper() const
{
return fMaxNoSteps;
return nullptr; // pIntStepper;
// It can only return 'pIntStepper' if it is a compatible type
}
inline
void G4FSALIntegrationDriver::SetMaxNoSteps(G4int val)
template <class T>
G4MagIntegratorStepper* G4FSALIntegrationDriver<T>::GetStepper()
{
fMaxNoSteps= val;
return nullptr;
// It can only return 'pIntStepper' if it is a compatible type
}
inline
void G4FSALIntegrationDriver::GetDerivatives(const G4FieldTrack &y_curr, // const, INput
G4double dydx[]) // OUTput
{
G4double tmpValArr[G4FieldTrack::ncompSVEC];
y_curr.DumpToArray( tmpValArr );
pIntStepper -> RightHandSide( tmpValArr , dydx );
template <class T>
G4int G4FSALIntegrationDriver<T>::GetMaxNoSteps() const
{
return fMaxNoSteps;
}
inline
G4double G4FSALIntegrationDriver::GetVerboseLevel() const
template <class T>
void G4FSALIntegrationDriver<T>::SetMaxNoSteps(G4int val)
{
return fVerboseLevel;
fMaxNoSteps = val;
}
template <class T>
G4int G4FSALIntegrationDriver<T>::GetVerboseLevel() const
{
return fVerboseLevel;
}
inline
void G4FSALIntegrationDriver::SetVerboseLevel(G4int newLevel)
template <class T>
void G4FSALIntegrationDriver<T>::SetVerboseLevel(G4int newLevel)
{
fVerboseLevel= newLevel;
fVerboseLevel = newLevel;
}
inline
G4double G4FSALIntegrationDriver::GetSmallestFraction() const
template <class T>
G4double G4FSALIntegrationDriver<T>::GetSmallestFraction() const
{
return fSmallestFraction;
return fSmallestFraction;
}
template <class T>
G4EquationOfMotion* G4FSALIntegrationDriver<T>::GetEquationOfMotion()
{
return pIntStepper->GetEquationOfMotion();
}
inline
G4int G4FSALIntegrationDriver::GetNoTotalSteps() const
template <class T>
void G4FSALIntegrationDriver<T>::SetEquationOfMotion(G4EquationOfMotion* equation)
{
return fNoTotalSteps;
pIntStepper->SetEquationOfMotion(equation);
}
inline
G4int G4FSALIntegrationDriver::GetTotalNoStepperCalls() const
{
return TotalNoStepperCalls;
}
@@ -0,0 +1,83 @@
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// $Id: $
//
// Helper namespace 'field_utils'
//
// Description:
// Simple methods to extract vectors from arrays in conventions of
// the magnetic field integration
//
// Implementation by Dmitry Sorokin - GSoC 2017
// Work supported by Google as part of Google Summer of Code 2017.
// Supervision / code review: John Apostolakis
#ifndef G4FIELD_UTILS_HH
#define G4FIELD_UTILS_HH
#include "G4Types.hh"
#include "G4ThreeVector.hh"
namespace field_utils {
enum class Value3D {
Position = 0,
Momentum = 3,
Spin = 9
};
enum class Value1D {
KineticEnergy = 6,
LabTime = 7,
ProperTime = 8
};
template <typename ArrayType>
G4double getValue(const ArrayType& array, Value1D value);
template <typename ArrayType>
G4double getValue2(const ArrayType& array, Value1D value);
template <typename ArrayType>
G4double getValue(const ArrayType& array, Value3D value);
template <typename ArrayType>
G4double getValue2(const ArrayType& array, Value3D value);
template <typename ArrayType>
G4ThreeVector makeVector(const ArrayType& array, Value3D value);
G4double relativeError(
const G4double y[],
const G4double yerr[],
const G4double hstep,
const G4double errorTolerance = 1);
} // field_utils
#include "G4FieldUtils.icc"
#endif
@@ -0,0 +1,75 @@
// ********************************************************************
// * 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. *
// ********************************************************************
//
// $Id: $
//
// Implementation by Dmitry Sorokin - GSoC 2017
// Work supported by Google as part of Google Summer of Code 2017.
// Supervision / code review: John Apostolakis
namespace field_utils {
namespace internal {
template<class T>
size_t getFirstIndex(const T& value) {
return static_cast<size_t>(value);
}
} // internal
template <typename ArrayType>
inline G4double getValue(const ArrayType& array, Value1D value)
{
const auto begin = internal::getFirstIndex(value);
return array[begin];
}
template <typename ArrayType>
G4double getValue2(const ArrayType& array, Value1D value)
{
return sqr(getValue(array, value));
}
template <typename ArrayType>
G4double getValue(const ArrayType& array, Value3D value)
{
return std::sqrt(getValue2(array, value));
}
template <typename ArrayType>
G4double getValue2(const ArrayType& array, const Value3D value)
{
const auto begin = internal::getFirstIndex(value);
return sqr(array[begin]) + sqr(array[begin+1]) + sqr(array[begin+2]);
}
template <typename ArrayType>
G4ThreeVector makeVector(const ArrayType& array, Value3D value)
{
const auto begin = internal::getFirstIndex(value);
return G4ThreeVector(array[begin], array[begin + 1], array[begin + 2]);
}
} // field_utils
@@ -0,0 +1,185 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// $Id: G4IntegrationDriver.hh 106739 2017-10-20 14:45:37Z dmsoroki $
//
//
// class G4IntegrationDriver
//
// Class description:
//
// Driver class which controls the integration error of a
// Runge-Kutta stepper
// History:
// - Created. D.Sorokin
// --------------------------------------------------------------------
#ifndef G4IntegrationDriver_HH
#define G4IntegrationDriver_HH
#include "G4Types.hh"
#include "G4FieldTrack.hh"
#include "G4VIntegrationDriver.hh"
template <class T>
class G4IntegrationDriver : public G4VIntegrationDriver {
public:
G4IntegrationDriver( G4double hminimum,
T* stepper,
G4int numberOfComponents = 6,
G4int statisticsVerbosity = 1);
virtual ~G4IntegrationDriver() override;
G4IntegrationDriver(const G4IntegrationDriver &) = delete;
const G4IntegrationDriver& operator =(const G4IntegrationDriver &) = delete;
// 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.
virtual G4bool AccurateAdvance(
G4FieldTrack& track,
G4double hstep,
G4double eps, // Requested y_err/hstep
G4double hinitial = 0) override; // Suggested 1st interval
// QuickAdvance just tries one Step - it does not ensure accuracy.
virtual G4bool QuickAdvance(
G4FieldTrack& fieldTrack,
const G4double dydx[],
G4double hstep,
G4double& dchord_step,
G4double& dyerr) override;
virtual void GetDerivatives(
const G4FieldTrack &track,
G4double dydx[]) const 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.
virtual G4double ComputeNewStepSize(
G4double errMaxNorm, // normalised error
G4double hstepCurrent) override; // current step size
virtual void SetVerboseLevel(G4int newLevel) override;
virtual G4int GetVerboseLevel() const override;
virtual G4EquationOfMotion* GetEquationOfMotion() override;
virtual void SetEquationOfMotion(G4EquationOfMotion* equation) override;
virtual const T* GetStepper() const override;
virtual T* GetStepper() override;
// Accessors.
G4double GetMinimumStep() const;
G4double GetSafety() const;
G4double GetPshrnk() const;
G4double GetPgrow() const;
// Sets a new stepper pItsStepper for this driver. Then it calls
// ReSetParameters to reset its parameters accordingly.
void RenewStepperAndAdjust(T *pItsStepper);
// i) sets the exponents (pgrow & pshrnk),
// using the current Stepper's order,
// ii) sets the safety
void ReSetParameters(G4double safety = 0.9);
void SetMinimumStep(G4double newval);
void SetSafety(G4double valS);
// This takes one Step that is of size htry, or as large
// as possible while satisfying the accuracy criterion of:
// yerr < eps * |y_end-y_start|
void OneGoodStep( G4double yVar[], // InOut
const G4double dydx[],
G4double& curveLength,
G4double htry,
G4double eps,
G4double& hdid,
G4double& hnext);
// Modify and Get the Maximum number of Steps that can be
// taken for the integration of a single segment -
// (ie a single call to AccurateAdvance).
G4int GetMaxNoSteps() const;
void SetMaxNoSteps( G4int val);
G4double GetSmallestFraction() const;
void SetSmallestFraction(G4double val);
private:
G4double ShrinkStepSize(G4double h, G4double error) const;
G4double GrowStepSize(G4double h, G4double error) const;
void UpdateErrorConstraints();
void CheckStep(
const G4ThreeVector& posIn, const G4ThreeVector& posOut, G4double hdid);
// Minimum Step allowed in a Step (in absolute units)
G4double fMinimumStep;
// Smallest fraction of (existing) curve length - in relative units
// below this fraction the current step will be the last
G4double fSmallestFraction;
// Expected range: smaller than 0.1 * epsilon and bigger than 5e-13
// ( Note: this range is not enforced. )
G4int fMaxNoSteps;
// The (default) maximum number of steps is Base
// divided by the order of Stepper
static constexpr G4int fMaxStepBase = 250;
// Parameters used to grow and shrink trial stepsize.
G4double safety;
G4double pshrnk; // exponent for shrinking
G4double pgrow; // exponent for growth
// muximum error values for shrinking / growing (optimisation).
G4double errorConstraintShrink;
G4double errorConstraintGrow;
// Maximum stepsize increase/decrease factors.
static constexpr G4double max_stepping_increase = 5;
static constexpr G4double max_stepping_decrease = 0.1;
T* pIntStepper;
// Step Statistics
unsigned long fNoTotalSteps, fNoBadSteps, fNoGoodSteps;
G4int fVerboseLevel; // Verbosity level for printing (debug, ..)
// Could be varied during tracking - to help identify issues
G4int fNoQuickAvanceCalls;
};
#include "G4IntegrationDriver.icc"
#endif
@@ -0,0 +1,436 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// $Id: G4IntegrationDriver.icc 106739 2017-10-20 14:45:37Z dmsoroki $
//
//
// class G4IntegrationDriver
//
// Class description:
//
// Driver class which controls the integration error of a
// Runge-Kutta stepper
// History:
// - Created. D.Sorokin
// --------------------------------------------------------------------
#include "globals.hh"
#include "G4GeometryTolerance.hh"
#include "G4FieldTrack.hh"
#include "G4FieldUtils.hh"
#include <cassert>
template <class T>
G4IntegrationDriver<T>::G4IntegrationDriver (
G4double hminimum,
T* pStepper,
G4int numComponents,
G4int statisticsVerbose)
: fSmallestFraction(1e-12),
fNoTotalSteps(0),
fNoBadSteps(0),
fNoGoodSteps(0),
fVerboseLevel(statisticsVerbose),
fNoQuickAvanceCalls(0)
{
if (numComponents != pStepper->GetNumberOfVariables()) {
std::ostringstream message;
message << "Driver's number of integrated components " << numComponents
<< " != Stepper's number of components " << pStepper->GetNumberOfVariables();
G4Exception("G4IntegrationDriver","001", FatalException, message);
}
RenewStepperAndAdjust(pStepper);
fMinimumStep = hminimum;
fMaxNoSteps = fMaxStepBase / pIntStepper->IntegratorOrder();
}
template <class T>
G4IntegrationDriver<T>::~G4IntegrationDriver()
{
if( fVerboseLevel > 0 )
G4cout << "G4Integration Driver Stats: #QuickAdvance " << fNoQuickAvanceCalls
<< " #AccurateAdvance " << fNoTotalSteps << G4endl;
}
// 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)
{
if (hstep < GetMinimumStep()) {
G4double dchord_step = 0, dyerr = 0;
G4double dydx[G4FieldTrack::ncompSVEC];
GetDerivatives(track, dydx);
return QuickAdvance(track, dydx, hstep, dchord_step, dyerr);
}
G4bool succeeded = false;
G4double hnext, hdid;
G4double y[G4FieldTrack::ncompSVEC], dydx[G4FieldTrack::ncompSVEC];
track.DumpToArray(y);
// hstep somtimes is too small. No need to add large curveLength.
G4double curveLength = 0;
G4double endCurveLength = hstep;
G4double h = hstep;
if (hinitial > perMillion * hstep && hinitial < hstep) {
h = hinitial;
}
for (G4int iter = 0; iter < fMaxNoSteps; ++iter) {
const G4ThreeVector StartPos =
field_utils::makeVector(y, field_utils::Value3D::Position);
pIntStepper->/*Compute*/RightHandSide(y, dydx);
OneGoodStep(y, dydx, curveLength, h, eps, hdid, hnext);
const G4ThreeVector EndPos =
field_utils::makeVector(y, field_utils::Value3D::Position);
CheckStep(EndPos, StartPos, hdid);
G4double restCurveLength = endCurveLength - curveLength;
if (restCurveLength < GetSmallestFraction() * hstep) {
succeeded = true;
break;
}
h = std::min(hnext, restCurveLength);
}
if (succeeded) {
track.LoadFromArray(y, pIntStepper->GetNumberOfVariables());
track.SetCurveLength(track.GetCurveLength() + curveLength);
}
return succeeded;
}
// Step failed; compute the size of retrial Step.
template <class T>
G4double G4IntegrationDriver<T>::ShrinkStepSize(G4double h, G4double error) const
{
if (error > errorConstraintShrink) {
return max_stepping_decrease * h;
}
return GetSafety() * h * std::pow(error, GetPshrnk());
}
// Compute size of next Step
template<class T>
G4double G4IntegrationDriver<T>::GrowStepSize(G4double h, G4double error) const
{
if (error < errorConstraintGrow) {
return max_stepping_increase * h;
}
return GetSafety() * h * std::pow(error, GetPgrow());
}
// 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[],
const G4double dydx[],
G4double& curveLength, // InOut
G4double htry,
G4double eps_rel_max,
G4double& hdid, // Out
G4double& hnext) // Out
{
G4double error = DBL_MAX;
G4double yerror[G4FieldTrack::ncompSVEC], ytemp[G4FieldTrack::ncompSVEC];
// Set stepsize to the initial trial value
G4double hstep = htry;
static G4ThreadLocal G4int tot_no_trials = 0;
const G4int max_trials = 100;
for (G4int iter = 0; iter < max_trials; ++iter) {
++tot_no_trials;
pIntStepper->Stepper(y, dydx, hstep, ytemp, yerror);
error = field_utils::relativeError(y, yerror, hstep, eps_rel_max);
// Step succeeded.
if (error <= 1) {
break;
}
hstep = ShrinkStepSize(hstep, error);
}
hnext = GrowStepSize(hstep, error);
curveLength += (hdid = hstep);
for(G4int k = 0; k < pIntStepper->GetNumberOfVariables(); ++k) {
y[k] = ytemp[k];
}
}
template <class T>
G4bool G4IntegrationDriver<T>::QuickAdvance(
G4FieldTrack& fieldTrack,
const G4double dydx[],
G4double hstep,
G4double& dchord_step,
G4double& dyerr)
{
++fNoQuickAvanceCalls;
if (hstep == 0) {
std::ostringstream message;
message << "Proposed step is zero; hstep = " << hstep << " !";
G4Exception("G4IntegrationDriver ::QuickAdvance()",
"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 ::QuickAdvance()",
"GeomField0003", EventMustBeAborted, message);
return false;
}
G4double yError[G4FieldTrack::ncompSVEC],
yIn[G4FieldTrack::ncompSVEC],
yOut[G4FieldTrack::ncompSVEC];
fieldTrack.DumpToArray(yIn);
pIntStepper->Stepper(yIn, dydx, hstep, yOut, yError);
dchord_step = pIntStepper->DistChord();
fieldTrack.LoadFromArray(yOut, pIntStepper->GetNumberOfVariables());
fieldTrack.SetCurveLength(fieldTrack.GetCurveLength() + hstep);
dyerr = field_utils::relativeError(yOut, yError, hstep) * hstep;
return true;
}
template <class T>
G4double G4IntegrationDriver<T>::ComputeNewStepSize(
G4double errMaxNorm, // max error (normalised)
G4double hstepCurrent) // current step size
{
if (errMaxNorm > 1) {
return ShrinkStepSize(hstepCurrent, errMaxNorm);
} else if (errMaxNorm >= 0) {
return GrowStepSize(hstepCurrent, errMaxNorm);
}
G4Exception("G4IntegrationDriver::ConputeNewStepSize", "Field002",
FatalException, "error is negative");
return max_stepping_increase * hstepCurrent;
}
template <class T>
void G4IntegrationDriver<T>::SetSmallestFraction(G4double newFraction)
{
if( newFraction > 1.e-16 && newFraction < 1e-8 ) {
fSmallestFraction = newFraction;
} else {
G4cerr << "Warning: SmallestFraction not changed. " << G4endl
<< " Proposed value was " << newFraction << G4endl
<< " Value must be between 1.e-8 and 1.e-16" << G4endl;
}
}
template <class T>
void G4IntegrationDriver<T>::GetDerivatives(
const G4FieldTrack& track, G4double dydx[]) const
{
G4double y[G4FieldTrack::ncompSVEC];
track.DumpToArray(y);
pIntStepper->RightHandSide(y, dydx);
}
template <class T>
void G4IntegrationDriver<T>::CheckStep(
const G4ThreeVector& posIn, const G4ThreeVector& posOut, G4double hdid)
{
++fNoTotalSteps;
const G4double endPointDist = (posOut - posIn).mag();
if (endPointDist >= hdid * (1. + perMillion)) {
++fNoBadSteps;
// Issue a warning only for gross differences -
// we understand how small difference occur.
if (endPointDist >= hdid * (1. + perThousand)){
G4cout << "WARNING: endPointDist >= hdid!" << G4endl;
}
} else {
++fNoGoodSteps;
}
}
template <class T>
void G4IntegrationDriver<T>::UpdateErrorConstraints()
{
errorConstraintShrink = std::pow(
max_stepping_decrease / GetSafety(), 1. / GetPshrnk());
errorConstraintGrow = std::pow(
max_stepping_increase / GetSafety(), 1. / GetPgrow());
}
template <class T>
inline G4double G4IntegrationDriver<T>::GetMinimumStep() const
{
return fMinimumStep;
}
template <class T>
inline G4double G4IntegrationDriver<T>::GetSafety() const
{
return safety;
}
template <class T>
inline G4double G4IntegrationDriver<T>::GetPshrnk() const
{
return pshrnk;
}
template <class T>
G4double G4IntegrationDriver<T>::GetPgrow() const
{
return pgrow;
}
template <class T>
void G4IntegrationDriver<T>::SetMinimumStep(G4double minimumStepLength)
{
fMinimumStep = minimumStepLength;
}
template <class T>
void G4IntegrationDriver<T>::ReSetParameters(G4double new_safety)
{
safety = new_safety;
pshrnk = -1.0 / pIntStepper->IntegratorOrder();
pgrow = -1.0 / (1.0 + pIntStepper->IntegratorOrder());
UpdateErrorConstraints();
}
template <class T>
void G4IntegrationDriver<T>::SetSafety(G4double val)
{
safety = val;
UpdateErrorConstraints();
}
template <class T>
void G4IntegrationDriver<T>::RenewStepperAndAdjust(T* stepper)
{
pIntStepper = stepper;
ReSetParameters();
}
template <class T>
const T* G4IntegrationDriver<T>::GetStepper() const
{
return pIntStepper;
}
template <class T>
T* G4IntegrationDriver<T>::GetStepper()
{
return pIntStepper;
}
template <class T>
G4int G4IntegrationDriver<T>::GetMaxNoSteps() const
{
return fMaxNoSteps;
}
template <class T>
void G4IntegrationDriver<T>::SetMaxNoSteps(G4int val)
{
fMaxNoSteps = val;
}
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>
G4EquationOfMotion* G4IntegrationDriver<T>::GetEquationOfMotion()
{
return pIntStepper->GetEquationOfMotion();
}
template <class T>
void G4IntegrationDriver<T>::SetEquationOfMotion(G4EquationOfMotion* equation)
{
pIntStepper->SetEquationOfMotion(equation);
}
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4MagIntegratorDriver.hh 104525 2017-06-02 07:22:58Z gcosmo $
// $Id: G4MagIntegratorDriver.hh 107059 2017-11-01 14:58:16Z gcosmo $
//
//
// class G4MagInt_Driver
@@ -41,155 +41,161 @@
#ifndef G4MagInt_Driver_Def
#define G4MagInt_Driver_Def
#include "G4Types.hh"
#include "G4FieldTrack.hh"
#include "G4VIntegrationDriver.hh"
#include "G4MagIntegratorStepper.hh"
class G4MagInt_Driver
class G4MagInt_Driver : public G4VIntegrationDriver
{
public: // with description
public: // with description
G4bool AccurateAdvance(G4FieldTrack& y_current,
G4double hstep,
G4double eps, // Requested y_err/hstep
G4double hinitial=0.0); // Suggested 1st interval
// 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.
G4MagInt_Driver(G4double hminimum,
G4MagIntegratorStepper* pItsStepper,
G4int numberOfComponents = 6,
G4int statisticsVerbosity = 1);
virtual ~G4MagInt_Driver() override;
// Constructor, destructor.
G4bool QuickAdvance( G4FieldTrack& y_val, // INOUT
const G4double dydx[],
G4double hstep, // IN
G4double& dchord_step,
G4double& dyerr ) ;
// QuickAdvance just tries one Step - it does not ensure accuracy.
G4MagInt_Driver(const G4MagInt_Driver&) = delete;
G4MagInt_Driver& operator=(const G4MagInt_Driver&) = delete;
// deleted Private copy constructor and assignment operator.
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) )
virtual G4bool AccurateAdvance(G4FieldTrack& y_current,
G4double hstep,
G4double eps, // Requested y_err/hstep
G4double hinitial = 0.0) override; // Suggested 1st interval
// 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.
G4MagInt_Driver( G4double hminimum,
G4MagIntegratorStepper *pItsStepper,
G4int numberOfComponents=6,
G4int statisticsVerbosity=1);
~G4MagInt_Driver();
// Constructor, destructor.
virtual G4bool QuickAdvance(G4FieldTrack& y_val, // INOUT
const G4double dydx[],
G4double hstep, // IN
G4double& dchord_step,
G4double& dyerr) override;
// QuickAdvance just tries one Step - it does not ensure accuracy.
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;
inline void GetDerivatives( const G4FieldTrack &y_curr, // const, INput
G4double dydx[] ); // OUTput
// Accessors.
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 void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper);
// Sets a new stepper pItsStepper for this driver. Then it calls
// ReSetParameters to reset its parameters accordingly.
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, // const, INput
G4double dydx[]) const override; // OUTput
// Accessors.
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.
virtual G4EquationOfMotion* GetEquationOfMotion() override;
virtual void SetEquationOfMotion(G4EquationOfMotion* equation) override;
inline void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper);
// Sets a new stepper pItsStepper for this driver. Then it calls
// ReSetParameters to reset its parameters accordingly.
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 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 G4double ComputeAndSetErrcon();
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 const G4MagIntegratorStepper* GetStepper() const;
inline G4MagIntegratorStepper* GetStepper();
inline G4double ComputeAndSetErrcon();
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 const G4MagIntegratorStepper* GetStepper() const override;
virtual G4MagIntegratorStepper* GetStepper() override;
G4double ComputeNewStepSize( G4double errMaxNorm, // normalised error
G4double hstepCurrent); // current step size
// 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 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|
G4double ComputeNewStepSize_WithinLimits(
G4double errMaxNorm, // normalised error
G4double hstepCurrent); // current step size
// 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.
virtual G4double ComputeNewStepSize(G4double errMaxNorm, // normalised error
G4double hstepCurrent) override; // current step size
// 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.
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 -
// (ie a single call to AccurateAdvance).
G4double ComputeNewStepSize_WithinLimits(G4double errMaxNorm, // normalised error
G4double hstepCurrent); // current step size
// 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.
public: // without description
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 -
// (ie a single call to AccurateAdvance).
inline void SetHmin(G4double newval);
inline void SetVerboseLevel(G4int newLevel);
inline G4double GetVerboseLevel() const;
public: // without description
inline G4double GetSmallestFraction() const;
void SetSmallestFraction( G4double val );
inline void SetHmin(G4double newval);
virtual void SetVerboseLevel(G4int newLevel) override;
virtual G4int GetVerboseLevel() const override;
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
inline G4double GetSmallestFraction() const;
void SetSmallestFraction( G4double val );
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
protected: // without description
void WarnSmallStepSize(G4double hnext, G4double hstep,
G4double h, G4double xDone,
G4int noSteps);
void PrintStatisticsReport() ;
// Report on the number of steps, maximum errors etc.
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
G4bool QuickAdvance( G4double yarrin[], // In
const G4double dydx[],
G4double hstep,
G4double yarrout[], // Out
@@ -197,58 +203,51 @@ class G4MagInt_Driver
G4double& dyerr ); // in length
#endif
private:
G4MagInt_Driver(const G4MagInt_Driver&);
G4MagInt_Driver& operator=(const G4MagInt_Driver&);
// Private copy constructor and assignment operator.
private:
private:
// ---------------------------------------------------------------
// INVARIANTS
G4double fMinimumStep;
// Minimum Step allowed in a Step (in absolute units)
G4double fSmallestFraction; // 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
G4double fMinimumStep;
// Minimum Step allowed in a Step (in absolute units)
G4double fSmallestFraction; // 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; // Number of Variables in integration
const G4int fMinNoVars; // Minimum number for FieldTrack
const G4int fNoVars; // Full number of variable
const G4int fNoIntegrationVariables; // Number of Variables in integration
const G4int fMinNoVars; // Minimum number for FieldTrack
const G4int fNoVars; // Full number of variable
G4int fMaxNoSteps;
static const G4int fMaxStepBase;
G4int fMaxNoSteps;
static const G4int fMaxStepBase;
G4double safety;
G4double pshrnk; // exponent for shrinking
G4double pgrow; // exponent for growth
G4double errcon;
// Parameters used to grow and shrink trial stepsize.
G4double safety;
G4double pshrnk; // exponent for shrinking
G4double pgrow; // exponent for growth
G4double errcon;
// Parameters used to grow and shrink trial stepsize.
static const G4double max_stepping_increase;
static const G4double max_stepping_decrease;
// Maximum stepsize increase/decrease factors.
static const G4double max_stepping_increase;
static const G4double max_stepping_decrease;
// Maximum stepsize increase/decrease factors.
G4int fStatisticsVerboseLevel;
G4int fStatisticsVerboseLevel;
// ---------------------------------------------------------------
// DEPENDENT Objects
G4MagIntegratorStepper *pIntStepper;
// ---------------------------------------------------------------
// DEPENDENT Objects
G4MagIntegratorStepper *pIntStepper;
// ---------------------------------------------------------------
// STATE
// ---------------------------------------------------------------
// STATE
unsigned long fNoTotalSteps, fNoBadSteps, fNoSmallSteps, fNoInitialSmallSteps;
unsigned long fNoCalls;
G4double fDyerr_max, fDyerr_mx2;
G4double fDyerrPos_smTot, fDyerrPos_lgTot, fDyerrVel_lgTot;
G4double fSumH_sm, fSumH_lg;
// Step Statistics
unsigned long fNoTotalSteps, fNoBadSteps, fNoSmallSteps, fNoInitialSmallSteps;
unsigned long fNoCalls;
G4double fDyerr_max, fDyerr_mx2;
G4double fDyerrPos_smTot, fDyerrPos_lgTot, fDyerrVel_lgTot;
G4double fSumH_sm, fSumH_lg;
// Step Statistics
G4int fVerboseLevel; // Verbosity level for printing (debug, ..)
// Could be varied during tracking - to help identify issues
G4int fVerboseLevel; // Verbosity level for printing (debug, ..)
// Could be varied during tracking - to help identify issues
};
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4MagIntegratorDriver.icc 69699 2013-05-13 08:50:30Z gcosmo $
// $Id: G4MagIntegratorDriver.icc 107059 2017-11-01 14:58:16Z gcosmo $
//
// --------------------------------------------------------------------
@@ -113,18 +113,6 @@ void G4MagInt_Driver::RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper)
ReSetParameters();
}
inline
const G4MagIntegratorStepper* G4MagInt_Driver::GetStepper() const
{
return pIntStepper;
}
inline
G4MagIntegratorStepper* G4MagInt_Driver::GetStepper()
{
return pIntStepper;
}
inline
G4int G4MagInt_Driver::GetMaxNoSteps() const
{
@@ -138,16 +126,7 @@ void G4MagInt_Driver::SetMaxNoSteps(G4int val)
}
inline
void G4MagInt_Driver::GetDerivatives(const G4FieldTrack &y_curr, // const, INput
G4double dydx[]) // OUTput
{
G4double tmpValArr[G4FieldTrack::ncompSVEC];
y_curr.DumpToArray( tmpValArr );
pIntStepper -> RightHandSide( tmpValArr , dydx );
}
inline
G4double G4MagInt_Driver::GetVerboseLevel() const
G4int G4MagInt_Driver::GetVerboseLevel() const
{
return fVerboseLevel;
}
@@ -162,4 +141,5 @@ inline
G4double G4MagInt_Driver::GetSmallestFraction() const
{
return fSmallestFraction;
}
}
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4MagIntegratorStepper.hh 97387 2016-06-02 10:03:42Z gcosmo $
// $Id: G4MagIntegratorStepper.hh 107059 2017-11-01 14:58:16Z gcosmo $
//
//
// class G4MagIntegratorStepper
@@ -86,7 +86,7 @@ class G4MagIntegratorStepper
inline void NormalisePolarizationVector( G4double vec[12] );
// Simple utility function to (re)normalise 'unit spin' vector.
inline void RightHandSide( const double y[], double dydx[] );
inline void RightHandSide( const double y[], double dydx[] ) const;
// Utility method to supply the standard Evaluation of the
// Right Hand side of the associated equation.
@@ -113,7 +113,7 @@ class G4MagIntegratorStepper
inline void ResetfNORHSCalls(){ fNoRHSCalls = 0; }
// Count number of calls to RHS method(s)
bool IsFSAL() { return fIsFSAL; }
bool IsFSAL() const { return fIsFSAL; }
protected:
void SetIntegrationOrder(int order) { fIntegrationOrder= order; }
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4MagIntegratorStepper.icc 97387 2016-06-02 10:03:42Z gcosmo $
// $Id: G4MagIntegratorStepper.icc 107059 2017-11-01 14:58:16Z gcosmo $
//
inline
@@ -55,7 +55,7 @@ G4int G4MagIntegratorStepper::GetNumberOfStateVariables() const
}
inline
void G4MagIntegratorStepper::RightHandSide( const double y[], double dydx[] )
void G4MagIntegratorStepper::RightHandSide( const double y[], double dydx[] ) const
{
fEquation_Rhs-> RightHandSide(y, dydx);
fNoRHSCalls++; // IncrementRHSCalls();
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4NystromRK4.hh 66356 2012-12-18 09:02:32Z gcosmo $
// $Id: G4NystromRK4.hh 106564 2017-10-13 09:06:13Z gcosmo $
//
// class G4NystromRK4
//
@@ -64,7 +64,7 @@ class G4NystromRK4 : public G4MagIntegratorStepper
// Single call for integration result and error
// - Provides Error via analytical method
virtual void ComputeRightHandSide(const double P[],double dPdS[]);
virtual void ComputeRightHandSide(const G4double P[],G4double dPdS[]);
// Must compute RHS - and does caches result
void SetDistanceForConstantField( G4double length );
@@ -77,6 +77,10 @@ class G4NystromRK4 : public G4MagIntegratorStepper
inline void getField (const G4double P[4]);
G4bool CheckCachedMomemtum( const G4double PosMom[6], G4double savedMom );
G4bool CheckFieldPosition( const G4double Position[3],
const G4double lastPosition[3] );
////////////////////////////////////////////////////////////////
// Private data
////////////////////////////////////////////////////////////////
@@ -0,0 +1,87 @@
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// $Id: $
//
// Helper namespace 'magneticfield'
//
// Description:
// An implementation of the 7 stage embedded Runge-Kutta 4,5 pair (RK547FEq1)
// from the paper D. J. Higham and G. Hall,
// “Embedded Runge-Kutta formulae with stable equilibrium states”,
// J. Comput. Appl. Math., vol. 29, no. 1, pp. 2533, Jan. 1990.
//
// Implementation by Dmitry Sorokin - GSoC 2017
// Work supported by Google as part of Google Summer of Code 2017.
// Supervision / code review: John Apostolakis
#ifndef G4RK547FEq1_HH
#define G4RK547FEq1_HH
#include "G4MagIntegratorStepper.hh"
#include "G4FieldTrack.hh"
class G4RK547FEq1 : public G4MagIntegratorStepper {
public:
G4RK547FEq1(G4EquationOfMotion* EqRhs, G4int integrationVariables = 6);
virtual void Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[]) override;
void Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[]);
G4RK547FEq1(const G4RK547FEq1&) = delete;
G4RK547FEq1& operator = (const G4RK547FEq1&) = delete;
virtual G4double DistChord() const override;
virtual G4int IntegratorOrder() const override { return 4; }
private:
void makeStep(
const G4double yInput[],
const G4double dydx[],
const G4double hstep,
G4double yOutput[],
G4double* dydxOutput = nullptr,
G4double* yError = nullptr) const;
G4double fyIn[G4FieldTrack::ncompSVEC],
fdydx[G4FieldTrack::ncompSVEC],
fyOut[G4FieldTrack::ncompSVEC],
fdydxOut[G4FieldTrack::ncompSVEC];
G4double fhstep = -1.0;
};
#endif
@@ -0,0 +1,87 @@
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// $Id: $
//
// Helper namespace 'magneticfield'
//
// Description:
// An implementation of the 7 stage embedded Runge-Kutta 4,5 pair (RK547FEq2)
// from the paper D. J. Higham and G. Hall,
// “Embedded Runge-Kutta formulae with stable equilibrium states”,
// J. Comput. Appl. Math., vol. 29, no. 1, pp. 2533, Jan. 1990.
//
// Implementation by Dmitry Sorokin - GSoC 2017
// Work supported by Google as part of Google Summer of Code 2017.
// Supervision / code review: John Apostolakis
#ifndef G4RK547FEq2_HH
#define G4RK547FEq2_HH
#include "G4MagIntegratorStepper.hh"
#include "G4FieldTrack.hh"
class G4RK547FEq2 : public G4MagIntegratorStepper {
public:
G4RK547FEq2(G4EquationOfMotion* EqRhs, G4int integrationVariables = 6);
virtual void Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[]) override;
void Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[]);
G4RK547FEq2 (const G4RK547FEq2&) = delete;
G4RK547FEq2& operator = (const G4RK547FEq2&) = delete;
virtual G4double DistChord() const override;
virtual G4int IntegratorOrder() const override { return 4; }
private:
void makeStep(
const G4double yInput[],
const G4double dydx[],
const G4double hstep,
G4double yOutput[],
G4double* dydxOutput = nullptr,
G4double* yError = nullptr) const;
G4double fyIn[G4FieldTrack::ncompSVEC],
fdydx[G4FieldTrack::ncompSVEC],
fyOut[G4FieldTrack::ncompSVEC],
fdydxOut[G4FieldTrack::ncompSVEC];
G4double fhstep= -1.0;
};
#endif
@@ -0,0 +1,87 @@
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// $Id: $
//
// Helper namespace 'magneticfield'
//
// Description:
// An implementation of the 7 stage embedded Runge-Kutta 4,5 pair (RK547FEq3)
// from the paper D. J. Higham and G. Hall,
// “Embedded Runge-Kutta formulae with stable equilibrium states”,
// J. Comput. Appl. Math., vol. 29, no. 1, pp. 2533, Jan. 1990.
//
// Implementation by Dmitry Sorokin - GSoC 2017
// Work supported by Google as part of Google Summer of Code 2017.
// Supervision / code review: John Apostolakis
#ifndef G4RK547FEq3_HH
#define G4RK547FEq3_HH
#include "G4MagIntegratorStepper.hh"
#include "G4FieldTrack.hh"
class G4RK547FEq3 : public G4MagIntegratorStepper {
public:
G4RK547FEq3(G4EquationOfMotion* EqRhs, G4int integrationVariables = 6);
virtual void Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[]) override;
void Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[]);
G4RK547FEq3(const G4RK547FEq3&) = delete;
G4RK547FEq3& operator = (const G4RK547FEq3&) = delete;
virtual G4double DistChord() const override;
virtual G4int IntegratorOrder() const override { return 4; }
private:
void makeStep(
const G4double yInput[],
const G4double dydx[],
const G4double hstep,
G4double yOutput[],
G4double* dydxOutput = nullptr,
G4double* yError = nullptr) const;
G4double fyIn[G4FieldTrack::ncompSVEC],
fdydx[G4FieldTrack::ncompSVEC],
fyOut[G4FieldTrack::ncompSVEC],
fdydxOut[G4FieldTrack::ncompSVEC];
G4double fhstep= -1.0;
};
#endif
@@ -0,0 +1,94 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// $Id: $
//
// class G4VIntegrationDriver
//
// Class description:
//
// Abstract base class for 'driver' classes which are responsible for
// undertaking integration of an state given an equation of motion and
// within acceptable error bound(s).
//
// Different integration methods are meant to be provided via this
// common interface, and can span the original type (explicit Runge Kutta
// methods), enhanced RK methods and alternatives such as the
// Bulirsch-Stoer and multi-step methods.
//
// The drivers' key mission is to insure that the error is below set values.
//
// Implementation by Dmitry Sorokin - GSoC 2017
// Work supported by Google as part of Google Summer of Code 2017.
// Supervision / code review: John Apostolakis
#ifndef G4VINTEGRATION_DRIVER_HH
#define G4VINTEGRATION_DRIVER_HH
#include "G4Types.hh"
#include "G4FieldTrack.hh"
#include "G4MagIntegratorStepper.hh"
class G4VIntegrationDriver {
public:
G4VIntegrationDriver() = default;
virtual ~G4VIntegrationDriver() = default;
G4VIntegrationDriver(const G4VIntegrationDriver&) = delete;
const G4VIntegrationDriver& operator = (const G4VIntegrationDriver&) = delete;
virtual G4bool QuickAdvance(G4FieldTrack& track, // INOUT
const G4double dydx[],
G4double hstep,
G4double& dchord_step,
G4double& dyerr) = 0;
virtual G4bool AccurateAdvance(G4FieldTrack& track,
G4double hstep,
G4double eps, // Requested y_err/hstep
G4double hinitial = 0) = 0; // Suggested 1st interval
virtual void GetDerivatives(const G4FieldTrack& track,
G4double dydx[]) const = 0;
virtual void SetEquationOfMotion(G4EquationOfMotion* equation) = 0;
virtual G4EquationOfMotion* GetEquationOfMotion() = 0;
//[[deprecated("use GetEquationOfMotion() instead of GetStepper()->GetEquationOfMotion()")]]
virtual const G4MagIntegratorStepper* GetStepper() const = 0;
virtual G4MagIntegratorStepper* GetStepper() = 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.
virtual G4double ComputeNewStepSize(G4double errMaxNorm, // normalised error
G4double hstepCurrent) = 0; // current step size
virtual void SetVerboseLevel(G4int level) = 0;
virtual G4int GetVerboseLevel() const = 0;
};
#endif