Import Geant4 11.4.0 source tree
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
//
|
||||
// G4FSALIntegrationDriver inline implementation
|
||||
//
|
||||
// Created: D.Sorokin, 2017
|
||||
// Author: Dmitry Sorokin (CERN, Google Summer of Code 2017), 20.10.2017
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "G4FieldUtils.hh"
|
||||
@@ -34,34 +34,34 @@ template <class T>
|
||||
G4FSALIntegrationDriver<T>::
|
||||
G4FSALIntegrationDriver ( G4double hminimum, T* pStepper,
|
||||
G4int numComponents, G4int statisticsVerbose )
|
||||
: Base(pStepper),
|
||||
fMinimumStep(hminimum),
|
||||
fVerboseLevel(statisticsVerbose)
|
||||
: Base(pStepper),
|
||||
fMinimumStep(hminimum),
|
||||
fVerboseLevel(statisticsVerbose)
|
||||
{
|
||||
if (numComponents != Base::GetStepper()->GetNumberOfVariables())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Driver's number of integrated components "
|
||||
<< numComponents
|
||||
<< " != Stepper's number of components "
|
||||
<< pStepper->GetNumberOfVariables();
|
||||
G4Exception("G4FSALIntegrationDriver","GeomField0002",
|
||||
FatalException, message);
|
||||
}
|
||||
if (numComponents != Base::GetStepper()->GetNumberOfVariables())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Driver's number of integrated components "
|
||||
<< numComponents
|
||||
<< " != Stepper's number of components "
|
||||
<< pStepper->GetNumberOfVariables();
|
||||
G4Exception("G4FSALIntegrationDriver","GeomField0002",
|
||||
FatalException, message);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4FSALIntegrationDriver<T>::~G4FSALIntegrationDriver()
|
||||
{
|
||||
#ifdef G4VERBOSE
|
||||
if( fVerboseLevel > 0 )
|
||||
{
|
||||
G4cout << "G4FSALIntegration Driver Stats: "
|
||||
<< "#QuickAdvance " << fNoQuickAvanceCalls
|
||||
<< " - #AccurateAdvance " << fNoAccurateAdvanceCalls << G4endl
|
||||
<< "#good steps " << fNoAccurateAdvanceGoodSteps << " "
|
||||
<< "#bad steps " << fNoAccurateAdvanceBadSteps << G4endl;
|
||||
}
|
||||
if( fVerboseLevel > 0 )
|
||||
{
|
||||
G4cout << "G4FSALIntegration Driver Stats: "
|
||||
<< "#QuickAdvance " << fNoQuickAvanceCalls
|
||||
<< " - #AccurateAdvance " << fNoAccurateAdvanceCalls << G4endl
|
||||
<< "#good steps " << fNoAccurateAdvanceGoodSteps << " "
|
||||
<< "#bad steps " << fNoAccurateAdvanceBadSteps << G4endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -76,66 +76,65 @@ G4bool G4FSALIntegrationDriver<T>::
|
||||
AccurateAdvance( G4FieldTrack& track, G4double hstep,
|
||||
G4double eps, G4double hinitial )
|
||||
{
|
||||
++fNoAccurateAdvanceCalls;
|
||||
++fNoAccurateAdvanceCalls;
|
||||
|
||||
if (hstep < GetMinimumStep())
|
||||
if (hstep < GetMinimumStep())
|
||||
{
|
||||
G4double dchord_step = 0.0, dyerr = 0.0;
|
||||
G4double dydx[G4FieldTrack::ncompSVEC];
|
||||
Base::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.0;
|
||||
G4double endCurveLength = hstep;
|
||||
|
||||
G4double h = hstep;
|
||||
if (hinitial > CLHEP::perMillion * hstep && hinitial < hstep)
|
||||
{
|
||||
h = hinitial;
|
||||
}
|
||||
|
||||
Base::GetStepper()->RightHandSide(y, dydx);
|
||||
|
||||
for (G4int iter = 0; iter < Base::GetMaxNoSteps(); ++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)
|
||||
{
|
||||
G4double dchord_step = 0.0, dyerr = 0.0;
|
||||
G4double dydx[G4FieldTrack::ncompSVEC];
|
||||
Base::GetDerivatives(track, dydx);
|
||||
return QuickAdvance(track, dydx, hstep, dchord_step, dyerr);
|
||||
succeeded = true;
|
||||
break;
|
||||
}
|
||||
|
||||
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.0;
|
||||
G4double endCurveLength = hstep;
|
||||
h = std::min(hnext, restCurveLength);
|
||||
}
|
||||
|
||||
|
||||
G4double h = hstep;
|
||||
if (hinitial > CLHEP::perMillion * hstep && hinitial < hstep)
|
||||
{
|
||||
h = hinitial;
|
||||
}
|
||||
if (succeeded)
|
||||
{
|
||||
track.LoadFromArray(y, Base::GetStepper()->GetNumberOfVariables());
|
||||
track.SetCurveLength(track.GetCurveLength() + curveLength);
|
||||
}
|
||||
|
||||
Base::GetStepper()->RightHandSide(y, dydx);
|
||||
|
||||
for (G4int iter = 0; iter < Base::GetMaxNoSteps(); ++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, Base::GetStepper()->GetNumberOfVariables());
|
||||
track.SetCurveLength(track.GetCurveLength() + curveLength);
|
||||
}
|
||||
|
||||
return succeeded;
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
// Driver for one Runge-Kutta Step with monitoring of local truncation error
|
||||
@@ -161,36 +160,36 @@ OneGoodStep(G4double y[],
|
||||
G4double& hdid, // Out
|
||||
G4double& hnext) // Out
|
||||
{
|
||||
G4double error2 = DBL_MAX;
|
||||
G4double error2 = DBL_MAX;
|
||||
|
||||
G4double yError[G4FieldTrack::ncompSVEC],
|
||||
yOut[G4FieldTrack::ncompSVEC],
|
||||
dydxOut[G4FieldTrack::ncompSVEC];
|
||||
G4double yError[G4FieldTrack::ncompSVEC],
|
||||
yOut[G4FieldTrack::ncompSVEC],
|
||||
dydxOut[G4FieldTrack::ncompSVEC];
|
||||
|
||||
// Set stepsize to the initial trial value
|
||||
G4double hstep = htry;
|
||||
// Set stepsize to the initial trial value
|
||||
G4double hstep = htry;
|
||||
|
||||
const G4int max_trials = 100;
|
||||
const G4int max_trials = 100;
|
||||
|
||||
for (G4int iter = 0; iter < max_trials; ++iter)
|
||||
{
|
||||
Base::GetStepper()->Stepper(y, dydx, hstep, yOut, yError, dydxOut);
|
||||
error2 = field_utils::relativeError2(y, yError, hstep, eps_rel_max);
|
||||
for (G4int iter = 0; iter < max_trials; ++iter)
|
||||
{
|
||||
Base::GetStepper()->Stepper(y, dydx, hstep, yOut, yError, dydxOut);
|
||||
error2 = field_utils::relativeError2(y, yError, hstep, eps_rel_max);
|
||||
|
||||
// Step succeeded.
|
||||
if (error2 <= 1) { break; }
|
||||
// Step succeeded.
|
||||
if (error2 <= 1) { break; }
|
||||
|
||||
hstep = Base::ShrinkStepSize2(hstep, error2);
|
||||
}
|
||||
hstep = Base::ShrinkStepSize2(hstep, error2);
|
||||
}
|
||||
|
||||
hnext = Base::GrowStepSize2(hstep, error2);
|
||||
curveLength += (hdid = hstep);
|
||||
hnext = Base::GrowStepSize2(hstep, error2);
|
||||
curveLength += (hdid = hstep);
|
||||
|
||||
for(G4int k = 0; k < Base::GetStepper()->GetNumberOfVariables(); ++k)
|
||||
{
|
||||
y[k] = yOut[k];
|
||||
dydx[k] = dydxOut[k];
|
||||
}
|
||||
for(G4int k = 0; k < Base::GetStepper()->GetNumberOfVariables(); ++k)
|
||||
{
|
||||
y[k] = yOut[k];
|
||||
dydx[k] = dydxOut[k];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -199,123 +198,122 @@ 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);
|
||||
|
||||
Base::GetStepper()->Stepper(yIn, dydxIn, hstep, yOut, yError, dydxOut);
|
||||
dchord_step = Base::GetStepper()->DistChord();
|
||||
|
||||
fieldTrack.LoadFromArray(yOut, Base::GetStepper()->GetNumberOfVariables());
|
||||
fieldTrack.SetCurveLength(fieldTrack.GetCurveLength() + hstep);
|
||||
|
||||
dyerr = field_utils::absoluteError(yOut, yError, hstep);
|
||||
++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);
|
||||
|
||||
Base::GetStepper()->Stepper(yIn, dydxIn, hstep, yOut, yError, dydxOut);
|
||||
dchord_step = Base::GetStepper()->DistChord();
|
||||
|
||||
fieldTrack.LoadFromArray(yOut, Base::GetStepper()->GetNumberOfVariables());
|
||||
fieldTrack.SetCurveLength(fieldTrack.GetCurveLength() + hstep);
|
||||
|
||||
dyerr = field_utils::absoluteError(yOut, yError, hstep);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<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("G4FSALIntegrationDriver::SetSmallestFraction()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
}
|
||||
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("G4FSALIntegrationDriver::SetSmallestFraction()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::CheckStep(
|
||||
const G4ThreeVector& posIn, const G4ThreeVector& posOut, G4double hdid)
|
||||
{
|
||||
const G4double endPointDist = (posOut - posIn).mag();
|
||||
if (endPointDist >= hdid * (1. + CLHEP::perMillion))
|
||||
{
|
||||
++fNoAccurateAdvanceBadSteps;
|
||||
const G4double endPointDist = (posOut - posIn).mag();
|
||||
if (endPointDist >= hdid * (1. + CLHEP::perMillion))
|
||||
{
|
||||
++fNoAccurateAdvanceBadSteps;
|
||||
#ifdef G4DEBUG_FIELD
|
||||
// Issue a warning only for gross differences -
|
||||
// we understand how small difference occur.
|
||||
if (endPointDist >= hdid * (1. + perThousand))
|
||||
{
|
||||
G4Exception("G4FSALIntegrationDriver::CheckStep()",
|
||||
"GeomField1002", JustWarning,
|
||||
"endPointDist >= hdid!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
// Issue a warning only for gross differences -
|
||||
// we understand how small difference occur.
|
||||
if (endPointDist >= hdid * (1. + perThousand))
|
||||
{
|
||||
++fNoAccurateAdvanceGoodSteps;
|
||||
G4Exception("G4FSALIntegrationDriver::CheckStep()",
|
||||
"GeomField1002", JustWarning, "endPointDist >= hdid!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
++fNoAccurateAdvanceGoodSteps;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline G4double G4FSALIntegrationDriver<T>::GetMinimumStep() const
|
||||
{
|
||||
return fMinimumStep;
|
||||
return fMinimumStep;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::SetMinimumStep(G4double minimumStepLength)
|
||||
{
|
||||
fMinimumStep = minimumStepLength;
|
||||
fMinimumStep = minimumStepLength;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4int G4FSALIntegrationDriver<T>::GetVerboseLevel() const
|
||||
{
|
||||
return fVerboseLevel;
|
||||
return fVerboseLevel;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::SetVerboseLevel(G4int newLevel)
|
||||
{
|
||||
fVerboseLevel = newLevel;
|
||||
fVerboseLevel = newLevel;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4double G4FSALIntegrationDriver<T>::GetSmallestFraction() const
|
||||
{
|
||||
return fSmallestFraction;
|
||||
return fSmallestFraction;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::IncrementQuickAdvanceCalls()
|
||||
{
|
||||
++fNoQuickAvanceCalls;
|
||||
++fNoQuickAvanceCalls;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -325,14 +323,32 @@ G4FSALIntegrationDriver<T>::AdvanceChordLimited(G4FieldTrack& track,
|
||||
G4double eps,
|
||||
G4double chordDistance)
|
||||
{
|
||||
return ChordFinderDelegate::AdvanceChordLimitedImpl(track, hstep,
|
||||
eps, chordDistance);
|
||||
return ChordFinderDelegate::AdvanceChordLimitedImpl(track, hstep,
|
||||
eps, chordDistance);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::OnStartTracking()
|
||||
{
|
||||
ChordFinderDelegate::ResetStepEstimate();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::OnComputeStep(const G4FieldTrack*)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4bool G4FSALIntegrationDriver<T>::DoesReIntegrate() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::StreamInfo( std::ostream& os ) const
|
||||
{
|
||||
// Write out the parameters / state of the driver
|
||||
// Write out the parameters / state of the driver
|
||||
|
||||
os << "State of G4IntegrationDriver: " << std::endl;
|
||||
os << "--Base state (G4RKIntegrationDriver): " << std::endl;
|
||||
Base::StreamInfo( os );
|
||||
|
||||
Reference in New Issue
Block a user