Import Geant4 0.0.0 source tree
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4CashKarpRKF45.cc,v 2.7 1998/11/19 20:57:05 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
// 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. Two different fourth order estimates are calculated;
|
||||
// their difference gives an error estimate.
|
||||
// (We use it to integrate the equations of the motion of a particle
|
||||
// in a magnetic field. )
|
||||
//
|
||||
// Similar to Numerical Recipes, .... put REFerence here!
|
||||
//
|
||||
|
||||
#include "G4CashKarpRKF45.hh"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor
|
||||
|
||||
G4CashKarpRKF45::G4CashKarpRKF45(G4Mag_EqRhs *EqRhs, G4int numberOfVariables):
|
||||
G4MagIntegratorStepper(EqRhs)
|
||||
{
|
||||
fNumberOfVariables = numberOfVariables ;
|
||||
|
||||
ak2 = new G4double[fNumberOfVariables] ;
|
||||
ak3 = new G4double[fNumberOfVariables] ;
|
||||
ak4 = new G4double[fNumberOfVariables] ;
|
||||
ak5 = new G4double[fNumberOfVariables] ;
|
||||
ak6 = new G4double[fNumberOfVariables] ;
|
||||
yTemp = new G4double[fNumberOfVariables] ;
|
||||
yIn = new G4double[fNumberOfVariables] ;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
|
||||
G4CashKarpRKF45::~G4CashKarpRKF45()
|
||||
{
|
||||
delete ak2;
|
||||
delete ak3;
|
||||
delete ak4;
|
||||
delete ak5;
|
||||
delete ak6;
|
||||
delete ak7;
|
||||
delete yTemp;
|
||||
delete yIn;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Given values for n = 6 variables yIn[0,...,n-1]
|
||||
// known at x, use the fifth-order Cash-Karp Runge-
|
||||
// Kutta-Fehlberg-4-5 method to advance the solution over an interval
|
||||
// Step and return the incremented variables as yOut[0,...,n-1]. Also
|
||||
// return an estimate of the local truncation error yErr[] using the
|
||||
// embedded 4th-order method. The user supplies routine
|
||||
// RightHandSide(y,dydx), which returns derivatives dydx for y .
|
||||
|
||||
void
|
||||
G4CashKarpRKF45::Stepper(const G4double yInput[],
|
||||
const G4double dydx[],
|
||||
const G4double Step,
|
||||
G4double yOut[],
|
||||
G4double yErr[])
|
||||
{
|
||||
// const G4int nvar = 6 ;
|
||||
G4int i;
|
||||
|
||||
const G4double a2 = 0.2 , a3 = 0.3 , a4 = 0.6 , a5 = 1.0 , a6 = 0.875 ,
|
||||
|
||||
b21 = 0.2 ,
|
||||
b31 = 3.0/40.0 , b32 = 9.0/40.0 ,
|
||||
b41 = 0.3 , b42 = -0.9 , b43 = 1.2 ,
|
||||
|
||||
b51 = -11.0/54.0 , b52 = 2.5 , b53 = -70.0/27.0 ,
|
||||
b54 = 35.0/27.0 ,
|
||||
|
||||
b61 = 1631.0/55296.0 , b62 = 175.0/512.0 ,
|
||||
b63 = 575.0/13824.0 , b64 = 44275.0/110592.0 ,
|
||||
b65 = 253.0/4096.0 ,
|
||||
|
||||
c1 = 37.0/378.0 , c3 = 250.0/621.0 , c4 = 125.0/594.0 ,
|
||||
c6 = 512.0/1771.0 ,
|
||||
dc5 = -277.0/14336.0 ;
|
||||
|
||||
const G4double dc1 = c1 - 2825.0/27648.0 , dc3 = c3 - 18575.0/48384.0 ,
|
||||
dc4 = c4 - 13525.0/55296.0 , dc6 = c6 - 0.25 ;
|
||||
|
||||
|
||||
// Saving yInput because yInput and yOut can be aliases for same array
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yIn[i]=yInput[i];
|
||||
}
|
||||
// RightHandSide(yIn, dydx) ; // 1st Step
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + b21*Step*dydx[i] ;
|
||||
}
|
||||
RightHandSide(yTemp, ak2) ; // 2nd Step
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + Step*(b31*dydx[i] + b32*ak2[i]) ;
|
||||
}
|
||||
RightHandSide(yTemp, ak3) ; // 3rd Step
|
||||
|
||||
for(i=0;i<fNumberOfVariables;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++)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
// Accumulate increments with proper weights
|
||||
|
||||
yOut[i] = yIn[i] + Step*(c1*dydx[i] + c3*ak3[i] + c4*ak4[i] + c6*ak6[i]) ;
|
||||
|
||||
// Estimate error as difference between 4th and
|
||||
// 5th order methods
|
||||
|
||||
yErr[i] = Step*(dc1*dydx[i] + dc3*ak3[i] + dc4*ak4[i] +
|
||||
dc5*ak5[i] + dc6*ak6[i]) ;
|
||||
}
|
||||
// NormaliseTangentVector( yOut ); // Not wanted
|
||||
|
||||
return ;
|
||||
|
||||
} // end of Stepper .......................................................
|
||||
|
||||
void
|
||||
G4CashKarpRKF45::StepWithEst(const G4double yInput[],
|
||||
const G4double dydx[],
|
||||
const G4double Step,
|
||||
G4double yOut[],
|
||||
G4double& alpha2,
|
||||
G4double& beta2,
|
||||
const G4double B1[],
|
||||
G4double B2[] )
|
||||
{
|
||||
|
||||
G4Exception("G4CashKarpRKF45::StepWithEst ERROR: This Method is no longer used.");
|
||||
|
||||
#if 0
|
||||
// const G4int nvar = 6 ;
|
||||
G4int i;
|
||||
|
||||
// Saving yInput because yInput and yOut can be aliases for same array
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yIn[i]=yInput[i];
|
||||
}
|
||||
|
||||
const G4double a2 = 0.2 , a3 = 0.3 , a4 = 0.6 , a5 = 1.0 , a6 = 0.875 ,
|
||||
|
||||
b21 = 0.2 ,
|
||||
b31 = 3.0/40.0 , b32 = 9.0/40.0 ,
|
||||
b41 = 0.3 , b42 = -0.9 , b43 = 1.2 ,
|
||||
|
||||
b51 = -11.0/54.0 , b52 = 2.5 , b53 = -70.0/27.0 ,
|
||||
b54 = 35.0/27.0 ,
|
||||
|
||||
b61 = 1631.0/55296.0 , b62 = 175.0/512.0 ,
|
||||
b63 = 575.0/13824.0 , b64 = 44275.0/110592.0 ,
|
||||
b65 = 253.0/4096.0 ,
|
||||
|
||||
c1 = 37.0/378.0 , c3 = 250.0/621.0 , c4 = 125.0/594.0 ,
|
||||
c6 = 512.0/1771.0 ,
|
||||
dc5 = -277.0/14336.0 ;
|
||||
|
||||
const G4double dc1 = c1 - 2825.0/27648.0 , dc3 = c3 - 18575.0/48384.0 ,
|
||||
dc4 = c4 - 13525.0/55296.0 , dc6 = c6 - 0.25 ;
|
||||
|
||||
alpha2 = 0 ;
|
||||
beta2 = 0 ;
|
||||
|
||||
// RightHandSide(yIn, dydx) ; // 1st Step
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
alpha2 += B1[i]*B1[i] ;
|
||||
beta2 += dydx[i+3]*dydx[i+3] ;
|
||||
}
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + b21*Step*dydx[i] ;
|
||||
}
|
||||
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(yTemp,ak2,B2) ; // Calculates yderive &
|
||||
// returns B too!
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
alpha2 += B2[i]*B2[i] ;
|
||||
beta2 += ak2[i+3]*ak2[i+3] ;
|
||||
}
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + Step*(b31*dydx[i] + b32*ak2[i]) ;
|
||||
}
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(yTemp,ak3,B2) ;
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
alpha2 += B2[i]*B2[i] ;
|
||||
beta2 += ak3[i+3]*ak3[i+3] ;
|
||||
}
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + Step*(b41*dydx[i] + b42*ak2[i] + b43*ak3[i]) ;
|
||||
}
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(yTemp,ak4,B2) ;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
alpha2 += B2[i]*B2[i] ;
|
||||
beta2 += ak4[i+3]*ak4[i+3] ;
|
||||
}
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + Step*(b51*dydx[i] + b52*ak2[i] + b53*ak3[i] +
|
||||
b54*ak4[i]) ;
|
||||
}
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(yTemp,ak5,B2) ;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
alpha2 += B2[i]*B2[i] ;
|
||||
beta2 += ak5[i+3]*ak5[i+3] ;
|
||||
}
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yTemp[i] = yIn[i] + Step*(b61*dydx[i] + b62*ak2[i] + b63*ak3[i] +
|
||||
b64*ak4[i] + b65*ak5[i]) ;
|
||||
}
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(yTemp,ak6,B2) ;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
alpha2 += B2[i]*B2[i] ;
|
||||
beta2 += ak6[i+3]*ak6[i+3] ;
|
||||
}
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
// Accumulate increments with proper weights
|
||||
|
||||
yOut[i] = yIn[i] + Step*(c1*dydx[i] + c3*ak3[i] + c4*ak4[i] + c6*ak6[i]) ;
|
||||
}
|
||||
|
||||
alpha2 *= sqr(GetEquationOfMotion()->FCof()*Step)/6.0 ;
|
||||
beta2 *= (Step*Step)/6.0 ;
|
||||
// NormaliseTangentVector( yOut );
|
||||
#endif
|
||||
|
||||
return ;
|
||||
|
||||
} // end of StepWithEst ....................................................
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4ChordFinder.cc,v 2.6 1998/11/13 14:30:21 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
// 25.02.97 John Apostolakis, desigh and implimentation
|
||||
// 05.03.97 V. Grichine , makeup to G4 'standard'
|
||||
|
||||
#include "G4ChordFinder.hh"
|
||||
#include "G4MagIntegratorDriver.hh"
|
||||
#include "G4Mag_UsualEqRhs.hh"
|
||||
#include "G4ClassicalRK4.hh"
|
||||
// #include "G4Field.hh"
|
||||
// #include "G4MagIntegratorStepper.hh"
|
||||
#include "G4MagIntegratorDriver.hh"
|
||||
|
||||
// For the moment fDeltaChord is a constant!
|
||||
|
||||
const G4double G4ChordFinder::fDefaultDeltaChord = 3. * mm;
|
||||
|
||||
// ..........................................................................
|
||||
|
||||
G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
G4double stepMinimum,
|
||||
G4MagIntegratorStepper* pItsStepper ) // A default one
|
||||
: fDeltaChord( fDefaultDeltaChord )
|
||||
{
|
||||
// Construct the Chord Finder
|
||||
// by creating in inverse order the Driver, the Stepper and EqRhs ...
|
||||
// G4Mag_EqRhs *
|
||||
fEquation = new G4Mag_UsualEqRhs(theMagField); // Should move q, p to
|
||||
//G4FieldTrack ??
|
||||
// --->> Charge Q = 0
|
||||
// --->> Momentum P = 1 NOMINAL VALUES !!!!!!!!!!!!!!!!!!
|
||||
|
||||
if( pItsStepper == 0 )
|
||||
{
|
||||
pItsStepper = fDriversStepper = new G4ClassicalRK4(fEquation);
|
||||
fAllocatedStepper= true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fAllocatedStepper= false;
|
||||
}
|
||||
fIntgrDriver = new G4MagInt_Driver(stepMinimum, pItsStepper);
|
||||
|
||||
}
|
||||
|
||||
// ......................................................................
|
||||
|
||||
G4ChordFinder::~G4ChordFinder()
|
||||
{
|
||||
delete fEquation; // fIntgrDriver->pIntStepper->theEquation_Rhs;
|
||||
if( fAllocatedStepper)
|
||||
{
|
||||
delete fDriversStepper;
|
||||
} // fIntgrDriver->pIntStepper;}
|
||||
delete fIntgrDriver;
|
||||
}
|
||||
|
||||
// ......................................................................
|
||||
|
||||
G4double
|
||||
G4ChordFinder::AdvanceChordLimited( G4FieldTrack& yCurrent,
|
||||
const G4double stepMax,
|
||||
const G4double epsStep )
|
||||
{
|
||||
G4double stepPossible;
|
||||
G4double dyErr;
|
||||
G4FieldTrack yEnd( yCurrent);
|
||||
|
||||
G4bool dbg= false;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if( dbg )
|
||||
G4cerr << "Entered FindNextChord Limited with:\n yCurrent: " << yCurrent
|
||||
<< " and initial Step=stepMax=" << stepMax << " mm. " << endl;
|
||||
#endif
|
||||
|
||||
stepPossible= FindNextChord(yCurrent, stepMax, yEnd, dyErr, epsStep);
|
||||
if ( dyErr < epsStep * stepPossible )
|
||||
{
|
||||
// Accept this accuracy.
|
||||
yCurrent = yEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Advance more accurately to "end of chord"
|
||||
#ifdef G4VERBOSE
|
||||
if (dbg) G4cerr << "Accurate advance to end of chord needed\n";
|
||||
#endif
|
||||
fIntgrDriver->AccurateAdvance(yCurrent, stepPossible, epsStep);
|
||||
}
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if( dbg ) G4cerr << "Exiting FindNextChord Limited with:\n yCurrent: "
|
||||
<< yCurrent<< endl;
|
||||
#endif
|
||||
|
||||
return stepPossible;
|
||||
}
|
||||
|
||||
// ..............................................................................
|
||||
|
||||
G4double
|
||||
G4ChordFinder::FindNextChord( const G4FieldTrack yStart,
|
||||
const G4double stepMax,
|
||||
G4FieldTrack& yEnd, // Endpoint
|
||||
G4double& dyErr, // Error of endpoint
|
||||
G4double epsStep )
|
||||
|
||||
// Returns Length of Step taken
|
||||
{
|
||||
// G4int stepRKnumber=0;
|
||||
G4FieldTrack yCurrent= yStart;
|
||||
G4double stepTrial= stepMax;
|
||||
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, dbg= false;
|
||||
G4double dChordStep;
|
||||
|
||||
fIntgrDriver-> GetDerivatives( yCurrent, dydx ) ;
|
||||
|
||||
do
|
||||
{
|
||||
yCurrent = yStart; // Always start from initial point
|
||||
|
||||
fIntgrDriver->QuickAdvance( yCurrent, dydx, stepTrial, dChordStep, dyErr);
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if( dbg ) {
|
||||
G4cerr << "Returned from QuickAdvance with: yCur=" << yCurrent << endl;
|
||||
G4cerr << " dChordStep= "<< dChordStep <<" dyErr=" << dyErr << endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// We check whether the criterion is met here.
|
||||
validEndPoint = AcceptableMissDist(dChordStep);
|
||||
|
||||
if( ! validEndPoint ) {
|
||||
// This is needed to decide new step size until QuickAdvance does it
|
||||
stepTrial = NewStep(stepTrial, dChordStep );
|
||||
|
||||
// Get the driver to calculate the new step size, if it is needed
|
||||
// stepTrial= fIntgrDriver->ComputeNewStepSize( dyErr/epsStep, stepTrial);
|
||||
#ifdef G4VERBOSE
|
||||
if( dbg )
|
||||
G4cerr << "Dchord too big. Trying new hstep=" << stepTrial << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
while( ! validEndPoint ); // End of do-while RKD
|
||||
|
||||
yEnd= yCurrent;
|
||||
return stepTrial;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
|
||||
G4double G4ChordFinder::NewStep(
|
||||
const G4double stepTrialOld,
|
||||
const G4double dChordStep ) // Current dchord achieved.
|
||||
|
||||
{
|
||||
G4double stepTrial;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//
|
||||
// G4FieldTrack G4NewMagTr::ApproxCurvePointV(
|
||||
// const G4FieldTrack& CurveA_PointVelocity,
|
||||
// const G4FieldTrack& CurveB_PointVelocity,
|
||||
// const G4ThreeVector& CurrentE_Point,
|
||||
// const G4double eps_step)
|
||||
//
|
||||
// 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,
|
||||
const 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.Position();
|
||||
G4ThreeVector CurveB_Point= CurveB_PointVelocity.Position();
|
||||
|
||||
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.CurveS() - CurveA_PointVelocity.CurveS();
|
||||
#ifdef DEBUG
|
||||
const G4double per_million=1e-6;
|
||||
if( ABdist * > curve_length * (1. + per_million ) ){
|
||||
G4cerr << " Error in ApproxCurvePoint \n" <<
|
||||
" The two points are further apart than the curve length " << endl <<
|
||||
" Dist = " << ABdist <<
|
||||
" curve length = " << curve_length << endl;
|
||||
}
|
||||
#endif
|
||||
G4double new_st_length;
|
||||
|
||||
if ( ABdist > 0.0 ){
|
||||
AE_fraction = ChordAE_Vector.mag() / ABdist;
|
||||
new_st_length= AE_fraction * curve_length;
|
||||
}else{
|
||||
G4cerr << " Error in ApproxCurvePoint: A and B are the same point\n" <<
|
||||
" Chord AB length = " << ChordAE_Vector.mag() << endl << endl;
|
||||
AE_fraction = 0.5; // Guess .. ?;
|
||||
new_st_length= AE_fraction * curve_length; // Is this correct ??
|
||||
}
|
||||
|
||||
if( (AE_fraction> 1.0 + perMillion) || (AE_fraction< 0.) ){
|
||||
G4cerr << " Error in ApproxCurvePoint: AE > AB or AE/AB <= 0 " << endl <<
|
||||
" AE_fraction = " << AE_fraction << endl <<
|
||||
" Chord AE length = " << ChordAE_Vector.mag() << endl <<
|
||||
" Chord AB length = " << ABdist << endl << endl;
|
||||
}
|
||||
|
||||
if ( AE_fraction > 0.0 ) {
|
||||
G4bool good_advance =
|
||||
fIntgrDriver->AccurateAdvance(Current_PointVelocity,
|
||||
new_st_length,
|
||||
eps_step/AE_fraction ); // Relative accuracy
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4ClassicalRK4.cc,v 2.8 1998/11/17 18:20:10 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4ClassicalRK4.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor sets the number of variables (default = 6)
|
||||
|
||||
G4ClassicalRK4:: G4ClassicalRK4(G4Mag_EqRhs *EqRhs, G4int numberOfVariables):
|
||||
G4MagErrorStepper(EqRhs, numberOfVariables),
|
||||
fNumberOfVariables(numberOfVariables)
|
||||
{
|
||||
dydxm = new G4double[fNumberOfVariables];
|
||||
dydxt = new G4double[fNumberOfVariables];
|
||||
yt = new G4double[fNumberOfVariables];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
|
||||
G4ClassicalRK4:: ~G4ClassicalRK4()
|
||||
{
|
||||
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 not be 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
|
||||
G4ClassicalRK4::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[])
|
||||
{
|
||||
const G4int nvar = fNumberOfVariables; // GetNumberOfVariables();
|
||||
G4int i;
|
||||
G4double hh = h*0.5 , h6 = h/6.0 ;
|
||||
|
||||
|
||||
for(i=0;i<nvar;i++)
|
||||
{
|
||||
yt[i] = yIn[i] + hh*dydx[i] ; // 1st Step K1=h*dydx
|
||||
}
|
||||
RightHandSide(yt,dydxt) ; // 2nd Step K2=h*dydxt
|
||||
|
||||
for(i=0;i<nvar;i++)
|
||||
{
|
||||
yt[i] = yIn[i] + hh*dydxt[i] ;
|
||||
}
|
||||
RightHandSide(yt,dydxm) ; // 3rd Step K3=h*dydxm
|
||||
|
||||
for(i=0;i<nvar;i++)
|
||||
{
|
||||
yt[i] = yIn[i] + h*dydxm[i] ;
|
||||
dydxm[i] += dydxt[i] ; // now dydxm=(K2+K3)/h
|
||||
}
|
||||
RightHandSide(yt,dydxt) ; // 4th Step K4=h*dydxt
|
||||
|
||||
for(i=0;i<nvar;i++) // Final RK4 output
|
||||
{
|
||||
yOut[i] = yIn[i] + h6*(dydx[i]+dydxt[i]+2.0*dydxm[i]); //+K1/6+K4/6+(K2+K3)/3
|
||||
}
|
||||
// NormaliseTangentVector( yOut );
|
||||
|
||||
return ;
|
||||
|
||||
} // end of DumbStepper ....................................................
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
void
|
||||
G4ClassicalRK4::StepWithEst( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[],
|
||||
G4double& alpha2,
|
||||
G4double& beta2,
|
||||
const G4double B1[],
|
||||
G4double B2[] )
|
||||
{
|
||||
|
||||
G4Exception(" G4ClassicalRK4::StepWithEst ERROR: this Method is no longer used.");
|
||||
|
||||
#if 0 // const G4int nvar = 6 ;
|
||||
const G4int nvar = GetNumberOfVariables();
|
||||
G4int i;
|
||||
G4double hh = h*0.5 , h6 = h/6.0 ;
|
||||
G4double B[3] ;
|
||||
alpha2 = 0 ;
|
||||
beta2 = 0 ;
|
||||
|
||||
for(i=0;i<nvar;i++)
|
||||
{
|
||||
yt[i] = yIn[i] + hh*dydx[i] ; // 1st Step K1=h*dydx
|
||||
}
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(yt,dydxt,B) ; // Calculates yderive &
|
||||
// returns B too!
|
||||
// RightHandSide(yt,dydxt) ; // 2nd Step K2=h*dydxt
|
||||
|
||||
for(i=0;i<nvar;i++)
|
||||
{
|
||||
yt[i] = yIn[i] + hh*dydxt[i] ;
|
||||
}
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(yt,dydxm,B2) ;
|
||||
// RightHandSide(yt,dydxm) ; // 3rd Step K3=h*dydxm
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
beta2 += dydx[i+3] *dydx[i+3]
|
||||
+ dydxt[i+3]*dydxt[i+3]
|
||||
+ dydxm[i+3]*dydxm[i+3] ;
|
||||
alpha2 += B1[i]*B1[i] + B[i]*B[i] + B2[i]*B2[i] ;
|
||||
}
|
||||
for(i=0;i<nvar;i++)
|
||||
{
|
||||
yt[i] = yIn[i] + h*dydxm[i] ;
|
||||
dydxm[i] += dydxt[i] ; // now dydxm=(K2+K3)/h
|
||||
}
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(yt,dydxt,B2) ;
|
||||
// RightHandSide(yt,dydxt) ; // 4th Step K4=h*dydxt
|
||||
|
||||
for(i=0;i<nvar;i++) // Final RK4 output
|
||||
{
|
||||
yOut[i] = yIn[i] + h6*(dydx[i]+dydxt[i]+2.0*dydxm[i]); //+K1/6+K4/6+(K2+K3)/3
|
||||
}
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
beta2 += dydxt[i+3]*dydxt[i+3] ;
|
||||
alpha2 += B2[i]*B2[i] ;
|
||||
}
|
||||
beta2 *= 0.25*h*h;
|
||||
alpha2 *= sqr(GetEquationOfMotion()->FCof()*h)*0.25 ;
|
||||
// NormaliseTangentVector( yOut );
|
||||
|
||||
#endif
|
||||
|
||||
return ;
|
||||
|
||||
} // end of StepWithEst ......................................................
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// This is the standard right-hand side for equation of motion.
|
||||
//
|
||||
// The only case another is required is when using a moving reference
|
||||
// frame ... or extending the class to include additional Forces,
|
||||
// eg an electric field
|
||||
//
|
||||
// 10.11.98 V.Grichine
|
||||
//
|
||||
#include "G4EqMagElectricField.hh"
|
||||
|
||||
void
|
||||
G4EqMagElectricField::
|
||||
SetChargeMomentumMass( const G4double particleCharge, // e+ units
|
||||
const G4double MomentumXc,
|
||||
const G4double particleMass)
|
||||
{
|
||||
fElectroMagCof = eplus*c_squared ;
|
||||
fElectroMagCof *= particleCharge/particleMass;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
G4EqMagElectricField::EvaluateRhsGivenB( const G4double y[],
|
||||
const G4double Field[],
|
||||
G4double dydx[] ) const
|
||||
{
|
||||
|
||||
// Components of y:
|
||||
// 0-2 dr/ds,
|
||||
// 3-5 dv/ds
|
||||
// FCof() = charge/mass
|
||||
|
||||
G4double vSquared = y[3]*y[3] + y[4]*y[4] + y[5]*y[5] ;
|
||||
|
||||
G4double vModule = sqrt(vSquared) ;
|
||||
|
||||
G4double vDotE = y[3]*Field[3] + y[4]*Field[4] + y[5]*Field[5] ;
|
||||
|
||||
G4double gammaReci = sqrt(1 - vSquared/c_squared) ;
|
||||
|
||||
dydx[0] = y[3]/vModule ;
|
||||
dydx[1] = y[4]/vModule ;
|
||||
dydx[2] = y[5]/vModule ;
|
||||
|
||||
dydx[3] = fElectroMagCof*(Field[3] + (y[4]*Field[2] - y[5]*Field[1])/c_light -
|
||||
y[3]*vDotE/c_light/c_light )*gammaReci/vModule ;
|
||||
|
||||
dydx[4] = fElectroMagCof*(Field[4] + (y[5]*Field[0] - y[3]*Field[2])/c_light -
|
||||
y[4]*vDotE/c_light/c_light )*gammaReci/vModule ;
|
||||
|
||||
dydx[5] = fElectroMagCof*(Field[5] + (y[3]*Field[1] - y[4]*Field[0])/c_light -
|
||||
y[5]*vDotE/c_light/c_light)*gammaReci/vModule ;
|
||||
return ;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4EquationOfMotion.cc,v 2.3 1998/11/12 19:48:23 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4EquationOfMotion.hh"
|
||||
|
||||
static const int G4maximum_number_of_field_components = 16;
|
||||
|
||||
void
|
||||
G4EquationOfMotion::RightHandSide( const G4double y[],
|
||||
G4double dydx[] ) const
|
||||
{
|
||||
G4double Field[G4maximum_number_of_field_components];
|
||||
|
||||
GetFieldValue(y, Field) ;
|
||||
EvaluateRhsGivenB( y, Field, dydx );
|
||||
}
|
||||
|
||||
void
|
||||
G4EquationOfMotion::EvaluateRhsReturnB( const G4double y[],
|
||||
G4double dydx[],
|
||||
G4double Field[] ) const
|
||||
{
|
||||
GetFieldValue(y, Field) ;
|
||||
EvaluateRhsGivenB( y, Field, dydx );
|
||||
}
|
||||
|
||||
#if HELP_THE_COMPILER
|
||||
void
|
||||
G4EquationOfMotion::doNothing()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4ExplicitEuler.cc,v 2.6 1998/11/12 16:16:10 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
// Explicit Euler: x_1 = x_0 + h * dx_0
|
||||
//
|
||||
// most simple approach for solving linear differential equations.
|
||||
// Take the current derivative and add it to the current position.
|
||||
//
|
||||
// W.Wander <wwc@mit.edu> 12/09/97
|
||||
|
||||
#include "G4ExplicitEuler.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor
|
||||
|
||||
G4ExplicitEuler::G4ExplicitEuler(G4Mag_EqRhs *EqRhs,
|
||||
G4int numberOfVariables) :
|
||||
G4MagErrorStepper(EqRhs, numberOfVariables),
|
||||
fNumberOfVariables(numberOfVariables)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
|
||||
G4ExplicitEuler::~G4ExplicitEuler()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
void
|
||||
G4ExplicitEuler::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[] )
|
||||
{
|
||||
// const G4int nvar = 6 ;
|
||||
|
||||
G4int i;
|
||||
|
||||
for(i=0;i<fNumberOfVariables;i++)
|
||||
{
|
||||
yOut[i] = yIn[i] + h*dydx[i] ; // 1st and only Step
|
||||
}
|
||||
// NormaliseTangentVector( yOut ); // this could harm more than
|
||||
// it helps - FIXME ???
|
||||
|
||||
return ;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4FieldManager.cc,v 2.1 1998/07/12 02:55:15 urbi Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4FieldManager.hh"
|
||||
|
||||
G4FieldManager::G4FieldManager()
|
||||
{
|
||||
fDetectorField= 0;
|
||||
fAllocatedChordFinder= false;
|
||||
}
|
||||
|
||||
G4FieldManager::G4FieldManager(G4MagneticField *detectorField)
|
||||
{
|
||||
fDetectorField= detectorField;
|
||||
|
||||
this->CreateChordFinder(detectorField);
|
||||
}
|
||||
|
||||
|
||||
G4FieldManager::~G4FieldManager()
|
||||
{
|
||||
if( fAllocatedChordFinder ){
|
||||
delete fChordFinder;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
G4FieldManager::CreateChordFinder(G4MagneticField *detectorMagField)
|
||||
{
|
||||
fChordFinder= new G4ChordFinder( detectorMagField );
|
||||
fAllocatedChordFinder= true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4FieldTrack.cc,v 2.3 1998/11/11 10:46:50 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4FieldTrack.hh"
|
||||
|
||||
ostream& operator<<( ostream& os, G4FieldTrack& SixVec)
|
||||
{
|
||||
G4double *SixV = SixVec.SixVector;
|
||||
os << " X= " << SixV[0] << " " << SixV[1] << " " << SixV[2] << " ";
|
||||
os << " V= " << SixV[3] << " " << SixV[4] << " " << SixV[5] << " ";
|
||||
os << " l= " << SixVec.CurveS();
|
||||
return os;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4HelixExplicitEuler.cc,v 2.3 1998/11/13 14:30:21 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4HelixExplicitEuler.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
//
|
||||
// Helix Explicit Euler: x_1 = x_0 + helix(h)
|
||||
// with helix(h) being a helix piece of length h
|
||||
// W.Wander <wwc@mit.edu> 12/09/97
|
||||
//
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// most simple approach for solving linear differential equations.
|
||||
// Take the current derivative and add it to the current position.
|
||||
//
|
||||
|
||||
void
|
||||
G4HelixExplicitEuler::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[])
|
||||
{
|
||||
AdvanceHelix(yIn, dydx, h, yOut);
|
||||
|
||||
// NormaliseTangentVector( yOut ); // this could harm more than it helps
|
||||
return ;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4HelixHeum.cc,v 2.3 1998/11/10 18:17:14 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4HelixHeum.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
//
|
||||
// Simple Heum:
|
||||
// x_1 = x_0 + h *
|
||||
// 1/4 * dx(t0,x0) +
|
||||
// 3/4 * dx(t0+2/3*h, x0+2/3*h*(dx(t0+h/3,x0+h/3*dx(t0,x0))))
|
||||
// W.Wander <wwc@mit.edu> 12/09/97
|
||||
//
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// third order solver
|
||||
//
|
||||
|
||||
void
|
||||
G4HelixHeum::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[])
|
||||
{
|
||||
const G4int nvar = 6 ;
|
||||
G4double dydxTemp[6], dydxTemp2[6];
|
||||
G4double yTemp[6], yAdd1[6], yAdd2[6] , yTemp2[6];
|
||||
|
||||
G4int i;
|
||||
|
||||
AdvanceHelix( yIn, dydx, h, yAdd1 );
|
||||
|
||||
AdvanceHelix( yIn, dydx, h/3.0, yTemp );
|
||||
RightHandSide(yTemp,dydxTemp);
|
||||
|
||||
AdvanceHelix( yIn, dydxTemp, (2.0 / 3.0) * h, yTemp2 );
|
||||
|
||||
RightHandSide(yTemp2,dydxTemp2);
|
||||
|
||||
AdvanceHelix( yIn, dydxTemp2, h, yAdd2 );
|
||||
|
||||
for( i = 0; i < nvar; i++ ) {
|
||||
yOut[i] = ( 0.25 * yAdd1[i] + 0.75 * yAdd2[i]);
|
||||
}
|
||||
|
||||
// NormaliseTangentVector( yOut );
|
||||
|
||||
return ;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4HelixImplicitEuler.cc,v 2.2 1998/11/10 18:17:14 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4HelixImplicitEuler.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
//
|
||||
// Helix Implicit Euler:
|
||||
// x_1 = x_0 + 1/2 * ( helix(h,t_0,x_0)
|
||||
// + helix(h,t_0+h,x_0+helix(h,t0,x0) ) )
|
||||
// W.Wander <wwc@mit.edu> 12/09/97
|
||||
//
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// second order solver
|
||||
// Take the current derivative and add it to the current position.
|
||||
// Take the output and its derivative. Add the mean of both derivatives
|
||||
// to form the final output
|
||||
//
|
||||
|
||||
void
|
||||
G4HelixImplicitEuler::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[])
|
||||
{
|
||||
const G4int nvar = 6 ;
|
||||
G4double dydxTemp[6];
|
||||
G4double yTemp[6], yTemp2[6];
|
||||
|
||||
G4int i;
|
||||
|
||||
// Step forward like in the explicit euler case
|
||||
AdvanceHelix( yIn, dydx, h, yTemp);
|
||||
|
||||
// now obtain the new field value at the new point
|
||||
RightHandSide(yTemp,dydxTemp);
|
||||
|
||||
// and also advance along a helix for this field value
|
||||
AdvanceHelix( yIn, dydxTemp, h, yTemp2);
|
||||
|
||||
// we take the average
|
||||
for( i = 0; i < nvar; i++ )
|
||||
yOut[i] = 0.5 * ( yTemp[i] + yTemp2[i] );
|
||||
|
||||
// NormaliseTangentVector( yOut );
|
||||
|
||||
return ;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4HelixSimpleRunge.cc,v 2.3 1998/11/13 14:30:22 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4HelixSimpleRunge.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
//
|
||||
// Simple Runge:
|
||||
// x_1 = x_0 + h * ( dx( t_0+h/2, x_0 + h/2 * dx( t_0, x_0) ) )
|
||||
// W.Wander <wwc@mit.edu> 12/09/97
|
||||
//
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// second order solver
|
||||
// take the derivative at a position to be assumed at the middle of the
|
||||
// Step and add it to the current position.
|
||||
//
|
||||
|
||||
void
|
||||
G4HelixSimpleRunge::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[])
|
||||
{
|
||||
const G4int nvar = 6 ;
|
||||
G4double dydxTemp[nvar];
|
||||
G4double yTemp[nvar]; // , yAdd[nvar];
|
||||
|
||||
AdvanceHelix( yIn, dydx, 0.5 * h, yTemp);
|
||||
|
||||
RightHandSide(yTemp,dydxTemp);
|
||||
|
||||
AdvanceHelix( yIn, dydxTemp, h, yOut);
|
||||
|
||||
// NormaliseTangentVector( yOut );
|
||||
|
||||
return ;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4ImplicitEuler.cc,v 2.6 1998/11/12 16:16:10 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
// Implicit Euler:
|
||||
//
|
||||
// x_1 = x_0 + h/2 * ( dx(t_0,x_0) + dx(t_0+h,x_0+h*dx(t_0,x_0) ) )
|
||||
//
|
||||
// second order solver
|
||||
// Take the current derivative and add it to the current position.
|
||||
// Take the output and its derivative. Add the mean of both derivatives
|
||||
// to form the final output
|
||||
//
|
||||
// W.Wander <wwc@mit.edu> 12/09/97
|
||||
// 6.11.98 V.Grichine, new constructor, fNumberOfVariables
|
||||
//
|
||||
|
||||
#include "G4ImplicitEuler.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor
|
||||
|
||||
G4ImplicitEuler::G4ImplicitEuler(G4Mag_EqRhs *EqRhs,
|
||||
G4int numberOfVariables):
|
||||
G4MagErrorStepper(EqRhs, numberOfVariables),
|
||||
fNumberOfVariables(numberOfVariables)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
|
||||
G4ImplicitEuler::~G4ImplicitEuler()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
void
|
||||
G4ImplicitEuler::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[])
|
||||
{
|
||||
// const G4int nvar = 6 ;
|
||||
G4double* dydxTemp = new G4double[fNumberOfVariables] ;
|
||||
G4double* yTemp = new G4double[fNumberOfVariables] ;
|
||||
|
||||
G4int i;
|
||||
|
||||
for( i = 0; i < fNumberOfVariables; i++ )
|
||||
{
|
||||
yTemp[i] = yIn[i] + h*dydx[i] ;
|
||||
}
|
||||
|
||||
RightHandSide(yTemp,dydxTemp);
|
||||
|
||||
for( i = 0; i < fNumberOfVariables; i++ )
|
||||
{
|
||||
yOut[i] = yIn[i] + 0.5 * h * ( dydx[i] + dydxTemp[i] );
|
||||
}
|
||||
|
||||
// NormaliseTangentVector( yOut );
|
||||
|
||||
return ;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4LineSection.cc,v 2.1 1998/07/12 02:55:20 urbi Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
// typedef double G4double;
|
||||
#include "G4LineSection.hh"
|
||||
|
||||
G4LineSection::G4LineSection( const G4ThreeVector& PntA,
|
||||
const G4ThreeVector& PntB )
|
||||
{
|
||||
EndpointA= PntA;
|
||||
VecAtoB=PntB-PntA;
|
||||
|
||||
inverse_square_distAB=1.0 / VecAtoB.mag2();
|
||||
}
|
||||
|
||||
G4double G4LineSection::Dist( G4ThreeVector OtherPnt ) const
|
||||
{
|
||||
G4double dist_sq;
|
||||
G4ThreeVector VecAZ;
|
||||
G4double sq_VecAZ, inner_prod, unit_projection ;
|
||||
|
||||
VecAZ= OtherPnt - EndpointA;
|
||||
sq_VecAZ = VecAZ.mag2();
|
||||
|
||||
inner_prod= VecAtoB.dot( VecAZ );
|
||||
|
||||
// Determine Projection(AZ on AB) / Length(AB)
|
||||
//
|
||||
unit_projection= inner_prod * InvsqDistAB();
|
||||
|
||||
if( (0. <= unit_projection ) && (unit_projection <= 1.0 ) )
|
||||
dist_sq= sq_VecAZ - unit_projection * inner_prod;
|
||||
else{
|
||||
// The perpendicular from the point to the line AB meets the line
|
||||
// in a point outside the line segment!
|
||||
//
|
||||
if( unit_projection < 0. ) {
|
||||
// A is the closest point
|
||||
dist_sq= sq_VecAZ;
|
||||
}else{
|
||||
// B is the closest point
|
||||
G4ThreeVector EndpointB = EndpointA + VecAtoB;
|
||||
G4ThreeVector VecBZ = OtherPnt - EndpointB;
|
||||
dist_sq = VecBZ.mag2();
|
||||
}
|
||||
}
|
||||
|
||||
return sqrt(dist_sq);
|
||||
}
|
||||
|
||||
G4double G4LineSection::Distline( const G4ThreeVector& OtherPnt,
|
||||
const G4ThreeVector& LinePntA,
|
||||
const G4ThreeVector& LinePntB )
|
||||
{
|
||||
G4LineSection LineAB( LinePntA, LinePntB ); // Line from A to B
|
||||
|
||||
return LineAB.Dist( OtherPnt );
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4MagErrorStepper.cc,v 2.3 1998/11/12 16:17:33 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4MagErrorStepper.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4LineSection.hh"
|
||||
|
||||
void
|
||||
G4MagErrorStepper::Stepper( const G4double yInput[],
|
||||
const G4double dydx[],
|
||||
const G4double hstep,
|
||||
G4double yOut[],
|
||||
G4double yErr[] )
|
||||
{
|
||||
const G4int nvar = 6 ;
|
||||
|
||||
G4int i;
|
||||
// correction for Richardson Extrapolation.
|
||||
G4double correction = 1. / ( (1 << IntegratorOrder()) -1 );
|
||||
|
||||
G4double yTemp[7], dydxTemp[6], yIn[7] ;
|
||||
|
||||
// Saving yInput because yInput and yOut can be aliases for same array
|
||||
|
||||
for(i=0;i<nvar;i++) yIn[i]=yInput[i];
|
||||
|
||||
G4double h = hstep * 0.5;
|
||||
|
||||
// Do two half steps
|
||||
|
||||
DumbStepper(yIn,dydx,h,yTemp);
|
||||
RightHandSide(yTemp,dydxTemp) ;
|
||||
DumbStepper(yTemp,dydxTemp,h,yOut);
|
||||
|
||||
// Store midpoint, chord calculation
|
||||
|
||||
yMidPoint = G4ThreeVector( yTemp[0], yTemp[1], yTemp[2]);
|
||||
|
||||
// Do a full Step
|
||||
h = hstep ;
|
||||
DumbStepper(yIn,dydx,h,yTemp);
|
||||
for(i=0;i<nvar;i++) {
|
||||
yErr[i] = yOut[i] - yTemp[i] ;
|
||||
yOut[i] += yErr[i]*correction ; // Provides by 1 increased
|
||||
// order of accuracy
|
||||
// Richardson Extrapolation
|
||||
}
|
||||
|
||||
yInitial = G4ThreeVector( yIn[0], yIn[1], yIn[2]);
|
||||
yFinal = G4ThreeVector( yOut[0], yOut[1], yOut[2]);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
G4double
|
||||
G4MagErrorStepper::DistChord() const
|
||||
{
|
||||
// Soon: must check whether h/R > 2 pi !!
|
||||
// Method below is good only for < 2 pi
|
||||
|
||||
return G4LineSection::Distline( yMidPoint, yInitial, yFinal );
|
||||
// This is a class method that gives distance of Mid
|
||||
// from the Chord between the Initial and Final points.
|
||||
}
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4MagHelicalStepper.cc,v 2.7 1998/11/13 14:30:23 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4MagHelicalStepper.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4LineSection.hh"
|
||||
// #include "G4MagneticField.hh"
|
||||
#include "G4Mag_EqRhs.hh"
|
||||
|
||||
// given a purely magnetic field a better approach than adding a straight line
|
||||
// (as in the normal runge-kutta-methods) is to add helix segments to the
|
||||
// current position
|
||||
|
||||
G4MagHelicalStepper::G4MagHelicalStepper(G4Mag_EqRhs *EqRhs)
|
||||
: G4MagIntegratorStepper(EqRhs)
|
||||
{
|
||||
fPtrMagEqOfMot = EqRhs;
|
||||
}
|
||||
|
||||
void
|
||||
G4MagHelicalStepper::AdvanceHelix( const G4double yIn[],
|
||||
const G4double Barr[],
|
||||
const G4double h,
|
||||
G4double yHelix[])
|
||||
{
|
||||
// const G4int nvar = 6;
|
||||
const G4double approc_limit = 0.05;
|
||||
|
||||
G4ThreeVector Bfld, Bnorm, B_x_P, vperp, vpar;
|
||||
// G4double norm;
|
||||
G4double B_d_P; // B_perp;
|
||||
G4double Theta; // , Theta_1;
|
||||
G4double R_1;
|
||||
G4double CosT2, SinT2, CosT, SinT;
|
||||
G4ThreeVector positionMove, endTangent;
|
||||
|
||||
Bfld= G4ThreeVector( Barr[0], Barr[1], Barr[2]);
|
||||
G4double Bmag = Bfld.mag();
|
||||
const G4double *pIn = yIn+3;
|
||||
G4ThreeVector initTangent= G4ThreeVector( pIn[0], pIn[1], pIn[2]);
|
||||
|
||||
// for too small magnetic fields there is no curvature
|
||||
// (include momentum here) FIXME
|
||||
|
||||
if( Bmag < 1e-12 ) {
|
||||
LinearStep( yIn, h, yHelix );
|
||||
} else {
|
||||
// Bnorm = Bfld.unit();
|
||||
Bnorm = (1.0/Bmag)*Bfld;
|
||||
|
||||
// calculate the direction of the force
|
||||
|
||||
B_x_P = Bnorm.cross(initTangent);
|
||||
|
||||
// parallel and perp vectors
|
||||
|
||||
B_d_P = Bnorm.dot(initTangent); // this is the fraction of P parallel to B
|
||||
|
||||
vpar = B_d_P * Bnorm; // the component parallel to B
|
||||
vperp= initTangent - vpar; // the component perpendicular to B
|
||||
|
||||
// B_v_P = sqrt( 1 - B_d_P * B_d_P); // Fraction of P perp to B
|
||||
|
||||
// calculate the radius^-1 of the helix and the stepping angle
|
||||
|
||||
R_1 = - fPtrMagEqOfMot->FCof() * Bmag; // / B_v_P - but this cancels
|
||||
|
||||
// again in Theta - so we don't need it.
|
||||
if( fabs(R_1) < 1e-10 ) {
|
||||
LinearStep( yIn, h, yHelix );
|
||||
} else {
|
||||
|
||||
Theta = R_1 * h; // * B_v_P;
|
||||
|
||||
// Trigonometrix
|
||||
|
||||
if( Theta < - approc_limit || Theta > approc_limit ) {
|
||||
SinT2 = sin(0.5 * Theta);
|
||||
CosT2 = cos(0.5 * Theta);
|
||||
// SinT = sin(Theta);
|
||||
// CosT = cos(Theta);
|
||||
SinT = 2.0 * SinT2 * CosT2;
|
||||
CosT = 1.0 - 2.0 * SinT2 * SinT2;
|
||||
} else {
|
||||
G4double Theta2 = Theta*Theta;
|
||||
G4double Theta3 = Theta2 * Theta;
|
||||
G4double Theta4 = Theta2 * Theta2;
|
||||
SinT = Theta - 1.0/6.0 * Theta3;
|
||||
CosT = 1 - 0.5 * Theta2 + 1.0/24.0 * Theta4;
|
||||
SinT2 = 0.5 * Theta - 1.0/48.0 * Theta3;
|
||||
CosT2 = 1 - 0.125 * Theta2 + 1.0/384 * Theta4;
|
||||
}
|
||||
|
||||
// the actual "rotation"
|
||||
|
||||
positionMove = h * ( CosT2 * vperp +
|
||||
SinT2 * B_x_P + vpar );
|
||||
endTangent = (CosT * vperp + SinT * B_x_P + vpar);
|
||||
|
||||
// Store the resulting position and tangent
|
||||
yHelix[0] = yIn[0] + positionMove.x();
|
||||
yHelix[1] = yIn[1] + positionMove.y();
|
||||
yHelix[2] = yIn[2] + positionMove.z();
|
||||
|
||||
yHelix[3] = endTangent.x();
|
||||
yHelix[4] = endTangent.y();
|
||||
yHelix[5] = endTangent.z();
|
||||
|
||||
// Store and/or calculate parameters for chord distance.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Use the midpoint method to get an error estimate and correction
|
||||
// modified from G4ClassicalRK4: W.Wander <wwc@mit.edu> 12/09/97
|
||||
//
|
||||
|
||||
void
|
||||
G4MagHelicalStepper::Stepper( const G4double yInput[],
|
||||
const G4double dydx[],
|
||||
const G4double hstep,
|
||||
G4double yOut[],
|
||||
G4double yErr[] )
|
||||
{
|
||||
const G4int nvar = 6 ;
|
||||
|
||||
G4int i;
|
||||
// correction for Richardson Extrapolation.
|
||||
G4double correction = 1. / ( (1 << IntegratorOrder()) -1 );
|
||||
|
||||
G4double yTemp[7], dydxTemp[6], yIn[7] ;
|
||||
|
||||
// Saving yInput because yInput and yOut can be aliases for same array
|
||||
|
||||
for(i=0;i<nvar;i++) yIn[i]=yInput[i];
|
||||
|
||||
G4double h = hstep * 0.5;
|
||||
|
||||
// Do two half steps
|
||||
|
||||
DumbStepper(yIn,dydx,h,yTemp);
|
||||
MagFieldEvaluate(yTemp,dydxTemp) ; // Was : RightHandSide(,)
|
||||
DumbStepper(yTemp,dydxTemp,h,yOut);
|
||||
|
||||
// Store midpoint, chord calculation
|
||||
|
||||
yMidPoint = G4ThreeVector( yTemp[0], yTemp[1], yTemp[2]);
|
||||
|
||||
// Do a full Step
|
||||
h = hstep ;
|
||||
DumbStepper(yIn,dydx,h,yTemp);
|
||||
for(i=0;i<nvar;i++) {
|
||||
yErr[i] = yOut[i] - yTemp[i] ;
|
||||
yOut[i] += yErr[i]*correction ; // Provides by 1 increased
|
||||
// order of accuracy
|
||||
// Richardson Extrapolation
|
||||
}
|
||||
|
||||
yInitial = G4ThreeVector( yIn[0], yIn[1], yIn[2]);
|
||||
yFinal = G4ThreeVector( yOut[0], yOut[1], yOut[2]);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
G4double
|
||||
G4MagHelicalStepper::DistChord() const
|
||||
{
|
||||
// Soon: must check whether h/R > 2 pi !!
|
||||
// Method below is good only for < 2 pi
|
||||
|
||||
return G4LineSection::Distline( yMidPoint, yInitial, yFinal );
|
||||
// This is a class method that gives distance of Mid
|
||||
// from the Chord between the Initial and Final points.
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4MagIntegratorDriver.cc,v 2.4 1998/11/11 18:51:48 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
//
|
||||
// Implementation for class G4MagInt_Driver
|
||||
// Tracking in space dependent magnetic field
|
||||
//
|
||||
// History of major changes:
|
||||
// 7 Oct 96 V. Grichine First version
|
||||
// 28 Jan 98 W. Wander: Added ability for low order integrators
|
||||
// 30 Jan 98 J. Apostolakis: Made method parameters into instance variables
|
||||
|
||||
#include <math.h>
|
||||
#include "G4ios.hh"
|
||||
#include "G4MagIntegratorDriver.hh"
|
||||
#include "G4FieldTrack.hh"
|
||||
|
||||
// Stepsize can increase by no more than 5.0
|
||||
// and decrease by no more than 1/10. = 0.1
|
||||
//
|
||||
const G4double G4MagInt_Driver::max_stepping_increase = 5.0;
|
||||
const G4double G4MagInt_Driver::max_stepping_decrease = 0.1;
|
||||
|
||||
G4bool
|
||||
G4MagInt_Driver::AccurateAdvance(
|
||||
G4FieldTrack& y_current,
|
||||
const G4double hstep,
|
||||
const G4double eps
|
||||
)
|
||||
// const G4double dydx[6], // We could may add this ??
|
||||
|
||||
// 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 .
|
||||
|
||||
// OLD:
|
||||
// The value h1 should be set as a guessed first stepsize, Hmin is the
|
||||
// minimum allowed stepsize. On output nOK and nBAD are the numbers of
|
||||
// good and bad (but retried and fixed) steps taken.
|
||||
{
|
||||
static const G4int maxstp = 5000;
|
||||
|
||||
G4int nstp, i ;
|
||||
G4double x, hnext, hdid, h ;
|
||||
|
||||
// G4double yscal[ncompSVEC];
|
||||
G4double y[G4FieldTrack::ncompSVEC], dydx[G4FieldTrack::ncompSVEC];
|
||||
G4double ystart[G4FieldTrack::ncompSVEC];
|
||||
G4double x1, x2;
|
||||
G4bool succeeded = true;
|
||||
|
||||
// Assume that hstep > 0
|
||||
|
||||
// ystart = y_current.PosVelVec();
|
||||
y_current.DumpToArray( ystart );
|
||||
x1= y_current.GetCurveLength();
|
||||
x2= x1 + hstep;
|
||||
|
||||
// // Initial Step size "h" is half the interval
|
||||
// h = 0.5 * hstep;
|
||||
// Initial Step size "h" is the full interval
|
||||
h = hstep;
|
||||
x = x1;
|
||||
|
||||
G4int nOK =0, nBAD = 0 ;
|
||||
|
||||
for(i=0;i<nvar;i++) y[i] = ystart[i] ;
|
||||
|
||||
nstp=1;
|
||||
do{
|
||||
pIntStepper->RightHandSide( y, dydx );
|
||||
|
||||
if( x+h > x2 ) h = x2 - x ; // When stepsize overshoots, decrease it!
|
||||
|
||||
OneGoodStep(y,dydx,x,h,eps,hdid,hnext) ;
|
||||
|
||||
if(hdid == h) nOK++ ; else nBAD++ ;
|
||||
|
||||
if(fabs(hnext) <= Hmin())
|
||||
{
|
||||
succeeded = false;
|
||||
// If simply a very small interval is being integrated, ...
|
||||
if( (fabs(hstep) > Hmin()) || (hnext > h) ){
|
||||
G4cerr<< " Warning (G4MagIntergratorDriver): The stepsize for the "
|
||||
" next iteration=" << hnext << " is too small - in Step number "
|
||||
<<nstp << " . Minimum for driver = "<< Hmin() << endl ;
|
||||
}
|
||||
}
|
||||
|
||||
h = hnext ;
|
||||
}while (((nstp++)<=maxstp) &&
|
||||
(x < x2) // Have we reached the end ?
|
||||
// --> a better test might be x-x2 > an_epsilon
|
||||
|
||||
);
|
||||
|
||||
for(i=0;i<nvar;i++) ystart[i] = y[i] ;
|
||||
|
||||
if(nstp > maxstp){
|
||||
|
||||
G4cerr << " Warning (G4MagIntergratorDriver): The number of steps "
|
||||
<< "used in the Integration driver (Runge-Kutta) is too many. "
|
||||
<< endl ;
|
||||
G4cerr << "Integration of the interval was not completed - only a "
|
||||
<< (x-x1)*100/(x2-x1)<<" % fraction of it was Done." << endl;
|
||||
succeeded = false;
|
||||
}
|
||||
|
||||
// Put back the values.
|
||||
y_current.LoadFromArray( ystart );
|
||||
y_current.SetCurveLength( x );
|
||||
|
||||
return succeeded;
|
||||
|
||||
} // end of AccurateAdvance ...........................
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
void
|
||||
G4MagInt_Driver::OneGoodStep( G4double y[],
|
||||
const G4double dydx[],
|
||||
G4double& x,
|
||||
const G4double htry,
|
||||
const G4double eps,
|
||||
G4double& hdid,
|
||||
G4double& hnext )
|
||||
|
||||
// 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
|
||||
|
||||
{
|
||||
G4double errmax, h, htemp, xnew ;
|
||||
G4int i;
|
||||
|
||||
G4double yerr[G4FieldTrack::ncompSVEC], ytemp[G4FieldTrack::ncompSVEC];
|
||||
|
||||
h = htry ; // Set stepsize to the initial trial value
|
||||
|
||||
for (;;)
|
||||
{
|
||||
pIntStepper-> Stepper(y,dydx,h,ytemp,yerr) ;
|
||||
|
||||
// Evaluate accuracy
|
||||
//
|
||||
errmax = sqrt( sqr(yerr[0]) + sqr(yerr[1]) + sqr(yerr[2]) );
|
||||
|
||||
errmax /= eps; // Scale relative to required tolerance
|
||||
if(errmax <= 1.0 ) break ; // Step succeeded.
|
||||
|
||||
// Step failed; compute the size of retrial Step.
|
||||
htemp = GetSafety()*h*pow(errmax,GetPshrnk()) ;
|
||||
|
||||
if(htemp >= 0.1*h) h = htemp ; // Truncation error too large,
|
||||
else h = 0.1*h ; // reduce stepsize, but no more
|
||||
// than a factor of 10
|
||||
xnew = x + h ;
|
||||
if(xnew == x) {
|
||||
G4cerr<<"Stepsize underflow in Stepper "<<endl ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute size of next Step
|
||||
if(errmax > errcon) hnext = GetSafety()*h*pow(errmax,GetPgrow()) ;
|
||||
else hnext = max_stepping_increase*h ;
|
||||
// No more than a factor of 5 increase
|
||||
|
||||
x += (hdid = h) ;
|
||||
|
||||
for(i=0;i<nvar;i++) y[i] = ytemp[i] ;
|
||||
|
||||
// delete[] ytemp ;
|
||||
// delete[] yerr ;
|
||||
return ;
|
||||
|
||||
} // end of OneGoodStep .............................
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// QuickAdvance just tries one Step - it does not ensure accuracy
|
||||
//
|
||||
G4bool G4MagInt_Driver::QuickAdvance(
|
||||
G4FieldTrack& y_posvel, // INOUT
|
||||
const G4double dydx[],
|
||||
G4double hstep, // In
|
||||
G4double& dchord_step,
|
||||
G4double& dyerr_len )
|
||||
{
|
||||
G4double yerr_vec[G4FieldTrack::ncompSVEC], yarrin[G4FieldTrack::ncompSVEC], yarrout[G4FieldTrack::ncompSVEC];
|
||||
G4double s_start;
|
||||
|
||||
// Move data into array
|
||||
y_posvel.DumpToArray( yarrin ); // yarrin <== y_posvel
|
||||
s_start = y_posvel.GetCurveLength();
|
||||
|
||||
// Do an Integration Step
|
||||
pIntStepper-> Stepper(yarrin, dydx, hstep, yarrout, yerr_vec) ;
|
||||
|
||||
// Estimate curve-chord distance
|
||||
dchord_step= pIntStepper-> DistChord();
|
||||
|
||||
// Put back the values.
|
||||
y_posvel.LoadFromArray( yarrout ); // yarrout ==> y_posvel
|
||||
y_posvel.SetCurveLength( s_start + hstep );
|
||||
|
||||
// A single measure of the error
|
||||
// TO-DO : account for tangent vector, energy, spin, ... ?
|
||||
dyerr_len= sqrt( sqr(yerr_vec[0])+sqr(yerr_vec[1])+sqr(yerr_vec[2]));
|
||||
|
||||
#ifdef RETURN_A_NEW_STEP_LENGTH
|
||||
// The following step cannot be done here because "eps" is not known.
|
||||
dyerr_len /= eps;
|
||||
|
||||
// Look at the velocity deviation ?
|
||||
// sqr(yerr_vec[3])+sqr(yerr_vec[4])+sqr(yerr_vec[5]));
|
||||
|
||||
// Look at the change in the velocity (squared maybe ..)
|
||||
G4double veloc_square = y_posvel.GetVelocity().mag2();
|
||||
|
||||
// Set suggested new step
|
||||
hstep= ComputeNewStepSize( dyerr_len, hstep);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// This method computes new step sizes - but does not limit changes to
|
||||
// within certain factors
|
||||
//
|
||||
|
||||
G4double
|
||||
G4MagInt_Driver::ComputeNewStepSize(
|
||||
G4double errMaxNorm, // max error (normalised)
|
||||
G4double hstepCurrent) // current step size
|
||||
{
|
||||
G4double hnew;
|
||||
|
||||
// Compute size of next Step for a failed step
|
||||
if(errMaxNorm > 1.0 ) {
|
||||
|
||||
// Step failed; compute the size of retrial Step.
|
||||
hnew = GetSafety()*hstepCurrent*pow(errMaxNorm,GetPshrnk()) ;
|
||||
}else{
|
||||
// Compute size of next Step for a successful step
|
||||
hnew = GetSafety()*hstepCurrent*pow(errMaxNorm,GetPgrow()) ;
|
||||
}
|
||||
|
||||
return hnew;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// This method computes new step sizes - but does not limit changes to
|
||||
// within certain factors
|
||||
//
|
||||
// It shares its logic with AccurateAdvance, so they should eventually
|
||||
// be merged ??
|
||||
|
||||
G4double
|
||||
G4MagInt_Driver::ComputeNewStepSize_WithinLimits(
|
||||
G4double errMaxNorm, // max error (normalised)
|
||||
G4double hstepCurrent) // current step size
|
||||
{
|
||||
G4double hnew;
|
||||
|
||||
// Compute size of next Step for a failed step
|
||||
if(errMaxNorm > 1.0 ) {
|
||||
|
||||
// Step failed; compute the size of retrial Step.
|
||||
hnew = GetSafety()*hstepCurrent*pow(errMaxNorm,GetPshrnk()) ;
|
||||
|
||||
if(hnew < max_stepping_decrease*hstepCurrent)
|
||||
hnew = max_stepping_decrease*hstepCurrent ;
|
||||
// reduce stepsize, but no more
|
||||
// than this factor (value= 1/10)
|
||||
}else{
|
||||
// Compute size of next Step for a successful step
|
||||
if(errMaxNorm > errcon) hnew = GetSafety()*hstepCurrent*pow(errMaxNorm,GetPgrow()) ;
|
||||
else hnew = max_stepping_increase * hstepCurrent ;
|
||||
// No more than a factor of 5 increase
|
||||
}
|
||||
|
||||
return hnew;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4MagIntegratorStepper.cc,v 2.0 1998/07/02 16:56:24 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4MagIntegratorStepper.hh"
|
||||
|
||||
// Constructor for creation of coefficient in Lorentz motion equation
|
||||
// as well as initialisation of geometry constants.
|
||||
// particleCharge is the particle charge in the elementary charge
|
||||
// momentumXc is the particle momentum multiplied by the speed of light in MeV,
|
||||
//
|
||||
|
||||
G4MagIntegratorStepper::G4MagIntegratorStepper(G4Mag_EqRhs *EqRhs)
|
||||
{
|
||||
theEquation_Rhs= EqRhs;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4Mag_EqRhs.cc,v 2.3 1998/11/12 16:19:40 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
// This is the standard right-hand side for equation of motion
|
||||
// in a pure Magnetic Field .
|
||||
//
|
||||
// Other that might be required are:
|
||||
// i) is when using a moving reference frame ... or
|
||||
// ii) extending for other forces, eg an electric field
|
||||
//
|
||||
// J. Apostolakis, January 13th, 1997
|
||||
//
|
||||
#include "G4MagneticField.hh"
|
||||
#include "G4Mag_EqRhs.hh"
|
||||
#include "G4EquationOfMotion.hh"
|
||||
|
||||
const G4double G4Mag_EqRhs::fUnitConstant = 0.299792458 * (GeV/(tesla*m));
|
||||
|
||||
// Constructor Implementation
|
||||
//
|
||||
G4Mag_EqRhs::G4Mag_EqRhs( G4MagneticField *magField )
|
||||
: G4EquationOfMotion(magField)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
G4Mag_EqRhs::SetChargeMomentumMass( const G4double particleCharge, // e+ units
|
||||
const G4double MomentumXc,
|
||||
const G4double particleMass)
|
||||
{
|
||||
fCof_val = fUnitConstant*particleCharge/MomentumXc; // B must be in Tesla
|
||||
// fMass = particleMass;
|
||||
}
|
||||
|
||||
G4Mag_EqRhs::~G4Mag_EqRhs() { }
|
||||
@@ -0,0 +1,38 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4Mag_UsualEqRhs.cc,v 2.2 1998/11/18 21:11:38 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
// This is the standard right-hand side for equation of motion.
|
||||
//
|
||||
// The only case another is required is when using a moving reference
|
||||
// frame ... or extending the class to include additional Forces,
|
||||
// eg an electric field
|
||||
//
|
||||
// J. Apostolakis, January 13th, 1997
|
||||
//
|
||||
#include "G4Mag_UsualEqRhs.hh"
|
||||
|
||||
void
|
||||
G4Mag_UsualEqRhs::EvaluateRhsGivenB( const G4double y[],
|
||||
const G4double B[3],
|
||||
G4double dydx[] ) const
|
||||
{
|
||||
G4double velocity_mag_square = sqr(y[3]) + sqr(y[4]) + sqr(y[5]);
|
||||
G4double inv_velocity_magnitude = 1.0 / sqrt( velocity_mag_square );
|
||||
|
||||
dydx[0] = y[3] * inv_velocity_magnitude; // (d/ds)x = Vx/V
|
||||
dydx[1] = y[4] * inv_velocity_magnitude; // (d/ds)y = Vy/V
|
||||
dydx[2] = y[5] * inv_velocity_magnitude; // (d/ds)z = Vz/V
|
||||
dydx[3] = FCof()*(y[4]*B[2] - y[5]*B[1]) ; // Ax = a*(Vy*Bz - Vz*By)
|
||||
dydx[4] = FCof()*(y[5]*B[0] - y[3]*B[2]) ; // Ay = a*(Vz*Bx - Vx*Bz)
|
||||
dydx[5] = FCof()*(y[3]*B[1] - y[4]*B[0]) ; // Az = a*(Vx*By - Vy*Bx)
|
||||
|
||||
return ;
|
||||
}
|
||||
@@ -0,0 +1,567 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4PropagatorInField.cc,v 2.11 1998/11/24 19:17:32 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
//
|
||||
// This routine implements an algorithm to track a particle in a //
|
||||
// non-uniform magnetic field. It utilises an ODE solver (with //
|
||||
// the Runge - Kutta method) to evolve the particle, and drives it //
|
||||
// until the particle has traveled a set distance or it enters a new
|
||||
// volume.
|
||||
//
|
||||
// Caveat: tracking is not exact - volumes can be missed!
|
||||
//
|
||||
//
|
||||
// 14.10.96 John Apostolakis, design and implementation
|
||||
// 17.03.97 John Apostolakis, renaming new set functions being added
|
||||
//
|
||||
|
||||
#include "G4PropagatorInField.hh"
|
||||
#include "G4ios.hh"
|
||||
#include <iomanip.h>
|
||||
|
||||
const G4double G4PropagatorInField::delta_intersection_val= 0.1 * mm;
|
||||
const G4double G4PropagatorInField::delta_one_step_val = 0.25 * mm;
|
||||
|
||||
G4double
|
||||
G4PropagatorInField::
|
||||
ComputeStep(const G4ThreeVector & StartPointA,
|
||||
const G4ThreeVector & Velocity, // Unit or non
|
||||
G4double CurrentProposedStepLength,
|
||||
G4double ¤tSafety, // In/Out
|
||||
G4VPhysicalVolume *pPhysVol )
|
||||
// Compute the next geometric Step for simple magnetic field
|
||||
{
|
||||
G4FieldTrack aFieldTrack =
|
||||
G4FieldTrack( StartPointA,
|
||||
Velocity,
|
||||
0.0, // length of path
|
||||
0.0, // energy
|
||||
0.0, // lab tof
|
||||
0.0, // proper tof
|
||||
0 );
|
||||
|
||||
// Do the Transport in the field (non recti-linear)
|
||||
return this->ComputeStep( aFieldTrack,
|
||||
CurrentProposedStepLength,
|
||||
currentSafety );
|
||||
}
|
||||
|
||||
G4double
|
||||
G4PropagatorInField::
|
||||
ComputeStep(G4FieldTrack& pFieldTrack,
|
||||
G4double CurrentProposedStepLength,
|
||||
G4double& currentSafety, // IN/OUT
|
||||
G4VPhysicalVolume *pPhysVol)
|
||||
|
||||
// Compute the next geometric Step
|
||||
{
|
||||
// Parameters for adaptive Runge-Kutta integration
|
||||
//
|
||||
G4double h_TrialStepSize; // 1st Step Size
|
||||
G4double TruePathLength;
|
||||
G4double StepTaken= 0.0;
|
||||
G4double s_length_taken;
|
||||
G4bool intersects;
|
||||
G4bool first_substep= true;
|
||||
|
||||
G4double NewSafety;
|
||||
fParticleIsLooping= false;
|
||||
|
||||
G4FieldTrack CurrentState(pFieldTrack);
|
||||
|
||||
#if 0
|
||||
CurrentState.SetVelocity( pFieldTrack.GetMomentumDir() );
|
||||
// For now, must utilize unit "velocity" J.A. Nov 17, 98
|
||||
|
||||
// Problem in setting the energy in this case .... (and in E field)
|
||||
#endif
|
||||
|
||||
|
||||
G4FieldTrack OriginalState= CurrentState;
|
||||
|
||||
// If the Step length is "infinite", then an approximate-maximum Step lenght
|
||||
// (used to calculate the relative accuracy) must be guessed.
|
||||
//
|
||||
|
||||
if( CurrentProposedStepLength >= kInfinity ){
|
||||
G4ThreeVector StartPointA, VelocityUnit;
|
||||
StartPointA = pFieldTrack.GetPosition();
|
||||
VelocityUnit= pFieldTrack.GetMomentumDir();
|
||||
CurrentProposedStepLength= 1.e3 * ( 10.0 * cm +
|
||||
fNavigator->GetWorldVolume()->GetLogicalVolume()->
|
||||
GetSolid()->DistanceToOut(StartPointA, VelocityUnit) ) ;
|
||||
}
|
||||
this->SetEpsilonStep( DeltaOneStep() / CurrentProposedStepLength);
|
||||
|
||||
G4int do_loop_count=0;
|
||||
do
|
||||
{
|
||||
do_loop_count++;
|
||||
G4FieldTrack SubStepStartState= CurrentState;
|
||||
G4ThreeVector SubStartPoint= CurrentState.GetPosition();
|
||||
// WAS = G4Navigator::Locate...
|
||||
|
||||
if( !first_substep)
|
||||
{
|
||||
fNavigator->LocateGlobalPointWithinVolume( SubStartPoint );
|
||||
}
|
||||
|
||||
// First figure out how far to evolve the particle !
|
||||
// -------------------------------------------------
|
||||
// and (later) with what accuracy to calculate this path.
|
||||
//
|
||||
h_TrialStepSize= CurrentProposedStepLength - StepTaken ;
|
||||
|
||||
// Next evolve it as far as this allows.
|
||||
// ---------------------------------------
|
||||
//
|
||||
// B <- Integrator - limited by the "chord miss" rule.
|
||||
//
|
||||
|
||||
s_length_taken= GetChordFinder()->AdvanceChordLimited(
|
||||
CurrentState, // Position & velocity
|
||||
h_TrialStepSize,
|
||||
GetEpsilonStep() );
|
||||
|
||||
// On Exit:
|
||||
// CurrentState is updated with the final position and velocity.
|
||||
|
||||
G4ThreeVector EndPointB= CurrentState.Position();
|
||||
|
||||
// Calculate the direction and length of the chord AB
|
||||
|
||||
G4ThreeVector ChordAB_Vector= EndPointB - SubStartPoint;
|
||||
G4double ChordAB_Length= ChordAB_Vector.mag(); // Magnitude (norm)
|
||||
G4ThreeVector ChordAB_Dir= ChordAB_Vector.unit();
|
||||
|
||||
// Check whether any volumes are encountered by the chord AB
|
||||
|
||||
G4double LinearStepLength =
|
||||
fNavigator->ComputeStep( SubStartPoint, ChordAB_Dir,
|
||||
ChordAB_Length, NewSafety);
|
||||
if( first_substep )
|
||||
{
|
||||
currentSafety= NewSafety;
|
||||
}
|
||||
// It might also be possible to update safety in other steps, but
|
||||
// it must be Done with care. J.Apostolakis August 5th, 1997
|
||||
|
||||
intersects= (LinearStepLength <= ChordAB_Length);
|
||||
// G4Navigator contracts to return k_infinity if len==asked
|
||||
// and it did not find a surface boundary at that length
|
||||
LinearStepLength = min( LinearStepLength, ChordAB_Length);
|
||||
|
||||
if( intersects )
|
||||
{
|
||||
// E <- Intersection Point of chord AB and either volume A's surface
|
||||
// or a daughter volume's surface ..
|
||||
|
||||
G4ThreeVector pointE= SubStartPoint + LinearStepLength * ChordAB_Dir;
|
||||
|
||||
G4FieldTrack IntersectPointVelct_G(CurrentState); // FT-Def-Construct
|
||||
|
||||
// Find the intersection point of AB true path with the surface
|
||||
// of vol(A) given our current "estimate" point E.
|
||||
|
||||
G4bool found_intersection=
|
||||
LocateIntersectionPoint( SubStepStartState, CurrentState,
|
||||
pointE, IntersectPointVelct_G );
|
||||
|
||||
if( found_intersection )
|
||||
{
|
||||
// G is our EndPoint ...
|
||||
G4ThreeVector IntersectPoint_G = IntersectPointVelct_G.Position();
|
||||
|
||||
End_PointAndTangent= IntersectPointVelct_G;
|
||||
G4ThreeVector NewChord= IntersectPoint_G - SubStartPoint;
|
||||
// LinearStepLength= NewChord.mag();
|
||||
StepTaken =
|
||||
TruePathLength= IntersectPointVelct_G.CurveS()
|
||||
- OriginalState.CurveS(); // which is Zero now.
|
||||
#ifdef G4VERBOSE
|
||||
if( Verbose() > 0 ){
|
||||
G4cout << " Found an intersection after a Step of length " <<
|
||||
StepTaken << endl;
|
||||
}
|
||||
#endif
|
||||
// TruePathLength= StepTaken;
|
||||
}
|
||||
else
|
||||
{
|
||||
// "Minor" chords do not intersect
|
||||
intersects= false;
|
||||
}
|
||||
}
|
||||
if( ! intersects )
|
||||
{
|
||||
StepTaken += s_length_taken;
|
||||
}
|
||||
first_substep= false;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if( Verbose() > 0 )
|
||||
printStatus( SubStepStartState, // or OriginalState,
|
||||
CurrentState,
|
||||
CurrentProposedStepLength,
|
||||
NewSafety,
|
||||
do_loop_count,
|
||||
pPhysVol);
|
||||
#endif
|
||||
|
||||
}
|
||||
while( (!intersects ) && (StepTaken < CurrentProposedStepLength)
|
||||
&& ( do_loop_count < GetMaxLoopCount() ) );
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if( do_loop_count >= GetMaxLoopCount() ){
|
||||
// G4cerr << "G4PropagateInField: Particle is looping - must be killed" << endl;
|
||||
G4cerr << "G4PropagateInField: Particle is looping - "
|
||||
<< " tracking in field will be stopped. " << endl;
|
||||
G4cerr << " Has performed " << do_loop_count << " steps in Field "
|
||||
<< " while a maximum of " << GetMaxLoopCount() << " are allowed. "
|
||||
<< endl;
|
||||
//G4cerr << " In future this will be treated better/quicker. " << endl;
|
||||
fParticleIsLooping= true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( ! intersects )
|
||||
{
|
||||
// Chord AB or "minor chords" do not intersect
|
||||
|
||||
// B is the endpoint Step of the current Step.
|
||||
// [ But if we were angle limited we could use B
|
||||
// as a new starting point ? ]
|
||||
|
||||
// On return we specify the endpoint, point B
|
||||
End_PointAndTangent= CurrentState;
|
||||
// LinearStepLength= ChordAB_Length;
|
||||
TruePathLength= StepTaken;
|
||||
|
||||
} // end if(!intersects)
|
||||
|
||||
// Set pFieldTrack to the return value
|
||||
pFieldTrack =End_PointAndTangent;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
// Check that "s" is correct
|
||||
if( fabs(OriginalState.CurveS() + TruePathLength
|
||||
- End_PointAndTangent.CurveS()) > 3.e-4 * TruePathLength )
|
||||
{
|
||||
G4cerr << " Error in G4PropagatorInField: Curve lenght mis-match, is advancement wrong ? ";
|
||||
G4cerr << " The curve length of the endpoint should be "
|
||||
<< OriginalState.CurveS() + TruePathLength
|
||||
<< " and is " << End_PointAndTangent.CurveS()
|
||||
<< " a difference of "
|
||||
<< OriginalState.CurveS() + TruePathLength
|
||||
- End_PointAndTangent.CurveS() << endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
return TruePathLength;
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// G4bool
|
||||
// G4PropagatorInField::LocateIntersectionPoint(
|
||||
// const G4FieldTrack& CurveStartPointVelocity, // A
|
||||
// const G4FieldTrack& CurveEndPointVelocity, // B
|
||||
// const G4ThreeVector& TrialPoint, // E
|
||||
// G4FieldTrack& IntersectPointVelocity) // Output
|
||||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Function that returns the intersection of the true path with the surface
|
||||
// of the current volume (either the external one or the inner one with one
|
||||
// of the daughters
|
||||
//
|
||||
// A = Initial point
|
||||
// B = another point
|
||||
//
|
||||
// Both A and B are assumed to be on the true path.
|
||||
//
|
||||
// E is the first point of intersection of the chord AB with
|
||||
// a volume other than A (on the surface of A or of a daughter)
|
||||
//
|
||||
// First Version: October 16th, 1996 John Apostolakis, CERN CN/ASD
|
||||
// Modified: January 22nd, 1997 J.A. IT/ASD
|
||||
//
|
||||
// Convention of Use :
|
||||
// i) If it returns "true", then IntersectionPointVelocity is set
|
||||
// to the approximate intersection point.
|
||||
// ii) If it returns "false", no intersection was found and
|
||||
// IntersectionPointVelocity is invalid.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
G4bool
|
||||
G4PropagatorInField::LocateIntersectionPoint(
|
||||
const G4FieldTrack& CurveStartPointVelocity, // A
|
||||
const G4FieldTrack& CurveEndPointVelocity, // B
|
||||
const G4ThreeVector& TrialPoint, // E
|
||||
G4FieldTrack& IntersectPointVelocity) // Output
|
||||
{
|
||||
// Find Intersection Point ( A, B, E ) of true path AB - start at E.
|
||||
|
||||
G4bool found_approximate_intersection = false;
|
||||
G4bool there_is_no_intersection = false;
|
||||
|
||||
G4FieldTrack CurrentA_PointVelocity= CurveStartPointVelocity;
|
||||
G4FieldTrack CurrentB_PointVelocity= CurveEndPointVelocity;
|
||||
G4ThreeVector CurrentE_Point= TrialPoint;
|
||||
|
||||
G4FieldTrack ApproxIntersecPointV(CurveEndPointVelocity); // FT-Def-Construct
|
||||
G4double NewSafety;
|
||||
G4bool first_step= true;
|
||||
G4int substep_no= 0;
|
||||
G4VPhysicalVolume *pPhysVol;
|
||||
|
||||
do{ // REPEAT
|
||||
|
||||
G4ThreeVector Point_A= CurrentA_PointVelocity.Position();
|
||||
G4ThreeVector Point_B= CurrentB_PointVelocity.Position();
|
||||
|
||||
// F = a point on true AB path close to point E (the closest if possible)
|
||||
//
|
||||
ApproxIntersecPointV= GetChordFinder()->ApproxCurvePointV(
|
||||
CurrentA_PointVelocity,
|
||||
CurrentB_PointVelocity,
|
||||
CurrentE_Point,
|
||||
this->GetEpsilonStep() );
|
||||
|
||||
// The above function is the most difficult part ...
|
||||
//
|
||||
// Another approach would be for the curved true path
|
||||
// to be an object and this should be a member function.
|
||||
// -> The Curve Start and End point would not be needed as arguments.
|
||||
//
|
||||
G4ThreeVector CurrentF_Point= ApproxIntersecPointV.Position();
|
||||
|
||||
// First check whether EF is small - then F is a good approx. point
|
||||
//
|
||||
// Calculate the length and direction of the chord AF
|
||||
|
||||
// ChordEF_Vector= Chord_Vector(CurrentE_Point, CurrentF_Point);
|
||||
// ------------
|
||||
G4ThreeVector ChordEF_Vector = CurrentF_Point - CurrentE_Point;
|
||||
|
||||
if ( ChordEF_Vector.mag2() <= sqr(DeltaIntersection()) ){
|
||||
|
||||
found_approximate_intersection = true;
|
||||
|
||||
// Create the "point" return value
|
||||
// IntersectPointVelocity.SetCurvePnt(
|
||||
// CurrentE_Point,
|
||||
// ApproxIntersecPointV.GetVelocity(),
|
||||
// ApproxIntersecPointV.CurveS() );
|
||||
IntersectPointVelocity = ApproxIntersecPointV;
|
||||
IntersectPointVelocity.SetPosition( CurrentE_Point );
|
||||
|
||||
// Note: in order to return a point on the boundary,
|
||||
// we must return E. But it is F on the curve.
|
||||
// So we must "cheat": we are using the position at point E and
|
||||
// the velocity at point F !!!
|
||||
//
|
||||
// This must limit the length we can allow for displacement!
|
||||
|
||||
}else{ // E is NOT close enough to the curve (ie point F).
|
||||
|
||||
if( !first_step){
|
||||
// Check whether any volumes are encountered by the chord AF
|
||||
//----------------------------------------------------------
|
||||
fNavigator->LocateGlobalPointWithinVolume( Point_A );
|
||||
// This locate is needed in all cases except for the
|
||||
// original point A, because - presumably - that was
|
||||
// called at the start of the physical Step
|
||||
}
|
||||
first_step= false;
|
||||
|
||||
// Calculate the length and direction of the chord AF
|
||||
G4ThreeVector ChordAF_Vector= CurrentF_Point - Point_A;
|
||||
G4double ChordAF_Length= ChordAF_Vector.mag();
|
||||
G4ThreeVector ChordAF_Dir= ChordAF_Vector.unit();
|
||||
|
||||
G4double stepLength =
|
||||
fNavigator->ComputeStep( Point_A, ChordAF_Dir,
|
||||
ChordAF_Length, NewSafety);
|
||||
|
||||
G4bool Intersects_AF = (stepLength <= ChordAF_Length);
|
||||
stepLength = min(stepLength, ChordAF_Length);
|
||||
if( Intersects_AF ){
|
||||
// There is an intersection of AF with a volume boundary
|
||||
|
||||
// G <- First Intersection of Chord AF
|
||||
//
|
||||
G4ThreeVector PointG= Point_A + stepLength * ChordAF_Dir;
|
||||
|
||||
// G is our new Candidate for the intersection point.
|
||||
// It replaces "E" and we will repeat the test to see if
|
||||
// it is a good enough approximate point for us.
|
||||
// B <- F
|
||||
// E <- G
|
||||
CurrentB_PointVelocity= ApproxIntersecPointV;
|
||||
CurrentE_Point= PointG;
|
||||
|
||||
// Else (not Intersects_AF)
|
||||
}else{
|
||||
// In this case:
|
||||
// There is NO intersection of AF with a volume boundary.
|
||||
// We must continue the search in the segment FB!
|
||||
|
||||
// Check whether any volumes are encountered by the chord FB
|
||||
//----------------------------------------------------------
|
||||
// Calculate the length and direction of the chord AF
|
||||
G4ThreeVector ChordFB_Vector= Point_B - CurrentF_Point;
|
||||
G4double ChordFB_Length= ChordFB_Vector.mag();
|
||||
G4ThreeVector ChordFB_Dir= ChordFB_Vector.unit();
|
||||
|
||||
fNavigator->LocateGlobalPointWithinVolume( CurrentF_Point );
|
||||
G4double stepLength =
|
||||
fNavigator->ComputeStep( CurrentF_Point, ChordFB_Dir,
|
||||
ChordFB_Length, NewSafety);
|
||||
|
||||
G4bool Intersects_FB = stepLength <= ChordFB_Length;
|
||||
stepLength = min(stepLength, ChordFB_Length);
|
||||
if( Intersects_FB ) {
|
||||
// There is an intersection of FB with a volume boundary
|
||||
// H <- First Intersection of Chord FB
|
||||
//
|
||||
G4ThreeVector PointH= CurrentF_Point + stepLength * ChordFB_Dir;
|
||||
|
||||
// H is our new Candidate for the intersection point.
|
||||
// It replaces "E" and we will repeat the test to see if
|
||||
// it is a good enough approximate point for us.
|
||||
|
||||
// Note that F must be in volume volA (the same as A)
|
||||
// (otherwise AF would meet a volume boundary!)
|
||||
// A <- F
|
||||
// E <- H
|
||||
CurrentA_PointVelocity= ApproxIntersecPointV;
|
||||
CurrentE_Point= PointH;
|
||||
|
||||
}else{ // (not Intersects_FB)
|
||||
//
|
||||
// There is NO intersection of FB with a volume boundary
|
||||
// This means that somehow a volume intersected the original
|
||||
// chord but misses the chord (or series of chords)
|
||||
// we have used.
|
||||
//
|
||||
there_is_no_intersection= true;
|
||||
//
|
||||
// the value of IntersectPointVelocity returned is not valid
|
||||
|
||||
} // Endif (Intersects_FB)
|
||||
|
||||
} // Endif (Intersects_AF)
|
||||
|
||||
} // EndIf ( E is close enough to the curve, ie point F. )
|
||||
// tests ChordAF_Vector.mag() <= maximum_lateral_displacement
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if( Verbose() > 1 )
|
||||
printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
|
||||
-1.0, NewSafety, substep_no, 0); // startVolume);
|
||||
#endif
|
||||
substep_no++;
|
||||
|
||||
} while ( ( ! found_approximate_intersection ) &&
|
||||
( ! there_is_no_intersection ) ); // UNTIL found or failed
|
||||
|
||||
return !there_is_no_intersection ; // Success or failure
|
||||
|
||||
}
|
||||
|
||||
void G4PropagatorInField::printStatus(
|
||||
const G4FieldTrack& StartFT,
|
||||
const G4FieldTrack& CurrentFT,
|
||||
G4double requestStep,
|
||||
G4double safety,
|
||||
G4int Step,
|
||||
G4VPhysicalVolume* startVolume)
|
||||
// G4VPhysicalVolume* endVolume)
|
||||
{
|
||||
const G4int verboseLevel=1;
|
||||
const G4ThreeVector StartPosition= StartFT.GetPosition();
|
||||
const G4ThreeVector StartUnitVelocity= StartFT.GetMomentumDir();
|
||||
const G4ThreeVector CurrentPosition= CurrentFT.GetPosition();
|
||||
const G4ThreeVector CurrentUnitVelocity= CurrentFT.GetMomentumDir();
|
||||
|
||||
G4double step_len= CurrentFT.GetCurveLength()
|
||||
- StartFT.GetCurveLength();
|
||||
|
||||
if( (Step == 0) && (verboseLevel <= 3) )
|
||||
{
|
||||
G4cout.precision(3);
|
||||
// G4cout.setf(ios_base::fixed,ios_base::floatfield);
|
||||
G4cout << setw( 6) << " "
|
||||
<< setw( 25) << " Current Position and Direction" << " "
|
||||
<< endl;
|
||||
G4cout << setw( 5) << "Step#" << " "
|
||||
<< setw( 9) << "X(mm)" << " "
|
||||
<< setw( 9) << "Y(mm)" << " "
|
||||
<< setw( 9) << "Z(mm)" << " "
|
||||
<< setw( 7) << " N_x " << " "
|
||||
<< setw( 7) << " N_y " << " "
|
||||
<< setw( 7) << " N_z " << " "
|
||||
// << setw( 9) << "KinE(MeV)" << " "
|
||||
// << setw( 9) << "dE(MeV)" << " "
|
||||
<< setw( 9) << "StepLen" << " "
|
||||
<< setw( 9) << "PhsStep" << " "
|
||||
<< setw(12) << "StartSafety" << " "
|
||||
<< setw(18) << "NextVolume" << " "
|
||||
<< endl;
|
||||
}
|
||||
|
||||
//
|
||||
if( verboseLevel > 3 )
|
||||
{
|
||||
// G4cout << "Current Position is " << CurrentPosition << endl
|
||||
// << " and UnitVelocity is " << CurrentUnitVelocity << endl;
|
||||
G4cout << "Step taken was " << step_len
|
||||
<< " out of PhysicalStep= " << requestStep << endl;
|
||||
G4cout << "Final safety is: " << safety << endl;
|
||||
|
||||
G4cout << "Chord length = " << (CurrentPosition-StartPosition).mag() << endl;
|
||||
G4cout << endl;
|
||||
}
|
||||
else // if( verboseLevel > 0 )
|
||||
{
|
||||
G4cout.precision(3);
|
||||
G4cout << setw( 5) << Step << " "
|
||||
<< setw( 9) << CurrentPosition.x() << " "
|
||||
<< setw( 9) << CurrentPosition.y() << " "
|
||||
<< setw( 9) << CurrentPosition.z() << " "
|
||||
<< setw( 7) << CurrentUnitVelocity.x() << " "
|
||||
<< setw( 7) << CurrentUnitVelocity.y() << " "
|
||||
<< setw( 7) << CurrentUnitVelocity.z() << " "
|
||||
// << setw( 9) << KineticEnergy << " "
|
||||
// << setw( 9) << EnergyDifference << " "
|
||||
<< setw( 9) << step_len << " "
|
||||
<< setw( 9) << requestStep << " "
|
||||
<< setw(12) << safety << " ";
|
||||
if( startVolume != 0) {
|
||||
G4cout << setw(12) << startVolume->GetName() << " ";
|
||||
} else {
|
||||
G4cout << setw(12) << "OutOfWorld" << " ";
|
||||
}
|
||||
|
||||
#if 0
|
||||
if( CurrentVolume != 0)
|
||||
{
|
||||
G4cout << setw(12) << CurrentVolume()->GetName() << " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cout << setw(12) << "OutOfWorld or Unknown" << " ";
|
||||
}
|
||||
#endif
|
||||
G4cout << endl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4RKG3_Stepper.cc,v 2.4 1998/11/12 17:20:41 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4RKG3_Stepper.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4LineSection.hh"
|
||||
|
||||
void G4RKG3_Stepper::Stepper( const G4double yInput[7],
|
||||
const G4double dydx[7],
|
||||
const G4double Step,
|
||||
G4double yOut[7],
|
||||
G4double yErr[])
|
||||
{
|
||||
G4double B[3];
|
||||
// G4double yderiv[6];
|
||||
// G4double alpha2, beta2;
|
||||
const G4int nvar = 6 ;
|
||||
// G4double beTemp2, beta2=0;
|
||||
|
||||
G4int i;
|
||||
G4double by15 = 1. / 15. ; // was 0.066666666 ;
|
||||
G4double yTemp[7], dydxTemp[6], yIn[7] ;
|
||||
// Saving yInput because yInput and yOut can be aliases for same array
|
||||
for(i=0;i<nvar;i++) yIn[i]=yInput[i];
|
||||
|
||||
G4double h = Step * 0.5;
|
||||
|
||||
// Do two half steps
|
||||
|
||||
|
||||
// To obtain B1 ...
|
||||
// GetEquationOfMotion()->GetFieldValue(yIn,B);
|
||||
// G4RKG3_Stepper::StepWithEst(yIn, dydx, Step, yOut,alpha2, beta2, B1, B2 );
|
||||
|
||||
StepNoErr(yIn, dydx,h, yTemp,B) ;
|
||||
// RightHandSide(yTemp,dydxTemp) ;
|
||||
GetEquationOfMotion()->EvaluateRhsGivenB(yTemp,B,dydxTemp) ;
|
||||
StepNoErr(yTemp,dydxTemp,h,yOut,B); // ,beTemp2) ;
|
||||
// beta2 += beTemp2;
|
||||
// beta2 *= 0.5;
|
||||
|
||||
// Store midpoint, chord calculation
|
||||
|
||||
fyMidPoint = G4ThreeVector( yTemp[0], yTemp[1], yTemp[2]);
|
||||
|
||||
// Do a full Step
|
||||
|
||||
h *= 2 ;
|
||||
StepNoErr(yIn,dydx,h,yTemp,B); // ,beTemp2) ;
|
||||
for(i=0;i<nvar;i++)
|
||||
{
|
||||
yErr[i] = yOut[i] - yTemp[i] ;
|
||||
yOut[i] += yErr[i]*by15 ; // Provides 5th order of accuracy
|
||||
}
|
||||
|
||||
// for(i=0;i<ncomp;i++)
|
||||
// {
|
||||
// fyInitial[i] = yIn[i];
|
||||
// fyFinal[i] = yOut[i];
|
||||
// }
|
||||
|
||||
fyInitial = G4ThreeVector( yIn[0], yIn[1], yIn[2]);
|
||||
fyFinal = G4ThreeVector( yOut[0], yOut[1], yOut[2]);
|
||||
// beta2 += beTemp2 ;
|
||||
// beta2 *= 0.5 ;
|
||||
// NormaliseTangentVector( yOut ); // Deleted
|
||||
return ;
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Integrator for RK from G3 with evaluation of error in solution and delta
|
||||
// geometry based on naive similarity with the case of uniform magnetic field.
|
||||
// B1[3] is input and is the first magnetic field values
|
||||
// B2[3] is output and is the final magnetic field values.
|
||||
|
||||
void G4RKG3_Stepper::StepWithEst( const G4double tIn[7],
|
||||
const G4double dydx[7],
|
||||
const G4double Step,
|
||||
G4double tOut[7],
|
||||
G4double& alpha2,
|
||||
G4double& beta2,
|
||||
const G4double B1[3],
|
||||
G4double B2[3]) // const
|
||||
|
||||
{
|
||||
|
||||
G4Exception(" G4ClassicalRK4::StepWithEst ERROR: this Method is no longer used.");
|
||||
|
||||
#if 0
|
||||
// const G4int nvar = 6 ;
|
||||
G4double K1[7],K2[7],K3[7],K4[7] ;
|
||||
G4double tTemp[7], yderiv[6] ;
|
||||
G4double B[3];
|
||||
G4int i ;
|
||||
|
||||
alpha2 = 0 ;
|
||||
beta2 = 0 ;
|
||||
|
||||
// GetEquationOfMotion()->EvaluateRhsReturnB(tIn,dydx,B1) ;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
K1[i] = Step * dydx[i+3];
|
||||
tTemp[i] = tIn[i] + Step*(0.5*tIn[i+3] + 0.125*K1[i]) ;
|
||||
tTemp[i+3] = tIn[i+3] + 0.5*K1[i] ;
|
||||
alpha2 += B1[i]*B1[i] ;
|
||||
beta2 += K1[i]*K1[i] ;
|
||||
}
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(tTemp,yderiv,B) ; // Calculates yderive & returns B too!
|
||||
// GetFieldValue(tTemp,B) ;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
K2[i] = Step * yderiv[i+3];
|
||||
tTemp[i+3] = tIn[i+3] + 0.5*K2[i] ;
|
||||
alpha2 += 2*B[i]*B[i] ;
|
||||
beta2 += K2[i]*K2[i] ;
|
||||
}
|
||||
|
||||
// Given B, calculate yderiv !
|
||||
GetEquationOfMotion()->EvaluateRhsGivenB(tTemp,B,yderiv) ;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
K3[i] = Step * yderiv[i+3];
|
||||
tTemp[i] = tIn[i] + Step*(tIn[i+3] + 0.5*K3[i]) ;
|
||||
tTemp[i+3] = tIn[i+3] + K3[i] ;
|
||||
beta2 += K3[i]*K3[i] ;
|
||||
}
|
||||
|
||||
// Calculates y-deriv(atives) & returns B too!
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(tTemp,yderiv,B2) ;
|
||||
|
||||
G4double drds2 = 0 ;
|
||||
for(i=0;i<3;i++) // Output trajectory vector
|
||||
{
|
||||
K4[i] = Step * yderiv[i+3];
|
||||
tOut[i] = tIn[i] + Step*(tIn[i+3] + (K1[i] + K2[i] + K3[i])/6.0) ;
|
||||
tOut[i+3] = tIn[i+3] + (K1[i] + 2*K2[i] + 2*K3[i] +K4[i])/6.0 ;
|
||||
alpha2 += B2[i]*B2[i] ;
|
||||
beta2 += K4[i]*K4[i] ;
|
||||
// drds2 += tOut[i+3]*tOut[i+3] ;
|
||||
}
|
||||
alpha2 *= sqr(GetEquationOfMotion()->FCof()*Step) * 0.25 ;
|
||||
beta2 *= 0.25 ;
|
||||
|
||||
// drds2 = sqrt(drds2) ;
|
||||
// for(i=0;i<3;i++) {tOut[i+3] /= drds2 ; } // Unit vector along momentum
|
||||
// NormaliseTangentVector( tOut ); // Deleted
|
||||
#endif
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// Integrator RK Stepper from G3 with only two field evaluation per Step.
|
||||
// It is used in propagation initial Step by small substeps after solution
|
||||
// error and delta geometry considerations. B[3] is magnetic field which
|
||||
// is passed from substep to substep.
|
||||
|
||||
void G4RKG3_Stepper::StepNoErr(const G4double tIn[7],
|
||||
const G4double dydx[7],
|
||||
const G4double Step,
|
||||
G4double tOut[7],
|
||||
G4double B[3] ) // const
|
||||
|
||||
{
|
||||
// Copy and edit the routine above, to delete alpha2, beta2, ...
|
||||
G4double K1[7],K2[7],K3[7],K4[7] ;
|
||||
G4double tTemp[7], yderiv[6] ;
|
||||
G4int i ;
|
||||
|
||||
G4Exception(" G4ClassicalRK4::StepNoErr ERROR: this Method should no longer be used.");
|
||||
|
||||
|
||||
#if 0
|
||||
// GetEquationOfMotion()->EvaluateRhsReturnB(tIn,dydx,B1) ;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
K1[i] = Step * dydx[i+3];
|
||||
tTemp[i] = tIn[i] + Step*(0.5*tIn[i+3] + 0.125*K1[i]) ;
|
||||
tTemp[i+3] = tIn[i+3] + 0.5*K1[i] ;
|
||||
}
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(tTemp,yderiv,B) ; // Calculates yderive
|
||||
// & returns B too!
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
K2[i] = Step * yderiv[i+3];
|
||||
tTemp[i+3] = tIn[i+3] + 0.5*K2[i] ;
|
||||
}
|
||||
|
||||
// Given B, calculate yderiv !
|
||||
GetEquationOfMotion()->EvaluateRhsGivenB(tTemp,B,yderiv) ;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
K3[i] = Step * yderiv[i+3];
|
||||
tTemp[i] = tIn[i] + Step*(tIn[i+3] + 0.5*K3[i]) ;
|
||||
tTemp[i+3] = tIn[i+3] + K3[i] ;
|
||||
}
|
||||
|
||||
// Calculates y-deriv(atives) & returns B too!
|
||||
GetEquationOfMotion()->EvaluateRhsReturnB(tTemp,yderiv,B) ;
|
||||
|
||||
G4double drds2 = 0 ;
|
||||
for(i=0;i<3;i++) // Output trajectory vector
|
||||
{
|
||||
K4[i] = Step * yderiv[i+3];
|
||||
tOut[i] = tIn[i] + Step*(tIn[i+3] + (K1[i] + K2[i] + K3[i])/6.0) ;
|
||||
tOut[i+3] = tIn[i+3] + (K1[i] + 2*K2[i] + 2*K3[i] +K4[i])/6.0 ;
|
||||
}
|
||||
// NormaliseTangentVector( tOut );
|
||||
#endif
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
G4double G4RKG3_Stepper::DistChord() const
|
||||
{
|
||||
// Soon: must check whether h/R > 2 pi !!
|
||||
// Method below is good only for < 2 pi
|
||||
|
||||
return G4LineSection::Distline( fyMidPoint, fyInitial, fyFinal );
|
||||
// This is a class method that gives distance of Mid
|
||||
// from the Chord between the Initial and Final points.
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4SimpleHeum.cc,v 2.6 1998/11/17 18:20:11 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
// Simple Heum:
|
||||
// x_1 = x_0 + h *
|
||||
// 1/4 * dx(t0,x0) +
|
||||
// 3/4 * dx(t0+2/3*h, x0+2/3*h*(dx(t0+h/3,x0+h/3*dx(t0,x0))))
|
||||
//
|
||||
// third order solver
|
||||
//
|
||||
// W.Wander <wwc@mit.edu> 12/09/97
|
||||
// 6.11.98. V.Grichine new data member fNumberOfVariables
|
||||
|
||||
|
||||
#include "G4SimpleHeum.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor
|
||||
|
||||
G4SimpleHeum::G4SimpleHeum(G4Mag_EqRhs *EqRhs, G4int num_variables):
|
||||
G4MagErrorStepper(EqRhs, num_variables),
|
||||
fNumberOfVariables(num_variables)
|
||||
{
|
||||
dydxTemp = new G4double[fNumberOfVariables] ;
|
||||
dydxTemp2 = new G4double[fNumberOfVariables] ;
|
||||
yTemp = new G4double[fNumberOfVariables] ;
|
||||
yTemp2 = new G4double[fNumberOfVariables] ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
|
||||
G4SimpleHeum::~G4SimpleHeum()
|
||||
{
|
||||
delete dydxTemp;
|
||||
delete dydxTemp2;
|
||||
delete yTemp;
|
||||
delete yTemp2;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
void
|
||||
G4SimpleHeum::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[])
|
||||
{
|
||||
// const G4int nvar = 6 ;
|
||||
|
||||
G4int i;
|
||||
|
||||
for( i = 0; i < fNumberOfVariables; i++ )
|
||||
{
|
||||
yTemp[i] = yIn[i] + (1.0/3.0) * h * dydx[i] ;
|
||||
}
|
||||
|
||||
RightHandSide(yTemp,dydxTemp);
|
||||
|
||||
for( i = 0; i < fNumberOfVariables; i++ )
|
||||
{
|
||||
yTemp2[i] = yIn[i] + (2.0/3.0) * h * dydxTemp[i] ;
|
||||
}
|
||||
|
||||
RightHandSide(yTemp2,dydxTemp2);
|
||||
|
||||
for( i = 0; i < fNumberOfVariables; i++ )
|
||||
{
|
||||
yOut[i] = yIn[i] + h * ( 0.25 * dydx[i] +
|
||||
0.75 * dydxTemp2[i]);
|
||||
}
|
||||
|
||||
// NormaliseTangentVector( yOut );
|
||||
|
||||
return ;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4SimpleRunge.cc,v 2.8 1998/11/19 20:54:58 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
// Simple Runge:
|
||||
//
|
||||
// x_1 = x_0 + h * ( dx( t_0+h/2, x_0 + h/2 * dx( t_0, x_0) ) )
|
||||
//
|
||||
// second order solver
|
||||
// take the derivative at a position to be assumed at the middle of the
|
||||
// Step and add it to the current position.
|
||||
//
|
||||
//
|
||||
// W.Wander <wwc@mit.edu> 12/09/97
|
||||
// 6.11.98 V.Grichine new data member fNumberOfVariables
|
||||
//
|
||||
|
||||
|
||||
#include "G4SimpleRunge.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor
|
||||
|
||||
G4SimpleRunge::G4SimpleRunge(G4Mag_EqRhs *EqRhs, G4int numberOfVariables):
|
||||
G4MagErrorStepper(EqRhs, numberOfVariables),
|
||||
fNumberOfVariables(numberOfVariables)
|
||||
{
|
||||
dydxTemp = new G4double[fNumberOfVariables] ;
|
||||
yTemp = new G4double[fNumberOfVariables] ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
|
||||
G4SimpleRunge::~G4SimpleRunge()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
void
|
||||
G4SimpleRunge::DumbStepper( const G4double yIn[],
|
||||
const G4double dydx[],
|
||||
const G4double h,
|
||||
G4double yOut[])
|
||||
{
|
||||
// const G4int nvar = 6 ;
|
||||
G4int i;
|
||||
|
||||
for( i = 0; i < fNumberOfVariables; i++ )
|
||||
{
|
||||
yTemp[i] = yIn[i] + 0.5 * h*dydx[i] ;
|
||||
}
|
||||
|
||||
RightHandSide(yTemp,dydxTemp);
|
||||
|
||||
for( i = 0; i < fNumberOfVariables; i++ )
|
||||
{
|
||||
yOut[i] = yIn[i] + h * ( dydxTemp[i] );
|
||||
}
|
||||
|
||||
// NormaliseTangentVector( yOut );
|
||||
|
||||
return ;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4UniformElectricField.cc,v 2.2 1998/11/19 20:45:22 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
//
|
||||
// Class for creation of uniform Electric Field
|
||||
//
|
||||
// 30.1.97 V.Grichine
|
||||
//
|
||||
#include "G4UniformElectricField.hh"
|
||||
#include "globals.hh"
|
||||
#include "geomdefs.hh"
|
||||
|
||||
G4UniformElectricField::G4UniformElectricField(const G4ThreeVector FieldVector )
|
||||
{
|
||||
fFieldComponents[3] = FieldVector.x();
|
||||
fFieldComponents[4] = FieldVector.y();
|
||||
fFieldComponents[5] = FieldVector.z();
|
||||
}
|
||||
|
||||
G4UniformElectricField::G4UniformElectricField(G4double vField,
|
||||
G4double vTheta,
|
||||
G4double vPhi )
|
||||
{
|
||||
if(vField >= 0 &&
|
||||
vTheta >= 0 && vTheta <= pi &&
|
||||
vPhi >= 0 && vPhi <= twopi)
|
||||
{
|
||||
fFieldComponents[3] = vField*sin(vTheta)*cos(vPhi) ;
|
||||
fFieldComponents[4] = vField*sin(vTheta)*sin(vPhi) ;
|
||||
fFieldComponents[5] = vField*cos(vTheta) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Exception("Invalid parameters in G4UniformElectricField::G4UniformElectricField") ;
|
||||
}
|
||||
}
|
||||
|
||||
G4UniformElectricField::~G4UniformElectricField()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
G4UniformElectricField::G4UniformElectricField (const G4UniformElectricField &p)
|
||||
{
|
||||
for (G4int i=3; i<6; i++)
|
||||
fFieldComponents[i] = p.fFieldComponents[i];
|
||||
}
|
||||
|
||||
G4UniformElectricField& G4UniformElectricField::operator = (const G4UniformElectricField &p)
|
||||
{
|
||||
for (G4int i=3; i<6; i++)
|
||||
fFieldComponents[i] = p.fFieldComponents[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
void G4UniformElectricField::GetFieldValue (const G4double [3],
|
||||
G4double E[3] ) const
|
||||
{
|
||||
E[0]= fFieldComponents[3] ;
|
||||
E[1]= fFieldComponents[4] ;
|
||||
E[2]= fFieldComponents[5] ;
|
||||
return ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 GEANT4 collaboration.
|
||||
//
|
||||
// By copying, distributing or modifying the Program (or any work
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4UniformMagField.cc,v 2.4 1998/11/27 16:15:53 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
//
|
||||
// Class for creation of uniform Magnetic Field
|
||||
//
|
||||
// 30.1.97 V.Grichine
|
||||
//
|
||||
#include "G4UniformMagField.hh"
|
||||
#include "globals.hh"
|
||||
#include "geomdefs.hh"
|
||||
|
||||
G4UniformMagField::G4UniformMagField(const G4ThreeVector& FieldVector )
|
||||
{
|
||||
fFieldComponents[0] = FieldVector.x();
|
||||
fFieldComponents[1] = FieldVector.y();
|
||||
fFieldComponents[2] = FieldVector.z();
|
||||
}
|
||||
|
||||
void
|
||||
G4UniformMagField::SetFieldValue(const G4ThreeVector& newFieldVector )
|
||||
{
|
||||
fFieldComponents[0] = newFieldVector.x();
|
||||
fFieldComponents[1] = newFieldVector.y();
|
||||
fFieldComponents[2] = newFieldVector.z();
|
||||
}
|
||||
|
||||
G4UniformMagField::G4UniformMagField(G4double vField,
|
||||
G4double vTheta,
|
||||
G4double vPhi )
|
||||
{
|
||||
if(vField >= 0 &&
|
||||
vTheta >= 0 && vTheta <= pi &&
|
||||
vPhi >= 0 && vPhi <= twopi)
|
||||
{
|
||||
fFieldComponents[0] = vField*sin(vTheta)*cos(vPhi) ;
|
||||
fFieldComponents[1] = vField*sin(vTheta)*sin(vPhi) ;
|
||||
fFieldComponents[2] = vField*cos(vTheta) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Exception("Invalid parameters in G4UniformMagField::G4UniformMagField") ;
|
||||
}
|
||||
}
|
||||
|
||||
G4UniformMagField::~G4UniformMagField()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
G4UniformMagField::G4UniformMagField (const G4UniformMagField &p)
|
||||
{
|
||||
for (G4int i=0; i<3; i++)
|
||||
fFieldComponents[i] = p.fFieldComponents[i];
|
||||
}
|
||||
|
||||
G4UniformMagField& G4UniformMagField::operator = (const G4UniformMagField &p)
|
||||
{
|
||||
for (G4int i=0; i<3; i++)
|
||||
fFieldComponents[i] = p.fFieldComponents[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
void G4UniformMagField::GetFieldValue (const G4double [3],
|
||||
G4double *B ) const
|
||||
{
|
||||
B[0]= fFieldComponents[0] ;
|
||||
B[1]= fFieldComponents[1] ;
|
||||
B[2]= fFieldComponents[2] ;
|
||||
return ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user