Import Geant4 9.2.0 source tree
This commit is contained in:
@@ -24,8 +24,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4CashKarpRKF45.cc,v 1.14 2006/06/29 18:23:29 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// $Id: G4CashKarpRKF45.cc,v 1.15 2008/01/11 18:11:44 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// The Cash-Karp Runge-Kutta-Fehlberg 4/5 method is an embedded fourth
|
||||
// order method (giving fifth-order accuracy) for the solution of an ODE.
|
||||
@@ -45,26 +45,29 @@
|
||||
//
|
||||
// Constructor
|
||||
|
||||
G4CashKarpRKF45::G4CashKarpRKF45(G4EquationOfMotion *EqRhs, G4int numberOfVariables, G4bool primary)
|
||||
: G4MagIntegratorStepper(EqRhs, numberOfVariables)
|
||||
G4CashKarpRKF45::G4CashKarpRKF45(G4EquationOfMotion *EqRhs,
|
||||
G4int noIntegrationVariables,
|
||||
G4bool primary)
|
||||
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables)
|
||||
{
|
||||
fNumberOfVariables = numberOfVariables ;
|
||||
// unsigned int noVariables= std::max(numberOfVariables,8); // For Time .. 7+1
|
||||
const G4int numberOfVariables = noIntegrationVariables;
|
||||
|
||||
ak2 = new G4double[fNumberOfVariables] ;
|
||||
ak3 = new G4double[fNumberOfVariables] ;
|
||||
ak4 = new G4double[fNumberOfVariables] ;
|
||||
ak5 = new G4double[fNumberOfVariables] ;
|
||||
ak6 = new G4double[fNumberOfVariables] ;
|
||||
ak2 = new G4double[numberOfVariables] ;
|
||||
ak3 = new G4double[numberOfVariables] ;
|
||||
ak4 = new G4double[numberOfVariables] ;
|
||||
ak5 = new G4double[numberOfVariables] ;
|
||||
ak6 = new G4double[numberOfVariables] ;
|
||||
ak7 = 0;
|
||||
yTemp = new G4double[fNumberOfVariables] ;
|
||||
yIn = new G4double[fNumberOfVariables] ;
|
||||
yTemp = new G4double[numberOfVariables] ;
|
||||
yIn = new G4double[numberOfVariables] ;
|
||||
|
||||
fLastInitialVector = new G4double[fNumberOfVariables] ;
|
||||
fLastFinalVector = new G4double[fNumberOfVariables] ;
|
||||
fLastDyDx = new G4double[fNumberOfVariables];
|
||||
fLastInitialVector = new G4double[numberOfVariables] ;
|
||||
fLastFinalVector = new G4double[numberOfVariables] ;
|
||||
fLastDyDx = new G4double[numberOfVariables];
|
||||
|
||||
fMidVector = new G4double[fNumberOfVariables];
|
||||
fMidError = new G4double[fNumberOfVariables];
|
||||
fMidVector = new G4double[numberOfVariables];
|
||||
fMidError = new G4double[numberOfVariables];
|
||||
fAuxStepper = 0;
|
||||
if( primary )
|
||||
fAuxStepper = new G4CashKarpRKF45(EqRhs, numberOfVariables, !primary);
|
||||
@@ -134,48 +137,55 @@ G4CashKarpRKF45::Stepper(const G4double yInput[],
|
||||
const G4double dc1 = c1 - 2825.0/27648.0 , dc3 = c3 - 18575.0/48384.0 ,
|
||||
dc4 = c4 - 13525.0/55296.0 , dc6 = c6 - 0.25 ;
|
||||
|
||||
// Initialise time to t0, needed when it is not updated by the integration.
|
||||
// [ Note: Only for time dependent fields (usually electric)
|
||||
// is it neccessary to integrate the time.]
|
||||
yOut[7] = yTemp[7] = yIn[7];
|
||||
|
||||
const G4int numberOfVariables= this->GetNumberOfVariables();
|
||||
// The number of variables to be integrated over
|
||||
|
||||
// Saving yInput because yInput and yOut can be aliases for same array
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
for(i=0;i<numberOfVariables;i++)
|
||||
{
|
||||
yIn[i]=yInput[i];
|
||||
}
|
||||
// RightHandSide(yIn, dydx) ; // 1st Step
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
for(i=0;i<numberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + b21*Step*dydx[i] ;
|
||||
}
|
||||
RightHandSide(yTemp, ak2) ; // 2nd Step
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
for(i=0;i<numberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + Step*(b31*dydx[i] + b32*ak2[i]) ;
|
||||
}
|
||||
RightHandSide(yTemp, ak3) ; // 3rd Step
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
for(i=0;i<numberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + Step*(b41*dydx[i] + b42*ak2[i] + b43*ak3[i]) ;
|
||||
}
|
||||
RightHandSide(yTemp, ak4) ; // 4th Step
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
for(i=0;i<numberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + Step*(b51*dydx[i] + b52*ak2[i] + b53*ak3[i] +
|
||||
b54*ak4[i]) ;
|
||||
}
|
||||
RightHandSide(yTemp, ak5) ; // 5th Step
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
for(i=0;i<numberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + Step*(b61*dydx[i] + b62*ak2[i] + b63*ak3[i] +
|
||||
b64*ak4[i] + b65*ak5[i]) ;
|
||||
}
|
||||
RightHandSide(yTemp, ak6) ; // 6th Step
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
for(i=0;i<numberOfVariables;i++)
|
||||
{
|
||||
// Accumulate increments with proper weights
|
||||
|
||||
|
||||
@@ -24,20 +24,20 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4ChordFinder.cc,v 1.47 2006/06/29 18:23:32 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// $Id: G4ChordFinder.cc,v 1.51 2008/10/29 14:17:42 gcosmo Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// 25.02.97 John Apostolakis, design and implimentation
|
||||
// 05.03.97 V. Grichine , style modification
|
||||
// 25.02.97 - John Apostolakis - Design and implementation
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#include "G4ChordFinder.hh"
|
||||
#include "G4MagneticField.hh"
|
||||
#include "G4Mag_UsualEqRhs.hh"
|
||||
#include "G4ClassicalRK4.hh"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
// ..........................................................................
|
||||
|
||||
@@ -53,7 +53,7 @@ G4ChordFinder::G4ChordFinder(G4MagInt_Driver* pIntegrationDriver)
|
||||
fStatsVerbose(0)
|
||||
{
|
||||
// Simple constructor which does not create equation, ..
|
||||
// fDeltaChord= fDefaultDeltaChord;
|
||||
|
||||
fIntgrDriver= pIntegrationDriver;
|
||||
fAllocatedStepper= false;
|
||||
fLastStepEstimate_Unconstrained = DBL_MAX; // Should move q, p to
|
||||
@@ -62,6 +62,7 @@ G4ChordFinder::G4ChordFinder(G4MagInt_Driver* pIntegrationDriver)
|
||||
// check the values and set the other parameters
|
||||
}
|
||||
|
||||
|
||||
// ..........................................................................
|
||||
|
||||
G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
@@ -79,6 +80,7 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
{
|
||||
// Construct the Chord Finder
|
||||
// by creating in inverse order the Driver, the Stepper and EqRhs ...
|
||||
|
||||
G4Mag_EqRhs *pEquation = new G4Mag_UsualEqRhs(theMagField);
|
||||
fEquation = pEquation;
|
||||
fLastStepEstimate_Unconstrained = DBL_MAX; // Should move q, p to
|
||||
@@ -103,40 +105,6 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
pItsStepper->GetNumberOfVariables() );
|
||||
}
|
||||
|
||||
// ......................................................................
|
||||
|
||||
void
|
||||
G4ChordFinder::SetFractions_Last_Next( G4double fractLast, G4double fractNext )
|
||||
{
|
||||
// Use -1.0 as request for Default.
|
||||
if( fractLast == -1.0 ) fractLast = 1.0; // 0.9;
|
||||
if( fractNext == -1.0 ) fractNext = 0.98; // 0.9;
|
||||
|
||||
// fFirstFraction = 0.999; // Orig 0.999 A safe value, range: ~ 0.95 - 0.999
|
||||
// fMultipleRadius = 15.0; // For later use, range: ~ 2 - 20
|
||||
|
||||
if( fStatsVerbose ) {
|
||||
G4cout << " ChordFnd> Trying to set fractions: "
|
||||
<< " first " << fFirstFraction
|
||||
<< " last " << fractLast
|
||||
<< " next " << fractNext
|
||||
<< " and multiple " << fMultipleRadius
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
if( (fractLast > 0.0) && (fractLast <=1.0) )
|
||||
{ fFractionLast= fractLast; }
|
||||
else
|
||||
G4cerr << "G4ChordFinder:: SetFractions_Last_Next: Invalid "
|
||||
<< " fraction Last = " << fractLast
|
||||
<< " must be 0 < fractionLast <= 1 " << G4endl;
|
||||
if( (fractNext > 0.0) && (fractNext <1.0) )
|
||||
{ fFractionNextEstimate = fractNext; }
|
||||
else
|
||||
G4cerr << "G4ChordFinder:: SetFractions_Last_Next: Invalid "
|
||||
<< " fraction Next = " << fractNext
|
||||
<< " must be 0 < fractionNext < 1 " << G4endl;
|
||||
}
|
||||
|
||||
// ......................................................................
|
||||
|
||||
@@ -146,16 +114,517 @@ G4ChordFinder::~G4ChordFinder()
|
||||
if( fAllocatedStepper)
|
||||
{
|
||||
delete fDriversStepper;
|
||||
} // fIntgrDriver->pIntStepper;}
|
||||
}
|
||||
delete fIntgrDriver;
|
||||
|
||||
if( fStatsVerbose ) { PrintStatistics(); }
|
||||
if( fStatsVerbose ) { PrintStatistics(); }
|
||||
}
|
||||
|
||||
|
||||
// ......................................................................
|
||||
|
||||
void
|
||||
G4ChordFinder::SetFractions_Last_Next( G4double fractLast, G4double fractNext )
|
||||
{
|
||||
// Use -1.0 as request for Default.
|
||||
if( fractLast == -1.0 ) fractLast = 1.0; // 0.9;
|
||||
if( fractNext == -1.0 ) fractNext = 0.98; // 0.9;
|
||||
|
||||
// fFirstFraction = 0.999; // Orig 0.999 A safe value, range: ~ 0.95 - 0.999
|
||||
// fMultipleRadius = 15.0; // For later use, range: ~ 2 - 20
|
||||
|
||||
if( fStatsVerbose )
|
||||
{
|
||||
G4cout << " ChordFnd> Trying to set fractions: "
|
||||
<< " first " << fFirstFraction
|
||||
<< " last " << fractLast
|
||||
<< " next " << fractNext
|
||||
<< " and multiple " << fMultipleRadius
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
if( (fractLast > 0.0) && (fractLast <=1.0) )
|
||||
{
|
||||
fFractionLast= fractLast;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cerr << "G4ChordFinder::SetFractions_Last_Next: Invalid "
|
||||
<< " fraction Last = " << fractLast
|
||||
<< " must be 0 < fractionLast <= 1 " << G4endl;
|
||||
}
|
||||
if( (fractNext > 0.0) && (fractNext <1.0) )
|
||||
{
|
||||
fFractionNextEstimate = fractNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cerr << "G4ChordFinder:: SetFractions_Last_Next: Invalid "
|
||||
<< " fraction Next = " << fractNext
|
||||
<< " must be 0 < fractionNext < 1 " << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ......................................................................
|
||||
|
||||
G4double
|
||||
G4ChordFinder::AdvanceChordLimited( G4FieldTrack& yCurrent,
|
||||
G4double stepMax,
|
||||
G4double epsStep,
|
||||
const G4ThreeVector latestSafetyOrigin,
|
||||
G4double latestSafetyRadius )
|
||||
{
|
||||
G4double stepPossible;
|
||||
G4double dyErr;
|
||||
G4FieldTrack yEnd( yCurrent);
|
||||
G4double startCurveLen= yCurrent.GetCurveLength();
|
||||
G4double nextStep;
|
||||
// *************
|
||||
stepPossible= FindNextChord(yCurrent, stepMax, yEnd, dyErr, epsStep,
|
||||
&nextStep, latestSafetyOrigin, latestSafetyRadius
|
||||
);
|
||||
// *************
|
||||
|
||||
G4bool good_advance;
|
||||
|
||||
if ( dyErr < epsStep * stepPossible )
|
||||
{
|
||||
// Accept this accuracy.
|
||||
|
||||
yCurrent = yEnd;
|
||||
good_advance = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Advance more accurately to "end of chord"
|
||||
// ***************
|
||||
good_advance = fIntgrDriver->AccurateAdvance(yCurrent, stepPossible,
|
||||
epsStep, nextStep);
|
||||
if ( ! good_advance )
|
||||
{
|
||||
// In this case the driver could not do the full distance
|
||||
stepPossible= yCurrent.GetCurveLength()-startCurveLen;
|
||||
}
|
||||
}
|
||||
return stepPossible;
|
||||
}
|
||||
|
||||
|
||||
// ............................................................................
|
||||
|
||||
G4double
|
||||
G4ChordFinder::FindNextChord( const G4FieldTrack& yStart,
|
||||
G4double stepMax,
|
||||
G4FieldTrack& yEnd, // Endpoint
|
||||
G4double& dyErrPos, // Error of endpoint
|
||||
G4double epsStep,
|
||||
G4double* pStepForAccuracy,
|
||||
const G4ThreeVector, // latestSafetyOrigin,
|
||||
G4double // latestSafetyRadius
|
||||
)
|
||||
{
|
||||
// Returns Length of Step taken
|
||||
|
||||
G4FieldTrack yCurrent= yStart;
|
||||
G4double stepTrial, stepForAccuracy;
|
||||
G4double dydx[G4FieldTrack::ncompSVEC];
|
||||
|
||||
// 1.) Try to "leap" to end of interval
|
||||
// 2.) Evaluate if resulting chord gives d_chord that is good enough.
|
||||
// 2a.) If d_chord is not good enough, find one that is.
|
||||
|
||||
G4bool validEndPoint= false;
|
||||
G4double dChordStep, lastStepLength; // stepOfLastGoodChord;
|
||||
|
||||
fIntgrDriver-> GetDerivatives( yCurrent, dydx );
|
||||
|
||||
G4int noTrials=0;
|
||||
const G4double safetyFactor= fFirstFraction; // 0.975 or 0.99 ? was 0.999
|
||||
|
||||
stepTrial = std::min( stepMax, safetyFactor*fLastStepEstimate_Unconstrained );
|
||||
|
||||
G4double newStepEst_Uncons= 0.0;
|
||||
do
|
||||
{
|
||||
G4double stepForChord;
|
||||
yCurrent = yStart; // Always start from initial point
|
||||
|
||||
// ************
|
||||
fIntgrDriver->QuickAdvance( yCurrent, dydx, stepTrial,
|
||||
dChordStep, dyErrPos);
|
||||
// ************
|
||||
|
||||
// We check whether the criterion is met here.
|
||||
validEndPoint = AcceptableMissDist(dChordStep);
|
||||
|
||||
lastStepLength = stepTrial;
|
||||
|
||||
// This method estimates to step size for a good chord.
|
||||
stepForChord = NewStep(stepTrial, dChordStep, newStepEst_Uncons );
|
||||
|
||||
if( ! validEndPoint )
|
||||
{
|
||||
if( stepTrial<=0.0 )
|
||||
{
|
||||
stepTrial = stepForChord;
|
||||
}
|
||||
else if (stepForChord <= stepTrial)
|
||||
{
|
||||
// Reduce by a fraction, possibly up to 20%
|
||||
stepTrial = std::min( stepForChord, fFractionLast * stepTrial);
|
||||
}
|
||||
else
|
||||
{
|
||||
stepTrial *= 0.1;
|
||||
}
|
||||
}
|
||||
noTrials++;
|
||||
}
|
||||
while( ! validEndPoint ); // End of do-while RKD
|
||||
|
||||
if( newStepEst_Uncons > 0.0 )
|
||||
{
|
||||
fLastStepEstimate_Unconstrained= newStepEst_Uncons;
|
||||
}
|
||||
|
||||
AccumulateStatistics( noTrials );
|
||||
|
||||
if( pStepForAccuracy )
|
||||
{
|
||||
// Calculate the step size required for accuracy, if it is needed
|
||||
//
|
||||
G4double dyErr_relative = dyErrPos/(epsStep*lastStepLength);
|
||||
if( dyErr_relative > 1.0 )
|
||||
{
|
||||
stepForAccuracy = fIntgrDriver->ComputeNewStepSize( dyErr_relative,
|
||||
lastStepLength );
|
||||
}
|
||||
else
|
||||
{
|
||||
stepForAccuracy = 0.0; // Convention to show step was ok
|
||||
}
|
||||
*pStepForAccuracy = stepForAccuracy;
|
||||
}
|
||||
|
||||
#ifdef TEST_CHORD_PRINT
|
||||
static int dbg=0;
|
||||
if( dbg )
|
||||
{
|
||||
G4cout << "ChordF/FindNextChord: NoTrials= " << noTrials
|
||||
<< " StepForGoodChord=" << std::setw(10) << stepTrial << G4endl;
|
||||
}
|
||||
#endif
|
||||
yEnd= yCurrent;
|
||||
return stepTrial;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
|
||||
G4double G4ChordFinder::NewStep(G4double stepTrialOld,
|
||||
G4double dChordStep, // Curr. dchord achieved
|
||||
G4double& stepEstimate_Unconstrained )
|
||||
{
|
||||
// Is called to estimate the next step size, even for successful steps,
|
||||
// in order to predict an accurate 'chord-sensitive' first step
|
||||
// which is likely to assist in more performant 'stepping'.
|
||||
|
||||
G4double stepTrial;
|
||||
static G4double lastStepTrial = 1., lastDchordStep= 1.;
|
||||
|
||||
#if 1
|
||||
|
||||
if (dChordStep > 0.0)
|
||||
{
|
||||
stepEstimate_Unconstrained =
|
||||
stepTrialOld*std::sqrt( fDeltaChord / dChordStep );
|
||||
stepTrial = fFractionNextEstimate * stepEstimate_Unconstrained;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should not update the Unconstrained Step estimate: incorrect!
|
||||
stepTrial = stepTrialOld * 2.;
|
||||
}
|
||||
|
||||
if( stepTrial <= 0.001 * stepTrialOld)
|
||||
{
|
||||
if ( dChordStep > 1000.0 * fDeltaChord )
|
||||
{
|
||||
stepTrial= stepTrialOld * 0.03;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( dChordStep > 100. * fDeltaChord )
|
||||
{
|
||||
stepTrial= stepTrialOld * 0.1;
|
||||
}
|
||||
else // Try halving the length until dChordStep OK
|
||||
{
|
||||
stepTrial= stepTrialOld * 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stepTrial > 1000.0 * stepTrialOld)
|
||||
{
|
||||
stepTrial= 1000.0 * stepTrialOld;
|
||||
}
|
||||
|
||||
if( stepTrial == 0.0 )
|
||||
{
|
||||
stepTrial= 0.000001;
|
||||
}
|
||||
|
||||
lastStepTrial = stepTrialOld;
|
||||
lastDchordStep= dChordStep;
|
||||
|
||||
#else
|
||||
|
||||
if ( dChordStep > 1000. * fDeltaChord )
|
||||
{
|
||||
stepTrial= stepTrialOld * 0.03;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( dChordStep > 100. * fDeltaChord )
|
||||
{
|
||||
stepTrial= stepTrialOld * 0.1;
|
||||
}
|
||||
else // Keep halving the length until dChordStep OK
|
||||
{
|
||||
stepTrial= stepTrialOld * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// A more sophisticated chord-finder could figure out a better
|
||||
// stepTrial, from dChordStep and the required d_geometry
|
||||
// e.g.
|
||||
// Calculate R, r_helix (eg at orig point)
|
||||
// if( stepTrial < 2 pi R )
|
||||
// stepTrial = R arc_cos( 1 - fDeltaChord / r_helix )
|
||||
// else
|
||||
// ??
|
||||
|
||||
return stepTrial;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
|
||||
G4FieldTrack
|
||||
G4ChordFinder::ApproxCurvePointS( const G4FieldTrack& CurveA_PointVelocity,
|
||||
const G4FieldTrack& CurveB_PointVelocity,
|
||||
const G4FieldTrack& ApproxCurveV,
|
||||
const G4ThreeVector& CurrentE_Point,
|
||||
const G4ThreeVector& CurrentF_Point,
|
||||
const G4ThreeVector& PointG,
|
||||
G4bool first, G4double eps_step)
|
||||
{
|
||||
// ApproxCurvePointS is 2nd implementation of ApproxCurvePoint.
|
||||
// Use Brent Algorithm (or InvParabolic) when possible.
|
||||
// Given a starting curve point A (CurveA_PointVelocity), curve point B
|
||||
// (CurveB_PointVelocity), a point E which is (generally) not on the curve
|
||||
// and a point F which is on the curve (first approximation), find new
|
||||
// point S on the curve closer to point E.
|
||||
// While advancing towards S utilise 'eps_step' as a measure of the
|
||||
// relative accuracy of each Step.
|
||||
|
||||
G4FieldTrack EndPoint( CurveA_PointVelocity);
|
||||
G4ThreeVector Point_A=CurveA_PointVelocity.GetPosition();
|
||||
G4ThreeVector Point_B=CurveB_PointVelocity.GetPosition();
|
||||
G4double xa,xb,xc,ya,yb,yc;
|
||||
|
||||
// InverseParabolic. AF Intersects (First Part of Curve)
|
||||
|
||||
if(first)
|
||||
{
|
||||
xa=0.;
|
||||
ya=(PointG-Point_A).mag();
|
||||
xb=(Point_A-CurrentF_Point).mag();
|
||||
yb=-(PointG-CurrentF_Point).mag();
|
||||
xc=(Point_A-Point_B).mag();
|
||||
yc=-(CurrentE_Point-Point_B).mag();
|
||||
}
|
||||
else
|
||||
{
|
||||
xa=0.;
|
||||
ya=(Point_A-PointG).mag();
|
||||
xb=(Point_B-Point_A).mag();
|
||||
yb=-(PointG-Point_B).mag();
|
||||
xc=-(Point_A-CurrentF_Point).mag();
|
||||
yc=-(Point_A-CurrentE_Point).mag();
|
||||
|
||||
}
|
||||
const G4double tolerance= 1.e-12;
|
||||
if(ya<=tolerance||std::abs(yc)<=tolerance)
|
||||
{
|
||||
; // What to do for the moment: return the same point as at start
|
||||
// then PropagatorInField will take care
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double test_step = InvParabolic(xa,ya,xb,yb,xc,yc);
|
||||
G4double curve;
|
||||
if(first)
|
||||
{
|
||||
curve=std::abs(EndPoint.GetCurveLength()
|
||||
-ApproxCurveV.GetCurveLength());
|
||||
}
|
||||
else
|
||||
{
|
||||
curve=std::abs(EndPoint.GetCurveLength()
|
||||
-CurveB_PointVelocity.GetCurveLength());
|
||||
}
|
||||
|
||||
if(test_step<=0) { test_step=0.1*xb; }
|
||||
if(test_step>=xb) { test_step=0.5*xb; }
|
||||
if(test_step>=curve){ test_step=0.5*curve; }
|
||||
|
||||
if(curve*(1.+eps_step)<xb) // Similar to ReEstimate Step from
|
||||
{ // G4VIntersectionLocator
|
||||
test_step=0.5*curve;
|
||||
}
|
||||
|
||||
G4bool goodAdvance;
|
||||
goodAdvance = fIntgrDriver->AccurateAdvance(EndPoint,test_step, eps_step);
|
||||
|
||||
#ifdef G4DEBUG_FIELD
|
||||
// Printing Brent and Linear Approximation
|
||||
//
|
||||
G4cout << "G4ChordFinder::ApproxCurvePointS() - test-step ShF = "
|
||||
<< test_step << " EndPoint = " << EndPoint << G4endl;
|
||||
|
||||
// Test Track
|
||||
//
|
||||
G4FieldTrack TestTrack( CurveA_PointVelocity);
|
||||
TestTrack = ApproxCurvePointV( CurveA_PointVelocity,
|
||||
CurveB_PointVelocity,
|
||||
CurrentE_Point, eps_step );
|
||||
G4cout.precision(14);
|
||||
G4cout << "G4ChordFinder::BrentApprox = " << EndPoint << G4endl;
|
||||
G4cout << "G4ChordFinder::LinearApprox= " << TestTrack << G4endl;
|
||||
#endif
|
||||
}
|
||||
return EndPoint;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
|
||||
G4FieldTrack G4ChordFinder::
|
||||
ApproxCurvePointV( const G4FieldTrack& CurveA_PointVelocity,
|
||||
const G4FieldTrack& CurveB_PointVelocity,
|
||||
const G4ThreeVector& CurrentE_Point,
|
||||
G4double eps_step)
|
||||
{
|
||||
// If r=|AE|/|AB|, and s=true path lenght (AB)
|
||||
// return the point that is r*s along the curve!
|
||||
|
||||
G4FieldTrack Current_PointVelocity = CurveA_PointVelocity;
|
||||
|
||||
G4ThreeVector CurveA_Point= CurveA_PointVelocity.GetPosition();
|
||||
G4ThreeVector CurveB_Point= CurveB_PointVelocity.GetPosition();
|
||||
|
||||
G4ThreeVector ChordAB_Vector= CurveB_Point - CurveA_Point;
|
||||
G4ThreeVector ChordAE_Vector= CurrentE_Point - CurveA_Point;
|
||||
|
||||
G4double ABdist= ChordAB_Vector.mag();
|
||||
G4double curve_length; // A curve length of AB
|
||||
G4double AE_fraction;
|
||||
|
||||
curve_length= CurveB_PointVelocity.GetCurveLength()
|
||||
- CurveA_PointVelocity.GetCurveLength();
|
||||
|
||||
G4double integrationInaccuracyLimit= std::max( perMillion, 0.5*eps_step );
|
||||
if( curve_length < ABdist * (1. - integrationInaccuracyLimit) )
|
||||
{
|
||||
#ifdef G4DEBUG_FIELD
|
||||
G4cerr << " Warning in G4ChordFinder::ApproxCurvePoint: "
|
||||
<< G4endl
|
||||
<< " The two points are further apart than the curve length "
|
||||
<< G4endl
|
||||
<< " Dist = " << ABdist
|
||||
<< " curve length = " << curve_length
|
||||
<< " relativeDiff = " << (curve_length-ABdist)/ABdist
|
||||
<< G4endl;
|
||||
if( curve_length < ABdist * (1. - 10*eps_step) )
|
||||
{
|
||||
G4cerr << " ERROR: the size of the above difference"
|
||||
<< " exceeds allowed limits. Aborting." << G4endl;
|
||||
G4Exception("G4ChordFinder::ApproxCurvePointV()", "PrecisionError",
|
||||
FatalException, "Unphysical curve length.");
|
||||
}
|
||||
#endif
|
||||
// Take default corrective action: adjust the maximum curve length.
|
||||
// NOTE: this case only happens for relatively straight paths.
|
||||
// curve_length = ABdist;
|
||||
}
|
||||
|
||||
G4double new_st_length;
|
||||
|
||||
if ( ABdist > 0.0 )
|
||||
{
|
||||
AE_fraction = ChordAE_Vector.mag() / ABdist;
|
||||
}
|
||||
else
|
||||
{
|
||||
AE_fraction = 0.5; // Guess .. ?;
|
||||
#ifdef G4DEBUG_FIELD
|
||||
G4cout << "Warning in G4ChordFinder::ApproxCurvePointV():"
|
||||
<< " A and B are the same point!" << G4endl
|
||||
<< " Chord AB length = " << ChordAE_Vector.mag() << G4endl
|
||||
<< G4endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
if( (AE_fraction> 1.0 + perMillion) || (AE_fraction< 0.) )
|
||||
{
|
||||
#ifdef G4DEBUG_FIELD
|
||||
G4cerr << " G4ChordFinder::ApproxCurvePointV() - Warning:"
|
||||
<< " Anomalous condition:AE > AB or AE/AB <= 0 " << G4endl
|
||||
<< " AE_fraction = " << AE_fraction << G4endl
|
||||
<< " Chord AE length = " << ChordAE_Vector.mag() << G4endl
|
||||
<< " Chord AB length = " << ABdist << G4endl << G4endl;
|
||||
G4cerr << " OK if this condition occurs after a recalculation of 'B'"
|
||||
<< G4endl << " Otherwise it is an error. " << G4endl ;
|
||||
#endif
|
||||
// This course can now result if B has been re-evaluated,
|
||||
// without E being recomputed (1 July 99).
|
||||
// In this case this is not a "real error" - but it is undesired
|
||||
// and we cope with it by a default corrective action ...
|
||||
//
|
||||
AE_fraction = 0.5; // Default value
|
||||
}
|
||||
|
||||
new_st_length= AE_fraction * curve_length;
|
||||
|
||||
G4bool good_advance;
|
||||
if ( AE_fraction > 0.0 )
|
||||
{
|
||||
good_advance = fIntgrDriver->AccurateAdvance(Current_PointVelocity,
|
||||
new_st_length, eps_step );
|
||||
//
|
||||
// In this case it does not matter if it cannot advance the full distance
|
||||
}
|
||||
|
||||
// If there was a memory of the step_length actually required at the start
|
||||
// of the integration Step, this could be re-used ...
|
||||
|
||||
G4cout.precision(14);
|
||||
|
||||
return Current_PointVelocity;
|
||||
}
|
||||
|
||||
|
||||
// ......................................................................
|
||||
|
||||
void
|
||||
G4ChordFinder::PrintStatistics()
|
||||
{
|
||||
// Print Statistics
|
||||
|
||||
G4cout << "G4ChordFinder statistics report: " << G4endl;
|
||||
G4cout
|
||||
<< " No trials: " << fTotalNoTrials_FNC
|
||||
@@ -170,372 +639,26 @@ G4ChordFinder::PrintStatistics()
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
// ......................................................................
|
||||
|
||||
G4double
|
||||
G4ChordFinder::AdvanceChordLimited( G4FieldTrack& yCurrent,
|
||||
G4double stepMax,
|
||||
G4double epsStep,
|
||||
const G4ThreeVector latestSafetyOrigin,
|
||||
G4double latestSafetyRadius
|
||||
)
|
||||
{
|
||||
G4double stepPossible;
|
||||
G4double dyErr;
|
||||
G4FieldTrack yEnd( yCurrent);
|
||||
G4double startCurveLen= yCurrent.GetCurveLength();
|
||||
|
||||
G4double nextStep;
|
||||
// *************
|
||||
stepPossible= FindNextChord(yCurrent, stepMax, yEnd, dyErr, epsStep, &nextStep
|
||||
, latestSafetyOrigin, latestSafetyRadius
|
||||
);
|
||||
// *************
|
||||
G4bool good_advance;
|
||||
if ( dyErr < epsStep * stepPossible )
|
||||
{
|
||||
// Accept this accuracy.
|
||||
yCurrent = yEnd;
|
||||
good_advance = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Advance more accurately to "end of chord"
|
||||
// ***************
|
||||
good_advance = fIntgrDriver->AccurateAdvance(yCurrent, stepPossible, epsStep, nextStep);
|
||||
// ***************
|
||||
if ( ! good_advance ){
|
||||
// In this case the driver could not do the full distance
|
||||
stepPossible= yCurrent.GetCurveLength()-startCurveLen;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef G4DEBUG_FIELD
|
||||
G4cout << "Exiting FindNextChord Limited with:" << G4endl
|
||||
<< " yCurrent: " << yCurrent<< G4endl;
|
||||
#endif
|
||||
|
||||
return stepPossible;
|
||||
}
|
||||
|
||||
// #define TEST_CHORD_PRINT 1
|
||||
|
||||
// ............................................................................
|
||||
|
||||
G4double
|
||||
G4ChordFinder::FindNextChord( const G4FieldTrack yStart,
|
||||
G4double stepMax,
|
||||
G4FieldTrack& yEnd, // Endpoint
|
||||
G4double& dyErrPos, // Error of endpoint
|
||||
G4double epsStep,
|
||||
G4double* pStepForAccuracy,
|
||||
const G4ThreeVector, // latestSafetyOrigin,
|
||||
G4double // latestSafetyRadius
|
||||
)
|
||||
// Returns Length of Step taken
|
||||
{
|
||||
// G4int stepRKnumber=0;
|
||||
G4FieldTrack yCurrent= yStart;
|
||||
G4double stepTrial, stepForAccuracy;
|
||||
G4double dydx[G4FieldTrack::ncompSVEC];
|
||||
|
||||
// 1.) Try to "leap" to end of interval
|
||||
// 2.) Evaluate if resulting chord gives d_chord that is good enough.
|
||||
// 2a.) If d_chord is not good enough, find one that is.
|
||||
|
||||
G4bool validEndPoint= false;
|
||||
G4double dChordStep, lastStepLength; // stepOfLastGoodChord;
|
||||
|
||||
fIntgrDriver-> GetDerivatives( yCurrent, dydx ) ;
|
||||
|
||||
G4int noTrials=0;
|
||||
const G4double safetyFactor= fFirstFraction; // 0.975 or 0.99 ? was 0.999
|
||||
|
||||
stepTrial = std::min( stepMax,
|
||||
safetyFactor * fLastStepEstimate_Unconstrained );
|
||||
|
||||
G4double newStepEst_Uncons= 0.0;
|
||||
do
|
||||
{
|
||||
G4double stepForChord;
|
||||
yCurrent = yStart; // Always start from initial point
|
||||
|
||||
// ************
|
||||
fIntgrDriver->QuickAdvance( yCurrent, dydx, stepTrial,
|
||||
dChordStep, dyErrPos);
|
||||
// ************
|
||||
|
||||
// We check whether the criterion is met here.
|
||||
validEndPoint = AcceptableMissDist(dChordStep);
|
||||
// && (dyErrPos < eps) ;
|
||||
|
||||
lastStepLength = stepTrial;
|
||||
|
||||
// This method estimates to step size for a good chord.
|
||||
stepForChord = NewStep(stepTrial, dChordStep, newStepEst_Uncons );
|
||||
|
||||
if( ! validEndPoint ) {
|
||||
if( stepTrial<=0.0 )
|
||||
stepTrial = stepForChord;
|
||||
else if (stepForChord <= stepTrial)
|
||||
// Reduce by a fraction, possibly up to 20%
|
||||
stepTrial = std::min( stepForChord,
|
||||
fFractionLast * stepTrial);
|
||||
else
|
||||
stepTrial *= 0.1;
|
||||
|
||||
// if(dbg) G4cerr<<"Dchord too big. Try new hstep="<<stepTrial<<G4endl;
|
||||
}
|
||||
// #ifdef TEST_CHORD_PRINT
|
||||
// TestChordPrint( noTrials, lastStepLength, dChordStep, stepTrial );
|
||||
// #endif
|
||||
|
||||
noTrials++;
|
||||
}
|
||||
while( ! validEndPoint ); // End of do-while RKD
|
||||
|
||||
if( newStepEst_Uncons > 0.0 ){
|
||||
fLastStepEstimate_Unconstrained= newStepEst_Uncons;
|
||||
}
|
||||
|
||||
AccumulateStatistics( noTrials );
|
||||
|
||||
// stepOfLastGoodChord = stepTrial;
|
||||
|
||||
if( pStepForAccuracy ){
|
||||
// Calculate the step size required for accuracy, if it is needed
|
||||
G4double dyErr_relative = dyErrPos/(epsStep*lastStepLength);
|
||||
if( dyErr_relative > 1.0 ) {
|
||||
stepForAccuracy =
|
||||
fIntgrDriver->ComputeNewStepSize( dyErr_relative,
|
||||
lastStepLength );
|
||||
}else{
|
||||
stepForAccuracy = 0.0; // Convention to show step was ok
|
||||
}
|
||||
*pStepForAccuracy = stepForAccuracy;
|
||||
}
|
||||
|
||||
#ifdef TEST_CHORD_PRINT
|
||||
static int dbg=0;
|
||||
if( dbg )
|
||||
G4cout << "ChordF/FindNextChord: NoTrials= " << noTrials
|
||||
<< " StepForGoodChord=" << std::setw(10) << stepTrial << G4endl;
|
||||
#endif
|
||||
|
||||
yEnd= yCurrent;
|
||||
return stepTrial;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#if 0
|
||||
// #ifdef G4VERBOSE
|
||||
if( dbg ) {
|
||||
G4cerr << "Returned from QuickAdvance with: yCur=" << yCurrent <<G4endl;
|
||||
G4cerr << " dChordStep= "<< dChordStep <<" dyErr=" << dyErr << G4endl;
|
||||
}
|
||||
#endif
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ...........................................................................
|
||||
|
||||
G4double G4ChordFinder::NewStep(G4double stepTrialOld,
|
||||
G4double dChordStep, // Curr. dchord achieved
|
||||
G4double& stepEstimate_Unconstrained )
|
||||
//
|
||||
// Is called to estimate the next step size, even for successful steps,
|
||||
// in order to predict an accurate 'chord-sensitive' first step
|
||||
// which is likely to assist in more performant 'stepping'.
|
||||
//
|
||||
|
||||
{
|
||||
G4double stepTrial;
|
||||
static G4double lastStepTrial = 1., lastDchordStep= 1.;
|
||||
|
||||
#if 1
|
||||
// const G4double threshold = 1.21, multiplier = 0.9;
|
||||
// 0.9 < 1 / std::sqrt(1.21)
|
||||
|
||||
if (dChordStep > 0.0)
|
||||
{
|
||||
stepEstimate_Unconstrained = stepTrialOld*std::sqrt( fDeltaChord / dChordStep );
|
||||
// stepTrial = 0.98 * stepEstimate_Unconstrained;
|
||||
stepTrial = fFractionNextEstimate * stepEstimate_Unconstrained;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should not update the Unconstrained Step estimate: incorrect!
|
||||
stepTrial = stepTrialOld * 2.;
|
||||
}
|
||||
|
||||
// if ( dChordStep < threshold * fDeltaChord ){
|
||||
// stepTrial= stepTrialOld * multiplier;
|
||||
// }
|
||||
if( stepTrial <= 0.001 * stepTrialOld)
|
||||
{
|
||||
if ( dChordStep > 1000.0 * fDeltaChord ){
|
||||
stepTrial= stepTrialOld * 0.03;
|
||||
}else{
|
||||
if ( dChordStep > 100. * fDeltaChord ){
|
||||
stepTrial= stepTrialOld * 0.1;
|
||||
}else{
|
||||
// Try halving the length until dChordStep OK
|
||||
stepTrial= stepTrialOld * 0.5;
|
||||
}
|
||||
}
|
||||
}else if (stepTrial > 1000.0 * stepTrialOld)
|
||||
{
|
||||
stepTrial= 1000.0 * stepTrialOld;
|
||||
}
|
||||
|
||||
if( stepTrial == 0.0 ){
|
||||
stepTrial= 0.000001;
|
||||
}
|
||||
|
||||
lastStepTrial = stepTrialOld;
|
||||
lastDchordStep= dChordStep;
|
||||
#else
|
||||
if ( dChordStep > 1000. * fDeltaChord ){
|
||||
stepTrial= stepTrialOld * 0.03;
|
||||
}else{
|
||||
if ( dChordStep > 100. * fDeltaChord ){
|
||||
stepTrial= stepTrialOld * 0.1;
|
||||
}else{
|
||||
// Keep halving the length until dChordStep OK
|
||||
stepTrial= stepTrialOld * 0.5;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// A more sophisticated chord-finder could figure out a better
|
||||
// stepTrial, from dChordStep and the required d_geometry
|
||||
// eg
|
||||
// Calculate R, r_helix (eg at orig point)
|
||||
// if( stepTrial < 2 pi R )
|
||||
// stepTrial = R arc_cos( 1 - fDeltaChord / r_helix )
|
||||
// else
|
||||
// ??
|
||||
|
||||
return stepTrial;
|
||||
}
|
||||
|
||||
//
|
||||
// Given a starting curve point A (CurveA_PointVelocity), a later
|
||||
// curve point B (CurveB_PointVelocity) and a point E which is (generally)
|
||||
// not on the curve, find and return a point F which is on the curve and
|
||||
// which is close to E. While advancing towards F utilise eps_step
|
||||
// as a measure of the relative accuracy of each Step.
|
||||
|
||||
G4FieldTrack
|
||||
G4ChordFinder::ApproxCurvePointV( const G4FieldTrack& CurveA_PointVelocity,
|
||||
const G4FieldTrack& CurveB_PointVelocity,
|
||||
const G4ThreeVector& CurrentE_Point,
|
||||
G4double eps_step)
|
||||
{
|
||||
// 1st implementation:
|
||||
// if r=|AE|/|AB|, and s=true path lenght (AB)
|
||||
// return the point that is r*s along the curve!
|
||||
|
||||
G4FieldTrack Current_PointVelocity= CurveA_PointVelocity;
|
||||
|
||||
G4ThreeVector CurveA_Point= CurveA_PointVelocity.GetPosition();
|
||||
G4ThreeVector CurveB_Point= CurveB_PointVelocity.GetPosition();
|
||||
|
||||
G4ThreeVector ChordAB_Vector= CurveB_Point - CurveA_Point;
|
||||
G4ThreeVector ChordAE_Vector= CurrentE_Point - CurveA_Point;
|
||||
|
||||
G4double ABdist= ChordAB_Vector.mag();
|
||||
G4double curve_length; // A curve length of AB
|
||||
G4double AE_fraction;
|
||||
|
||||
curve_length= CurveB_PointVelocity.GetCurveLength()
|
||||
- CurveA_PointVelocity.GetCurveLength();
|
||||
|
||||
// const
|
||||
G4double integrationInaccuracyLimit= std::max( perMillion, 0.5*eps_step );
|
||||
if( curve_length < ABdist * (1. - integrationInaccuracyLimit) ){
|
||||
#ifdef G4DEBUG_FIELD
|
||||
G4cerr << " Warning in G4ChordFinder::ApproxCurvePoint: "
|
||||
<< G4endl
|
||||
<< " The two points are further apart than the curve length "
|
||||
<< G4endl
|
||||
<< " Dist = " << ABdist
|
||||
<< " curve length = " << curve_length
|
||||
<< " relativeDiff = " << (curve_length-ABdist)/ABdist
|
||||
<< G4endl;
|
||||
if( curve_length < ABdist * (1. - 10*eps_step) ) {
|
||||
G4cerr << " ERROR: the size of the above difference"
|
||||
<< " exceeds allowed limits. Aborting." << G4endl;
|
||||
G4Exception("G4ChordFinder::ApproxCurvePointV()", "PrecisionError",
|
||||
FatalException, "Unphysical curve length.");
|
||||
}
|
||||
#endif
|
||||
// Take default corrective action:
|
||||
// --> adjust the maximum curve length.
|
||||
// NOTE: this case only happens for relatively straight paths.
|
||||
curve_length = ABdist;
|
||||
}
|
||||
|
||||
G4double new_st_length;
|
||||
|
||||
if ( ABdist > 0.0 ){
|
||||
AE_fraction = ChordAE_Vector.mag() / ABdist;
|
||||
}else{
|
||||
AE_fraction = 0.5; // Guess .. ?;
|
||||
#ifdef G4DEBUG_FIELD
|
||||
G4cout << "Warning in G4ChordFinder::ApproxCurvePoint:"
|
||||
<< " A and B are the same point!" << G4endl
|
||||
<< " Chord AB length = " << ChordAE_Vector.mag() << G4endl
|
||||
<< G4endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
if( (AE_fraction> 1.0 + perMillion) || (AE_fraction< 0.) ){
|
||||
#ifdef G4DEBUG_FIELD
|
||||
G4cerr << " G4ChordFinder::ApproxCurvePointV - Warning:"
|
||||
<< " Anomalous condition:AE > AB or AE/AB <= 0 " << G4endl
|
||||
<< " AE_fraction = " << AE_fraction << G4endl
|
||||
<< " Chord AE length = " << ChordAE_Vector.mag() << G4endl
|
||||
<< " Chord AB length = " << ABdist << G4endl << G4endl;
|
||||
G4cerr << " OK if this condition occurs after a recalculation of 'B'"
|
||||
<< G4endl << " Otherwise it is an error. " << G4endl ;
|
||||
#endif
|
||||
// This course can now result if B has been re-evaluated,
|
||||
// without E being recomputed (1 July 99)
|
||||
// In this case this is not a "real error" - but it undesired
|
||||
// and we cope with it by a default corrective action ...
|
||||
AE_fraction = 0.5; // Default value
|
||||
}
|
||||
|
||||
new_st_length= AE_fraction * curve_length;
|
||||
|
||||
G4bool good_advance;
|
||||
if ( AE_fraction > 0.0 ) {
|
||||
good_advance =
|
||||
fIntgrDriver->AccurateAdvance(Current_PointVelocity,
|
||||
new_st_length,
|
||||
eps_step ); // Relative accuracy
|
||||
// In this case it does not matter if it cannot advance the full distance
|
||||
}
|
||||
|
||||
// If there was a memory of the step_length actually require at the start
|
||||
// of the integration Step, this could be re-used ...
|
||||
|
||||
return Current_PointVelocity;
|
||||
}
|
||||
|
||||
void
|
||||
G4ChordFinder::TestChordPrint( G4int noTrials,
|
||||
G4int lastStepTrial,
|
||||
G4double dChordStep,
|
||||
G4double nextStepTrial )
|
||||
void G4ChordFinder::TestChordPrint( G4int noTrials,
|
||||
G4int lastStepTrial,
|
||||
G4double dChordStep,
|
||||
G4double nextStepTrial )
|
||||
{
|
||||
G4int oldprec= G4cout.precision(5);
|
||||
G4cout << " ChF/fnc: notrial " << std::setw( 3) << noTrials
|
||||
<< " this_step= " << std::setw(10) << lastStepTrial;
|
||||
if( std::fabs( (dChordStep / fDeltaChord) - 1.0 ) < 0.001 ){
|
||||
G4cout.precision(8);
|
||||
}else{ G4cout.precision(6); }
|
||||
G4cout << " dChordStep= " << std::setw(12) << dChordStep;
|
||||
if( std::fabs( (dChordStep / fDeltaChord) - 1.0 ) < 0.001 )
|
||||
{
|
||||
G4cout.precision(8);
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cout.precision(6);
|
||||
}
|
||||
G4cout << " dChordStep= " << std::setw(12) << dChordStep;
|
||||
if( dChordStep > fDeltaChord ) { G4cout << " d+"; }
|
||||
else { G4cout << " d-"; }
|
||||
G4cout.precision(5);
|
||||
|
||||
@@ -115,7 +115,7 @@ CalculatePointInside(G4ThreeVector safetyOrigin,
|
||||
}
|
||||
|
||||
G4double
|
||||
G4ChordFinderSaf::FindNextChord( const G4FieldTrack yStart,
|
||||
G4ChordFinderSaf::FindNextChord( const G4FieldTrack& yStart,
|
||||
G4double stepMax,
|
||||
G4FieldTrack& yEnd, // Endpoint
|
||||
G4double& dyErrPos, // Error of endpoint
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4ClassicalRK4.cc,v 1.12 2006/06/29 18:23:37 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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: G4ConstRK4.cc,v 1.2 2008/10/29 14:17:42 gcosmo Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// - 18.09.2008 - J.Apostolakis, T.Nikitina - Created
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
#include "G4ConstRK4.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4LineSection.hh"
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor sets the number of variables (default = 8)
|
||||
|
||||
G4ConstRK4::G4ConstRK4(G4Mag_EqRhs* EqRhs, G4int numberOfVariables)
|
||||
: G4MagErrorStepper(EqRhs, numberOfVariables)
|
||||
{
|
||||
if(numberOfVariables !=8 )
|
||||
{
|
||||
G4Exception("G4ConstRK4::G4ConstRK4()", "InvalidSetup", FatalException,
|
||||
"Valid only for number of variables=8. Use another Stepper!");
|
||||
}
|
||||
else
|
||||
{
|
||||
fEq=EqRhs;
|
||||
yMiddle= new G4double[8];
|
||||
dydxMid= new G4double[8];
|
||||
yInitial= new G4double[8];
|
||||
yOneStep= new G4double[8];
|
||||
|
||||
dydxm = new G4double[8];
|
||||
dydxt = new G4double[8];
|
||||
yt = new G4double[8];
|
||||
Field[0]=0.;Field[1]=0.;Field[2]=0.;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
|
||||
G4ConstRK4::~G4ConstRK4()
|
||||
{
|
||||
delete [] yMiddle;
|
||||
delete [] dydxMid;
|
||||
delete [] yInitial;
|
||||
delete [] yOneStep;
|
||||
delete [] dydxm;
|
||||
delete [] dydxt;
|
||||
delete [] yt;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Given values for the variables y[0,..,n-1] and their derivatives
|
||||
// dydx[0,...,n-1] known at x, use the classical 4th Runge-Kutta
|
||||
// method to advance the solution over an interval h and return the
|
||||
// incremented variables as yout[0,...,n-1], which is not a distinct
|
||||
// array from y. The user supplies the routine RightHandSide(x,y,dydx),
|
||||
// which returns derivatives dydx at x. The source is routine rk4 from
|
||||
// NRC p. 712-713 .
|
||||
|
||||
void G4ConstRK4::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
G4double h,
|
||||
G4double yOut[])
|
||||
{
|
||||
G4double hh = h*0.5 , h6 = h/6.0 ;
|
||||
|
||||
// 1st Step K1=h*dydx
|
||||
yt[5] = yIn[5] + hh*dydx[5] ;
|
||||
yt[4] = yIn[4] + hh*dydx[4] ;
|
||||
yt[3] = yIn[3] + hh*dydx[3] ;
|
||||
yt[2] = yIn[2] + hh*dydx[2] ;
|
||||
yt[1] = yIn[1] + hh*dydx[1] ;
|
||||
yt[0] = yIn[0] + hh*dydx[0] ;
|
||||
RightHandSideConst(yt,dydxt) ;
|
||||
|
||||
// 2nd Step K2=h*dydxt
|
||||
yt[5] = yIn[5] + hh*dydxt[5] ;
|
||||
yt[4] = yIn[4] + hh*dydxt[4] ;
|
||||
yt[3] = yIn[3] + hh*dydxt[3] ;
|
||||
yt[2] = yIn[2] + hh*dydxt[2] ;
|
||||
yt[1] = yIn[1] + hh*dydxt[1] ;
|
||||
yt[0] = yIn[0] + hh*dydxt[0] ;
|
||||
RightHandSideConst(yt,dydxm) ;
|
||||
|
||||
// 3rd Step K3=h*dydxm
|
||||
// now dydxm=(K2+K3)/h
|
||||
yt[5] = yIn[5] + h*dydxm[5] ;
|
||||
dydxm[5] += dydxt[5] ;
|
||||
yt[4] = yIn[4] + h*dydxm[4] ;
|
||||
dydxm[4] += dydxt[4] ;
|
||||
yt[3] = yIn[3] + h*dydxm[3] ;
|
||||
dydxm[3] += dydxt[3] ;
|
||||
yt[2] = yIn[2] + h*dydxm[2] ;
|
||||
dydxm[2] += dydxt[2] ;
|
||||
yt[1] = yIn[1] + h*dydxm[1] ;
|
||||
dydxm[1] += dydxt[1] ;
|
||||
yt[0] = yIn[0] + h*dydxm[0] ;
|
||||
dydxm[0] += dydxt[0] ;
|
||||
RightHandSideConst(yt,dydxt) ;
|
||||
|
||||
// 4th Step K4=h*dydxt
|
||||
yOut[5] = yIn[5]+h6*(dydx[5]+dydxt[5]+2.0*dydxm[5]);
|
||||
yOut[4] = yIn[4]+h6*(dydx[4]+dydxt[4]+2.0*dydxm[4]);
|
||||
yOut[3] = yIn[3]+h6*(dydx[3]+dydxt[3]+2.0*dydxm[3]);
|
||||
yOut[2] = yIn[2]+h6*(dydx[2]+dydxt[2]+2.0*dydxm[2]);
|
||||
yOut[1] = yIn[1]+h6*(dydx[1]+dydxt[1]+2.0*dydxm[1]);
|
||||
yOut[0] = yIn[0]+h6*(dydx[0]+dydxt[0]+2.0*dydxm[0]);
|
||||
|
||||
} // end of DumbStepper ....................................................
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Stepper
|
||||
|
||||
void
|
||||
G4ConstRK4::Stepper( const G4double yInput[],
|
||||
const G4double dydx[],
|
||||
G4double hstep,
|
||||
G4double yOutput[],
|
||||
G4double yError [] )
|
||||
{
|
||||
const G4int nvar = 8 ;
|
||||
const G4int maxvar= 8;
|
||||
|
||||
G4int i;
|
||||
|
||||
// Correction for Richardson extrapolation
|
||||
//
|
||||
G4double correction = 1. / ( (1 << IntegratorOrder()) -1 );
|
||||
|
||||
// Saving yInput because yInput and yOutput can be aliases for same array
|
||||
|
||||
for (i=0;i<nvar;i++) { yInitial[i]=yInput[i]; }
|
||||
|
||||
yInitial[7]= yInput[7]; // Copy the time in case...even if not really needed
|
||||
yMiddle[7] = yInput[7]; // Copy the time from initial value
|
||||
yOneStep[7] = yInput[7]; // As it contributes to final value of yOutput ?
|
||||
yOutput[7] = yInput[7]; // -> dumb stepper does it too for RK4
|
||||
for (i=nvar;i<maxvar;i++) { yOutput[i]=yInput[i]; }
|
||||
yError[7] = 0.0;
|
||||
|
||||
G4double halfStep = hstep * 0.5;
|
||||
|
||||
// Do two half steps
|
||||
//
|
||||
GetConstField(yInitial,Field);
|
||||
DumbStepper (yInitial, dydx, halfStep, yMiddle);
|
||||
RightHandSideConst(yMiddle, dydxMid);
|
||||
DumbStepper (yMiddle, dydxMid, halfStep, yOutput);
|
||||
|
||||
// Store midpoint, chord calculation
|
||||
//
|
||||
fMidPoint = G4ThreeVector( yMiddle[0], yMiddle[1], yMiddle[2]);
|
||||
|
||||
// Do a full Step
|
||||
//
|
||||
DumbStepper(yInitial, dydx, hstep, yOneStep);
|
||||
for(i=0;i<nvar;i++)
|
||||
{
|
||||
yError [i] = yOutput[i] - yOneStep[i] ;
|
||||
yOutput[i] += yError[i]*correction ;
|
||||
// Provides accuracy increased by 1 order via the
|
||||
// Richardson extrapolation
|
||||
}
|
||||
|
||||
fInitialPoint = G4ThreeVector( yInitial[0], yInitial[1], yInitial[2]);
|
||||
fFinalPoint = G4ThreeVector( yOutput[0], yOutput[1], yOutput[2]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Estimate the maximum distance from the curve to the chord
|
||||
//
|
||||
// We estimate this using the distance of the midpoint to chord.
|
||||
// The method below is good only for angle deviations < 2 pi;
|
||||
// this restriction should not be a problem for the Runge Kutta methods,
|
||||
// which generally cannot integrate accurately for large angle deviations
|
||||
|
||||
G4double G4ConstRK4::DistChord() const
|
||||
{
|
||||
G4double distLine, distChord;
|
||||
|
||||
if (fInitialPoint != fFinalPoint)
|
||||
{
|
||||
distLine= G4LineSection::Distline( fMidPoint, fInitialPoint, fFinalPoint );
|
||||
// This is a class method that gives distance of Mid
|
||||
// from the Chord between the Initial and Final points
|
||||
distChord = distLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
distChord = (fMidPoint-fInitialPoint).mag();
|
||||
}
|
||||
return distChord;
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4DELPHIMagField.cc,v 1.6 2006/06/29 18:23:39 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
#include "G4DELPHIMagField.hh"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4ElectricField.cc,v 1.2 2006/06/29 18:23:42 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4ElectroMagneticField.cc,v 1.3 2006/06/29 18:23:44 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4EqEMFieldWithSpin.cc,v 1.1 2007/08/30 23:34:19 gum Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// $Id: G4EqEMFieldWithSpin.cc,v 1.4 2008/11/21 21:17:03 gum Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// This is the standard right-hand side for equation of motion.
|
||||
@@ -39,15 +39,23 @@
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
#include "G4EqEMFieldWithSpin.hh"
|
||||
#include "G4ElectroMagneticField.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "globals.hh"
|
||||
|
||||
G4EqEMFieldWithSpin::G4EqEMFieldWithSpin(G4ElectroMagneticField *emField )
|
||||
: G4EquationOfMotion( emField ) { anomaly = 1.165923e-3; }
|
||||
: G4EquationOfMotion( emField )
|
||||
{
|
||||
anomaly = 0.0011659208;
|
||||
}
|
||||
|
||||
G4EqEMFieldWithSpin::~G4EqEMFieldWithSpin()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
G4EqEMFieldWithSpin::SetChargeMomentumMass(G4double particleCharge, // e+ units
|
||||
G4double MomentumXc,
|
||||
G4double MomentumXc,
|
||||
G4double particleMass)
|
||||
{
|
||||
fElectroMagCof = eplus*particleCharge*c_light ;
|
||||
@@ -60,14 +68,13 @@ G4EqEMFieldWithSpin::SetChargeMomentumMass(G4double particleCharge, // e+ units
|
||||
E = std::sqrt(sqr(MomentumXc)+sqr(particleMass));
|
||||
beta = MomentumXc/E;
|
||||
gamma = E/particleMass;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
G4EqEMFieldWithSpin::EvaluateRhsGivenB(const G4double y[],
|
||||
const G4double Field[],
|
||||
G4double dydx[] ) const
|
||||
const G4double Field[],
|
||||
G4double dydx[] ) const
|
||||
{
|
||||
|
||||
// Components of y:
|
||||
@@ -98,10 +105,12 @@ G4EqEMFieldWithSpin::EvaluateRhsGivenB(const G4double y[],
|
||||
dydx[4] = cof1*(cof2*Field[4] + (y[5]*Field[0] - y[3]*Field[2])) ;
|
||||
|
||||
dydx[5] = cof1*(cof2*Field[5] + (y[3]*Field[1] - y[4]*Field[0])) ;
|
||||
|
||||
dydx[6] = dydx[8] = 0.;//not used
|
||||
|
||||
// Lab Time of flight
|
||||
dydx[7] = inverse_velocity;
|
||||
|
||||
|
||||
G4ThreeVector BField(Field[0],Field[1],Field[2]);
|
||||
|
||||
G4ThreeVector u(y[3], y[4], y[5]);
|
||||
@@ -111,6 +120,9 @@ G4EqEMFieldWithSpin::EvaluateRhsGivenB(const G4double y[],
|
||||
G4double ucb = (anomaly+1./gamma)/beta;
|
||||
|
||||
G4ThreeVector Spin(y[9],y[10],y[11]);
|
||||
|
||||
if (Spin.mag() > 0.) Spin = Spin.unit();
|
||||
|
||||
G4ThreeVector dSpin;
|
||||
|
||||
dSpin = ParticleCharge*omegac*(ucb*(Spin.cross(BField))-udb*(Spin.cross(u)));
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4EqMagElectricField.cc,v 1.13 2006/06/29 18:23:46 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// $Id: G4EqMagElectricField.cc,v 1.14 2008/04/24 12:33:35 tnikitin Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// This is the standard right-hand side for equation of motion.
|
||||
@@ -87,6 +87,8 @@ G4EqMagElectricField::EvaluateRhsGivenB(const G4double y[],
|
||||
|
||||
dydx[5] = cof1*(cof2*Field[5] + (y[3]*Field[1] - y[4]*Field[0])) ;
|
||||
|
||||
dydx[6] = 0.;//not used
|
||||
|
||||
// Lab Time of flight
|
||||
dydx[7] = inverse_velocity;
|
||||
return ;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4EquationOfMotion.cc,v 1.9 2006/06/29 18:23:48 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4ErrorMag_UsualEqRhs.cc,v 1.1 2007/05/16 12:54:02 gcosmo Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4ExactHelixStepper.cc,v 1.8 2007/12/10 16:29:47 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// $Id: G4ExactHelixStepper.cc,v 1.9 2008/10/29 14:34:35 gcosmo Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// Helix a-la-Explicity Euler: x_1 = x_0 + helix(h)
|
||||
// with helix(h) being a helix piece of length h
|
||||
@@ -111,7 +111,7 @@ G4ExactHelixStepper::DumbStepper( const G4double yIn[],
|
||||
G4double G4ExactHelixStepper::DistChord() const
|
||||
{
|
||||
// Implementation : must check whether h/R > pi !!
|
||||
// If( h/R < pi) DistChord=h/2*tan(Ang_curve/4)
|
||||
// If( h/R < pi) DistChord=h/2*std::tan(Ang_curve/4)
|
||||
// Else DistChord=R_helix
|
||||
//
|
||||
G4double distChord;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4ExplicitEuler.cc,v 1.8 2006/06/29 18:23:53 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// Explicit Euler: x_1 = x_0 + h * dx_0
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4FieldManager.cc,v 1.14 2006/06/29 18:23:55 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// $Id: G4FieldManager.cc,v 1.15 2007/12/07 15:34:10 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "G4Field.hh"
|
||||
#include "G4MagneticField.hh"
|
||||
#include "G4ChordFinder.hh"
|
||||
#include "G4FieldManagerStore.hh"
|
||||
|
||||
G4FieldManager::G4FieldManager(G4Field *detectorField,
|
||||
G4ChordFinder *pChordFinder,
|
||||
@@ -54,6 +55,10 @@ G4FieldManager::G4FieldManager(G4Field *detectorField,
|
||||
fFieldChangesEnergy= detectorField->DoesFieldChangeEnergy();
|
||||
else
|
||||
fFieldChangesEnergy= fieldChangesEnergy;
|
||||
|
||||
// Add to store
|
||||
G4FieldManagerStore::Register(this);
|
||||
|
||||
}
|
||||
|
||||
G4FieldManager::G4FieldManager(G4MagneticField *detectorField)
|
||||
@@ -69,6 +74,8 @@ G4FieldManager::G4FieldManager(G4MagneticField *detectorField)
|
||||
fChordFinder= new G4ChordFinder( detectorField );
|
||||
fDelta_One_Step_Value= fDefault_Delta_One_Step_Value;
|
||||
fDelta_Intersection_Val= fDefault_Delta_Intersection_Val;
|
||||
// Add to store
|
||||
G4FieldManagerStore::Register(this);
|
||||
}
|
||||
|
||||
void G4FieldManager::ConfigureForTrack( const G4Track * )
|
||||
@@ -82,6 +89,7 @@ G4FieldManager::~G4FieldManager()
|
||||
if( fAllocatedChordFinder ){
|
||||
delete fChordFinder;
|
||||
}
|
||||
G4FieldManagerStore::DeRegister(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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: G4FieldManagerStore.cc,v 1.4 2008/01/17 10:56:23 gcosmo Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// G4FieldManagerStore
|
||||
//
|
||||
// Implementation for singleton container
|
||||
//
|
||||
// History:
|
||||
// 07.12.07 J.Apostolakis Adapted from G4LogicalVolumeStore
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "G4Types.hh"
|
||||
#include "G4FieldManagerStore.hh"
|
||||
#include "G4ChordFinder.hh"
|
||||
|
||||
// ***************************************************************************
|
||||
// Static class variables
|
||||
// ***************************************************************************
|
||||
//
|
||||
G4FieldManagerStore* G4FieldManagerStore::fgInstance = 0;
|
||||
G4bool G4FieldManagerStore::locked = false;
|
||||
|
||||
// ***************************************************************************
|
||||
// Protected constructor: Construct underlying container with
|
||||
// initial size of 100 entries
|
||||
// ***************************************************************************
|
||||
//
|
||||
G4FieldManagerStore::G4FieldManagerStore()
|
||||
: std::vector<G4FieldManager*>()
|
||||
{
|
||||
reserve(100);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Destructor
|
||||
// ***************************************************************************
|
||||
//
|
||||
G4FieldManagerStore::~G4FieldManagerStore()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Delete all elements from the store
|
||||
// ***************************************************************************
|
||||
//
|
||||
void G4FieldManagerStore::Clean()
|
||||
{
|
||||
// Locks store for deletion of field managers. De-registration will be
|
||||
// performed at this stage. G4FieldManagers will not de-register themselves.
|
||||
//
|
||||
locked = true;
|
||||
|
||||
size_t i=0;
|
||||
G4FieldManagerStore* store = GetInstance();
|
||||
|
||||
for(iterator pos=store->begin(); pos!=store->end(); pos++)
|
||||
{
|
||||
if (*pos) { delete *pos; }
|
||||
i++;
|
||||
}
|
||||
|
||||
#ifdef G4GEOMETRY_DEBUG
|
||||
if (store->size() < i-1)
|
||||
{ G4cout << "No field managers deleted. Already deleted by user ?" << G4endl; }
|
||||
else
|
||||
{ G4cout << i-1 << " field managers deleted !" << G4endl; }
|
||||
#endif
|
||||
|
||||
locked = false;
|
||||
store->clear();
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Add field manager to container
|
||||
// ***************************************************************************
|
||||
//
|
||||
void G4FieldManagerStore::Register(G4FieldManager* pFieldManager)
|
||||
{
|
||||
GetInstance()->push_back(pFieldManager);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Remove volume from container
|
||||
// ***************************************************************************
|
||||
//
|
||||
void G4FieldManagerStore::DeRegister(G4FieldManager* pFieldMgr)
|
||||
{
|
||||
if (!locked) // Do not de-register if locked !
|
||||
{
|
||||
for (iterator i=GetInstance()->begin(); i!=GetInstance()->end(); i++)
|
||||
{
|
||||
if (*i==pFieldMgr) // For LogVol was **i == *pLogVolume ... Reason?
|
||||
{
|
||||
GetInstance()->erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Return ptr to Store, setting if necessary
|
||||
// ***************************************************************************
|
||||
//
|
||||
G4FieldManagerStore* G4FieldManagerStore::GetInstance()
|
||||
{
|
||||
static G4FieldManagerStore worldStore;
|
||||
if (!fgInstance)
|
||||
{
|
||||
fgInstance = &worldStore;
|
||||
}
|
||||
return fgInstance;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Globally reset the state
|
||||
// ***************************************************************************
|
||||
//
|
||||
void
|
||||
G4FieldManagerStore::ClearAllChordFindersState()
|
||||
{
|
||||
G4ChordFinder *pChordFnd;
|
||||
|
||||
for (iterator i=GetInstance()->begin(); i!=GetInstance()->end(); i++)
|
||||
{
|
||||
pChordFnd = (*i)->GetChordFinder();
|
||||
if( pChordFnd )
|
||||
{
|
||||
pChordFnd->ResetStepEstimate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4FieldTrack.cc,v 1.13 2006/06/29 18:23:58 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// $Id: G4FieldTrack.cc,v 1.14 2007/10/03 15:34:42 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@@ -57,7 +57,7 @@ G4FieldTrack::G4FieldTrack( const G4ThreeVector& pPosition,
|
||||
fRestMass_c2(restMass_c2),
|
||||
fLabTimeOfFlight(LaboratoryTimeOfFlight),
|
||||
// fProperTimeOfFlight(0.0),
|
||||
fMomentumDir(pMomentumDirection),
|
||||
// fMomentumDir(pMomentumDirection),
|
||||
fChargeState( charge, magnetic_dipole_moment )
|
||||
{
|
||||
G4double momentum = std::sqrt(kineticEnergy*kineticEnergy
|
||||
@@ -65,6 +65,11 @@ G4FieldTrack::G4FieldTrack( const G4ThreeVector& pPosition,
|
||||
|
||||
G4ThreeVector pMomentum= momentum * pMomentumDirection;
|
||||
SetCurvePnt( pPosition, pMomentum, curve_length );
|
||||
// Sets momentum direction as well.
|
||||
|
||||
// Set the momentum direction again - keeping value from argument exactly
|
||||
fMomentumDir=pMomentumDirection;
|
||||
|
||||
InitialiseSpin( Spin );
|
||||
|
||||
// fpChargeState = new G4ChargeState( charge, magnetic_dipole_moment );
|
||||
@@ -83,7 +88,7 @@ G4FieldTrack::G4FieldTrack( const G4ThreeVector& pPosition,
|
||||
fRestMass_c2(restMass_c2),
|
||||
fLabTimeOfFlight(pLaboratoryTimeOfFlight),
|
||||
fProperTimeOfFlight(pProperTimeOfFlight),
|
||||
fMomentumDir(pMomentumDirection),
|
||||
// fMomentumDir(pMomentumDirection),
|
||||
fChargeState( DBL_MAX ) // charge not set
|
||||
{
|
||||
G4double momentum = std::sqrt(kineticEnergy*kineticEnergy
|
||||
@@ -91,6 +96,11 @@ G4FieldTrack::G4FieldTrack( const G4ThreeVector& pPosition,
|
||||
G4ThreeVector pMomentum= momentum * pMomentumDirection;
|
||||
|
||||
SetCurvePnt( pPosition, pMomentum, curve_length );
|
||||
// Sets momentum direction as well.
|
||||
|
||||
// Set the momentum direction again
|
||||
// -- to avoid numerical issues from multiplying by momentum and dividing again
|
||||
fMomentumDir=pMomentumDirection;
|
||||
|
||||
G4ThreeVector Spin(0.0, 0.0, 0.0);
|
||||
if( !pSpin ) Spin= G4ThreeVector(0.,0.,0.);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4HarmonicPolMagField.cc,v 1.6 2006/06/29 18:24:00 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4HelixExplicitEuler.cc,v 1.8 2007/12/10 16:29:49 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// Helix Explicit Euler: x_1 = x_0 + helix(h)
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4HelixHeum.cc,v 1.6 2006/06/29 18:24:04 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// Simple Heum:
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4HelixImplicitEuler.cc,v 1.6 2006/06/29 18:24:06 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// Helix Implicit Euler:
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4HelixSimpleRunge.cc,v 1.7 2006/06/29 18:24:08 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// Simple Runge:
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4ImplicitEuler.cc,v 1.9 2006/06/29 18:24:11 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// Implicit Euler:
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4LineCurrentMagField.cc,v 1.6 2006/06/29 18:24:13 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
#include "G4LineCurrentMagField.hh"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4LineSection.cc,v 1.10 2006/06/29 18:24:16 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4MagErrorStepper.cc,v 1.13 2006/06/29 18:24:18 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4MagHelicalStepper.cc,v 1.23 2007/09/05 12:20:17 gcosmo Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4MagIntegratorDriver.cc,v 1.49 2007/08/17 12:30:33 gcosmo Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4MagIntegratorStepper.cc,v 1.11 2006/06/29 18:24:34 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4Mag_EqRhs.cc,v 1.11 2006/06/29 18:24:36 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// This is the standard right-hand side for equation of motion
|
||||
// in a pure Magnetic Field .
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4Mag_SpinEqRhs.cc,v 1.12 2006/06/29 18:24:39 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// $Id: G4Mag_SpinEqRhs.cc,v 1.13 2008/11/21 21:18:26 gum Exp $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// This is the standard right-hand side for equation of motion.
|
||||
// This version of the right-hand side includes the three components
|
||||
@@ -44,7 +44,7 @@
|
||||
G4Mag_SpinEqRhs::G4Mag_SpinEqRhs( G4MagneticField* MagField )
|
||||
: G4Mag_EqRhs( MagField )
|
||||
{
|
||||
anomaly = 1.165923e-3;
|
||||
anomaly = 0.0011659208;
|
||||
}
|
||||
|
||||
G4Mag_SpinEqRhs::~G4Mag_SpinEqRhs() {}
|
||||
@@ -52,18 +52,18 @@ G4Mag_SpinEqRhs::~G4Mag_SpinEqRhs() {}
|
||||
void
|
||||
G4Mag_SpinEqRhs::SetChargeMomentumMass(G4double particleCharge, // in e+ units
|
||||
G4double MomentumXc,
|
||||
G4double mass)
|
||||
G4double particleMass)
|
||||
{
|
||||
// To set fCof_val
|
||||
G4Mag_EqRhs::SetChargeMomentumMass(particleCharge, MomentumXc, mass);
|
||||
G4Mag_EqRhs::SetChargeMomentumMass(particleCharge, MomentumXc, particleMass);
|
||||
|
||||
omegac = 0.105658387*GeV/mass * 2.837374841e-3*(rad/cm/kilogauss);
|
||||
omegac = 0.105658387*GeV/particleMass * 2.837374841e-3*(rad/cm/kilogauss);
|
||||
|
||||
ParticleCharge = particleCharge;
|
||||
|
||||
E = std::sqrt(sqr(MomentumXc)+sqr(mass));
|
||||
E = std::sqrt(sqr(MomentumXc)+sqr(particleMass));
|
||||
beta = MomentumXc/E;
|
||||
gamma = E/mass;
|
||||
gamma = E/particleMass;
|
||||
|
||||
}
|
||||
|
||||
@@ -95,6 +95,9 @@ G4Mag_SpinEqRhs::EvaluateRhsGivenB( const G4double y[],
|
||||
dydx[6] = dydx[7] = dydx[8] = 0.0;
|
||||
|
||||
G4ThreeVector Spin(y[9],y[10],y[11]);
|
||||
|
||||
if (Spin.mag() > 0.) Spin = Spin.unit();
|
||||
|
||||
G4ThreeVector dSpin;
|
||||
|
||||
dSpin = ParticleCharge*omegac*(ucb*(Spin.cross(BField))-udb*(Spin.cross(u)));
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4Mag_UsualEqRhs.cc,v 1.12 2006/06/29 18:24:42 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// This is the 'standard' right-hand side for the equation of motion
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4MagneticField.cc,v 1.3 2006/06/29 18:24:44 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4QuadrupoleMagField.cc,v 1.4 2006/06/29 18:24:46 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4RKG3_Stepper.cc,v 1.15 2007/08/21 10:17:41 tnikitin Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4SimpleHeum.cc,v 1.8 2006/06/29 18:24:51 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// Simple Heum:
|
||||
// x_1 = x_0 + h *
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4SimpleRunge.cc,v 1.10 2006/06/29 18:24:53 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
// Simple Runge:
|
||||
//
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4UniformElectricField.cc,v 1.12 2006/06/29 18:24:56 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//
|
||||
//
|
||||
// $Id: G4UniformMagField.cc,v 1.11 2006/06/29 18:24:58 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-01 $
|
||||
// GEANT4 tag $Name: geant4-09-02 $
|
||||
//
|
||||
//
|
||||
// Class for creation of uniform Magnetic Field
|
||||
|
||||
Reference in New Issue
Block a user