Import Geant4 10.6.0 source tree

This commit is contained in:
Gabriele Cosmo
2019-12-06 15:12:28 +01:00
parent b2a62ae692
commit 5baee230e9
2997 changed files with 141580 additions and 98673 deletions
@@ -0,0 +1,158 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4BFieldIntegrationDriver implementation
//
// Specialized integration driver for pure magnetic field
//
// Author: D.Sorokin
// --------------------------------------------------------------------
#include "G4BFieldIntegrationDriver.hh"
#include "G4FieldTrack.hh"
#include "G4FieldUtils.hh"
#include "G4Exception.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "templates.hh"
namespace {
G4Mag_EqRhs* toMagneticEquation(G4EquationOfMotion* equation)
{
auto e = dynamic_cast<G4Mag_EqRhs*>(equation);
if (!e)
{
G4Exception("G4BFieldIntegrationDriver::G4BFieldIntegrationDriver",
"GeomField0003", FatalErrorInArgument,
"Works only with G4Mag_EqRhs");
}
return e;
}
} // namespace
G4BFieldIntegrationDriver::G4BFieldIntegrationDriver(
std::unique_ptr<G4VIntegrationDriver> smallStepDriver,
std::unique_ptr<G4VIntegrationDriver> largeStepDriver)
: fSmallStepDriver(std::move(smallStepDriver)),
fLargeStepDriver(std::move(largeStepDriver)),
fCurrDriver(fSmallStepDriver.get()),
fEquation(toMagneticEquation(fCurrDriver->GetEquationOfMotion()))
{
if (fSmallStepDriver->GetEquationOfMotion()
!= fLargeStepDriver->GetEquationOfMotion())
{
G4Exception("G4BFieldIntegrationDriver Constructor:",
"GeomField1001", FatalException, "different EoM");
}
}
G4double G4BFieldIntegrationDriver::AdvanceChordLimited(G4FieldTrack& yCurrent,
G4double stepMax,
G4double epsStep,
G4double chordDistance)
{
const G4double radius = CurvatureRadius(yCurrent);
G4VIntegrationDriver* driver = nullptr;
if (chordDistance < 2 * radius)
{
stepMax = std::min(stepMax, twopi * radius);
driver = fSmallStepDriver.get();
++fSmallDriverSteps;
} else
{
driver = fLargeStepDriver.get();
++fLargeDriverSteps;
}
if (driver != fCurrDriver)
{
driver->OnComputeStep();
}
fCurrDriver = driver;
return fCurrDriver->AdvanceChordLimited(yCurrent, stepMax,
epsStep, chordDistance);
}
void
G4BFieldIntegrationDriver::SetEquationOfMotion(G4EquationOfMotion* equation)
{
fEquation = toMagneticEquation(equation);
fSmallStepDriver->SetEquationOfMotion(equation);
fLargeStepDriver->SetEquationOfMotion(equation);
}
G4double
G4BFieldIntegrationDriver::CurvatureRadius(const G4FieldTrack& track) const
{
G4double field[G4Field::MAX_NUMBER_OF_COMPONENTS];
GetFieldValue(track, field);
const G4double Bmag2 = field[0] * field[0]
+ field[1] * field[1]
+ field[2] * field[2] ;
if (Bmag2 == 0.0 )
{
return DBL_MAX;
}
const G4double momentum2 = track.GetMomentum().mag2();
const G4double fCof_inv = eplus / std::abs(fEquation->FCof());
return std::sqrt(momentum2 / Bmag2) * fCof_inv;
}
void
G4BFieldIntegrationDriver::GetFieldValue(const G4FieldTrack& track,
G4double Field[] ) const
{
G4ThreeVector pos= track.GetPosition();
G4double positionTime[4]= { pos.x(), pos.y(), pos.z(),
track.GetLabTimeOfFlight() } ;
fEquation->GetFieldValue(positionTime, Field);
}
void G4BFieldIntegrationDriver::PrintStatistics() const
{
const auto totSteps = fSmallDriverSteps + fLargeDriverSteps;
const auto toFraction = [&](double value) { return value / totSteps * 100; };
G4cout << "============= G4BFieldIntegrationDriver statistics ===========\n"
<< "total steps " << totSteps << " "
<< "smallDriverSteps " << toFraction(fSmallDriverSteps) << " "
<< "largeDriverSteps " << toFraction(fLargeDriverSteps) << "\n"
<< "======================================\n";
}
@@ -23,41 +23,28 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Bogacki-Shampine - 4 - 3(2) non-FSAL implementation by Somnath Banerjee
// Supervision / code review: John Apostolakis
// G4BogackiShampine23 implementation
//
// Somnath's work was sponsored by Google as part of the Google Summer of
// Code 2015, as part of the CERN / SFT organisation.p
// ===================================================================
// Bogacki-Shampine - 4 - 3(2) non-FSAL implementation
//
// Implementation of the method proposed in the publication
// A 3(2) pair of Runge - Kutta formulas,”
// by P. Bogacki and L. F. Shampine,
// Appl. Math. Lett., vol. 2, no. 4, pp. 321325, Jan. 1989.
// "A 3(2) pair of Runge - Kutta formulas"
// by P. Bogacki and L. F. Shampine,
// Appl. Math. Lett., vol. 2, no. 4, pp. 321-325, Jan. 1989.
//
// First version: 20 May 2015
// The Bogacki shampine method has the following Butcher's tableau
//
// History
// -----------------------------
// Created by Somnath Banerjee on 20 May 2015
///////////////////////////////////////////////////////////////////////////////
/*
This contains the stepper function of the G4BogackiShampine23 class
The Bogacki shampine method has the following Butcher's tableau
0 |
1/2|1/2
3/4|0 3/4
1 |2/9 1/3 4/9
-------------------
|2/9 1/3 4/9 0
|7/24 1/4 1/3 1/8
*/
// 0 |
// 1/2|1/2
// 3/4|0 3/4
// 1 |2/9 1/3 4/9
// -------------------
// |2/9 1/3 4/9 0
// |7/24 1/4 1/3 1/8
//
// Created: Somnath Banerjee, Google Summer of Code 2015, 20 May 2015
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4BogackiShampine23.hh"
#include "G4LineSection.hh"
@@ -66,10 +53,9 @@ The Bogacki shampine method has the following Butcher's tableau
using namespace field_utils;
G4BogackiShampine23::G4BogackiShampine23(G4EquationOfMotion* EqRhs,
G4int integrationVariables):
G4MagIntegratorStepper(EqRhs, integrationVariables)
G4int integrationVariables)
: G4MagIntegratorStepper(EqRhs, integrationVariables)
{
SetIntegrationOrder(3);
SetFSAL(true);
}
@@ -83,38 +69,47 @@ void G4BogackiShampine23::makeStep(const G4double yInput[],
{
G4double yTemp[G4FieldTrack::ncompSVEC];
for(G4int i = GetNumberOfVariables(); i < GetNumberOfStateVariables(); ++i)
for(G4int i = GetNumberOfVariables(); i < GetNumberOfStateVariables(); ++i)
{
yOutput[i] = yTemp[i] = yInput[i];
}
G4double ak2[G4FieldTrack::ncompSVEC],
ak3[G4FieldTrack::ncompSVEC];
const G4double b21 = 0.5 ,
b31 = 0., b32 = 3.0 / 4.0,
b41 = 2.0 / 9.0, b42 = 1.0 / 3.0, b43 = 4.0 / 9.0;
const G4double b21 = 0.5 ,
b31 = 0., b32 = 3.0 / 4.0,
b41 = 2.0 / 9.0, b42 = 1.0 / 3.0, b43 = 4.0 / 9.0;
const G4double dc1 = b41 - 7.0 / 24.0, dc2 = b42 - 1.0 / 4.0,
dc3 = b43 - 1.0 / 3.0, dc4 = - 1.0 / 8.0;
const G4double dc1 = b41 - 7.0 / 24.0, dc2 = b42 - 1.0 / 4.0,
dc3 = b43 - 1.0 / 3.0, dc4 = - 1.0 / 8.0;
// RightHandSide(yInput, dydx);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + b21 * hstep * dydx[i];
// RightHandSide(yInput, dydx);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
{
yTemp[i] = yInput[i] + b21 * hstep * dydx[i];
}
RightHandSide(yTemp, ak2);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b31 * dydx[i] + b32 * ak2[i]);
RightHandSide(yTemp, ak2);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
{
yTemp[i] = yInput[i] + hstep * (b31 * dydx[i] + b32 * ak2[i]);
}
RightHandSide(yTemp, ak3);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yOutput[i] = yInput[i] + hstep * (b41 * dydx[i] + b42 * ak2[i] + b43 * ak3[i]);
RightHandSide(yTemp, ak3);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
{
yOutput[i] = yInput[i] + hstep * (b41*dydx[i] + b42*ak2[i] + b43*ak3[i]);
}
if (dydxOutput && yError) {
RightHandSide(yOutput, dydxOutput);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yError[i] = hstep * (dc1 * dydx[i] + dc2 * ak2[i] +
dc3 * ak3[i] + dc4 * dydxOutput[i]);
if (dydxOutput && yError)
{
RightHandSide(yOutput, dydxOutput);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
{
yError[i] = hstep * (dc1 * dydx[i] + dc2 * ak2[i] +
dc3 * ak3[i] + dc4 * dydxOutput[i]);
}
}
}
@@ -23,29 +23,17 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Bogacki-Shampine's RK 5(4) non-FSAL implementation by Somnath Banerjee
// Supervision / code review: John Apostolakis
// G4BogackiShampine45 implementation
//
// Somnath's work was sponsored by Google as part of the Google Summer of
// Code 2015, as part of the CERN / SFT organisation.p
//
// First version: 25 May 2015
//
// History
// -----------------------------
// Created by Somnath Banerjee on May-August 2015
// Improvements by John Apostolakis, May 2016
///////////////////////////////////////////////////////////////////////////////
//
// This is the source file of G4BogackiShampine45 class containing the
// definition of the stepper() method that evaluates one step in
// Bogacki-Shampine's RK 5(4) non-FSAL interpolation method
// Definition of the stepper() method that evaluates one step in
// field propagation.
//
// The Butcher table of the Bogacki-Shampine-8-4-5 method is:
//
// 0 |
// 1/6 | 1/6
// 2/9 | 2/27 4/27
// 2/9 | 2/27 4/27
// 3/7 | 183/1372 -162/343 1053/1372
// 2/3 | 68/297 -4/11 42/143 1960/3861
// 3/4 | 597/22528 81/352 63099/585728 58653/366080 4617/20480
@@ -55,39 +43,40 @@
// 587/8064 0 4440339/15491840 24353/124800 387/44800 2152/5985 7267/94080 0
// 2479/34992 0 123/416 612941/3411720 43/1440 2272/6561 79937/1113912 3293/556956
//
// Do NOT re-indent the lines above - their meaning becomes lost
// ********************************
// Coefficients have been obtained from rksuite.f : http://www.netlib.org/ode/rksuite/
// Note on meaning of label "non-FSAL version":
// This method calculates the deriviative dy/dx at the endpoint of the integration interval at each step.
// as part of its evaluation of the endpoint and its error.
// So this value is available to be returned, for re-use in case of a successful step.
// ( This is done in a 'later' version using a refined interface. )
// Coefficients have been obtained from:
// http://www.netlib.org/ode/rksuite/
//
// Note on meaning of label "non-FSAL version":
// This method calculates the deriviative dy/dx at the endpoint of the
// integration interval at each step, as part of its evaluation of the
// endpoint and its error. So this value is available to be returned,
// for re-use in case of a successful step.
// (This is done in a 'later' version using a refined interface).
//
// Created: Somnath Banerjee, Google Summer of Code 2015, May-August 2015
// Revision: John Apostolakis, CERN, May 2016
// --------------------------------------------------------------------
#include <cassert>
#include "G4BogackiShampine45.hh"
#include "G4LineSection.hh"
G4bool G4BogackiShampine45::fPreparedConstants= false;
G4bool G4BogackiShampine45::fPreparedConstants = false;
G4double G4BogackiShampine45::bi[12][7];
//Constructor
// Constructor
//
G4BogackiShampine45::G4BogackiShampine45(G4EquationOfMotion *EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables),
fLastStepLength(-1.0),
fAuxStepper(nullptr),
fPreparedInterpolation(false)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables)
{
const G4int numberOfVariables = noIntegrationVariables;
//New Chunk of memory being created for use by the stepper
// New Chunk of memory being created for use by the stepper
//aki - for storing intermediate RHS
// aki - for storing intermediate RHS
ak2 = new G4double[numberOfVariables];
ak3 = new G4double[numberOfVariables];
ak4 = new G4double[numberOfVariables];
@@ -99,8 +88,9 @@ G4BogackiShampine45::G4BogackiShampine45(G4EquationOfMotion *EqRhs,
ak10 = new G4double[numberOfVariables];
ak11 = new G4double[numberOfVariables];
for (int i = 0; i < 6; i++) {
p[i]= new G4double[numberOfVariables];
for (auto i = 0; i < 6; ++i)
{
p[i]= new G4double[numberOfVariables];
}
assert ( GetNumberOfStateVariables() >= 8 );
@@ -115,11 +105,13 @@ G4BogackiShampine45::G4BogackiShampine45(G4EquationOfMotion *EqRhs,
fLastFinalVector = new G4double[numStateVars] ;
fLastDyDx = new G4double[numberOfVariables]; // Only derivatives
fMidVector = new G4double[numberOfVariables]; // new G4double[numStateVars];
fMidError = new G4double[numberOfVariables]; // new G4double[numStateVars];
fMidVector = new G4double[numberOfVariables];
fMidError = new G4double[numberOfVariables];
if( ! fPreparedConstants )
{
PrepareConstants();
}
if( primary )
{
@@ -127,56 +119,55 @@ G4BogackiShampine45::G4BogackiShampine45(G4EquationOfMotion *EqRhs,
}
}
// Destructor
//
G4BogackiShampine45::~G4BogackiShampine45()
{
// Clear all previously allocated memory for stepper and DistChord
//
delete [] ak2;
delete [] ak3;
delete [] ak4;
delete [] ak5;
delete [] ak6;
delete [] ak7;
delete [] ak8;
delete [] ak9;
delete [] ak10;
delete [] ak11;
//Destructor
G4BogackiShampine45::~G4BogackiShampine45(){
//clear all previously allocated memory for stepper and DistChord
delete[] ak2;
delete[] ak3;
delete[] ak4;
delete[] ak5;
delete[] ak6;
delete[] ak7;
delete[] ak8;
delete[] ak9;
delete[] ak10;
delete[] ak11;
for (int i = 0; i < 6; i++) {
delete[] p[i];
for (auto i = 0; i < 6; ++i)
{
delete [] p[i];
}
delete[] yTemp;
delete[] yIn;
delete [] yTemp;
delete [] yIn;
delete[] fLastInitialVector;
delete[] fLastFinalVector;
delete[] fLastDyDx;
delete[] fMidVector;
delete[] fMidError;
delete [] fLastInitialVector;
delete [] fLastFinalVector;
delete [] fLastDyDx;
delete [] fMidVector;
delete [] fMidError;
delete fAuxStepper;
}
// G4double* G4BogackiShampine45::getLastDydx(){
// return ak8;
// }
void
G4BogackiShampine45::GetLastDydx( G4double dyDxLast[] )
void G4BogackiShampine45::GetLastDydx( G4double dyDxLast[] )
{
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
for(G4int i=0; i < numberOfVariables; i++ ){
for(G4int i=0; i < numberOfVariables; ++i )
{
dyDxLast[i] = ak9[i];
}
}
//Stepper :
// Stepper
//
// Passing in the value of yInput[],the first time dydx[] and Step length
// Giving back yOut and yErr arrays for output and error respectively
//
void G4BogackiShampine45::Stepper( const G4double yInput[],
const G4double DyDx[],
G4double Step,
@@ -186,6 +177,7 @@ void G4BogackiShampine45::Stepper( const G4double yInput[],
G4int i;
// Constants from the Butcher tableu
//
const G4double
b21 = 1.0/6.0 ,
b31 = 2.0/27.0 , b32 = 4.0/27.0,
@@ -221,6 +213,7 @@ void G4BogackiShampine45::Stepper( const G4double yInput[],
// taken and is used directly later (instead of defining the last row
// of Butcher table in separate constants and taking the
// difference)
//
const G4double
dc1 = b81 - 2479.0 / 34992.0 ,
dc2 = 0.0,
@@ -231,73 +224,76 @@ void G4BogackiShampine45::Stepper( const G4double yInput[],
dc7 = b87 - 79937.0 / 1113912.0,
dc8 = - 3293.0 / 556956.0;
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
// The number of variables to be integrated over
//
yOut[7] = yTemp[7] = yIn[7] = yInput[7];
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<numberOfVariables;i++)
// Saving yInput because yInput and yOut can be aliases for same array
//
for(i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
}
// RightHandSide(yIn, dydx) ;
// 1st Step - Not doing, getting passed
for(i=0;i<numberOfVariables;i++)
//
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + b21*Step*DyDx[i] ;
}
RightHandSide(yTemp, ak2) ; // 2nd Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b31*DyDx[i] + b32*ak2[i]) ;
}
RightHandSide(yTemp, ak3) ; // 3rd Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b41*DyDx[i] + b42*ak2[i] + b43*ak3[i]) ;
}
RightHandSide(yTemp, ak4) ; // 4th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b51*DyDx[i] + b52*ak2[i] + b53*ak3[i] +
b54*ak4[i]) ;
}
RightHandSide(yTemp, ak5) ; // 5th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b61*DyDx[i] + b62*ak2[i] + b63*ak3[i] +
b64*ak4[i] + b65*ak5[i]) ;
}
RightHandSide(yTemp, ak6) ; // 6th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b71*DyDx[i] + b72*ak2[i] + b73*ak3[i] +
b74*ak4[i] + b75*ak5[i] + b76*ak6[i]);
}
RightHandSide(yTemp, ak7); //7th Step
RightHandSide(yTemp, ak7); // 7th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*(b81*DyDx[i] + b82*ak2[i] + b83*ak3[i] +
b84*ak4[i] + b85*ak5[i] + b86*ak6[i] +
b87*ak7[i]);
}
RightHandSide(yOut, ak8); //8th Step - Final one Using FSAL
RightHandSide(yOut, ak8); // 8th Step - Final one Using FSAL
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yErr[i] = Step*(dc1*DyDx[i] + dc2*ak2[i] + dc3*ak3[i] + dc4*ak4[i] +
dc5*ak5[i] + dc6*ak6[i] + dc7*ak7[i] + dc8*ak8[i]) ;
// Store Input and Final values, for possible use in calculating chord
//
fLastInitialVector[i] = yIn[i] ;
fLastFinalVector[i] = yOut[i];
fLastDyDx[i] = DyDx[i];
@@ -309,48 +305,51 @@ void G4BogackiShampine45::Stepper( const G4double yInput[],
return ;
}
//The following has not been tested
//The DistChord() function fot the class - must define it here.
G4double G4BogackiShampine45::DistChord() const
// DistChord
//
G4double G4BogackiShampine45::DistChord() const
{
G4double distLine, distChord;
G4ThreeVector initialPoint, finalPoint, midPoint;
// Store last initial and final points (they will be overwritten in self-Stepper call!)
initialPoint = G4ThreeVector( fLastInitialVector[0],
// Store last initial and final points
// (they will be overwritten in self-Stepper call!)
//
initialPoint = G4ThreeVector(fLastInitialVector[0],
fLastInitialVector[1], fLastInitialVector[2]);
finalPoint = G4ThreeVector( fLastFinalVector[0],
finalPoint = G4ThreeVector(fLastFinalVector[0],
fLastFinalVector[1], fLastFinalVector[2]);
#if 1
// Old method -- Do half a step using StepNoErr
fAuxStepper->Stepper( fLastInitialVector, fLastDyDx, 0.5 * fLastStepLength,
fMidVector, fMidError);
//
fAuxStepper->Stepper( fLastInitialVector, fLastDyDx, 0.5*fLastStepLength,
fMidVector, fMidError);
#else
// New method -- Using interpolation, requires only 3 extra stages (ie 3 extra field evaluations )
// New method -- Using interpolation,
// requires only 3 extra stages (ie 3 extra field evaluations )
// Use Interpolation, instead of auxiliary stepper to evaluate midpoint
if( ! fPreparedInterpolation ) {
G4BogackiShampine45 *cThis= const_cast<G4BogackiShampine45 *>(this);
cThis-> SetupInterpolationHigh(); // ( fLastInitialVector, fLastDyDx, fLastStepLength );
//
if( ! fPreparedInterpolation )
{
G4BogackiShampine45* cThis = const_cast<G4BogackiShampine45 *>(this);
cThis-> SetupInterpolationHigh();
}
//For calculating the output at the tau fraction of Step
// For calculating the output at the tau fraction of Step
//
G4double tau = 0.5;
// cThis->InterpolateHigh( /* fLastInitialVector, fLastDyDx, fLastStepLength, */, fMidVector, tau);
// Old arguments: ( /*yInput, dydx, step,*/ yOut, tau );
this->InterpolateHigh( tau, fMidVector );
InterpolateHigh( tau, fMidVector );
#endif
midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2]);
// Use stored values of Initial and Endpoint + new Midpoint to evaluate
// distance of Chord
// distance of Chord
if (initialPoint != finalPoint)
{
distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
distLine = G4LineSection::Distline( midPoint,initialPoint,finalPoint );
distChord = distLine;
}
else
@@ -361,9 +360,9 @@ G4double G4BogackiShampine45::DistChord() const
}
void G4BogackiShampine45::SetupInterpolationHigh()
// ( const G4double *yInput, const G4double *dydx, const G4double Step)
{
//Coefficients for the additional stages :
// Coefficients for the additional stages
//
const G4double
a91 = 455.0/6144.0 ,
a92 = 0.0 ,
@@ -396,46 +395,50 @@ void G4BogackiShampine45::SetupInterpolationHigh()
a1110 = -1403317093.0/11371610250.0 ;
const G4int numberOfVariables= this->GetNumberOfVariables();
// const G4double *yIn= fLastInitialVector;
const G4double *dydx= fLastDyDx;
const G4double* dydx= fLastDyDx;
const G4double Step = fLastStepLength;
yTemp[7] = yIn[7];
//Evaluate the extra stages :
for(int i=0; i<numberOfVariables; i++){
// Evaluate the extra stages
//
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(a91*dydx[i] + a92*ak2[i] + a93*ak3[i] +
a94*ak4[i] + a95*ak5[i] + a96*ak6[i] +
a97*ak7[i] + a98*ak8[i] );
}
RightHandSide(yTemp, ak9); //9th stage
RightHandSide(yTemp, ak9); // 9th stage
for(int i=0; i<numberOfVariables; i++){
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(a101*dydx[i] + a102*ak2[i] + a103*ak3[i] +
a104*ak4[i] + a105*ak5[i] + a106*ak6[i] +
a107*ak7[i] + a108*ak8[i] + a109*ak9[i] );
}
RightHandSide(yTemp, ak10); //10th stage
RightHandSide(yTemp, ak10); // 10th stage
for(int i=0; i<numberOfVariables; i++){
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(a111*dydx[i] + a112*ak2[i] + a113*ak3[i] +
a114*ak4[i] + a115*ak5[i] + a116*ak6[i] +
a117*ak7[i] + a118*ak8[i] + a119*ak9[i] +
a1110*ak10[i] );
}
RightHandSide(yTemp, ak11); //11th stage
RightHandSide(yTemp, ak11); // 11th stage
// In future we can restrict the number of variables interpolated
int nwant = numberOfVariables;
//
G4int nwant = numberOfVariables;
// Form the coefficients of the interpolating polynomial in its shifted
// and scaled form. The terms are grouped to minimize the errors
// of the transformation, to cope with ill-conditioning. ( From RKSUITE )
//
for (int l = 0; l < nwant; l++) {
// Form the coefficients of the interpolating polynomial in its shifted
// and scaled form. The terms are grouped to minimize the errors
// of the transformation, to cope with ill-conditioning. ( From RKSUITE )
//
for (G4int l = 0; l < nwant; ++l)
{
// Coefficient of tau^6
p[5][l] = bi[5][6]*ak5[l] +
((bi[10][6]*ak10[l] + bi[8][6]*ak8[l]) +
@@ -467,25 +470,31 @@ void G4BogackiShampine45::SetupInterpolationHigh()
bi[10][2]*ak10[l])+ ((bi[4][2]*ak4[l] +
bi[11][2]*ak2[l]) + bi[7][2]*ak7[l]);
}
//
// Scale all the coefficients by the step size.
//
for (int i = 0; i < 6; i++) {
for (int l = 0; l < nwant; l++) {
// Scale all the coefficients by the step size.
//
for (G4int i = 0; i < 6; ++i)
{
for (G4int l = 0; l < nwant; ++l)
{
p[i][l] *= Step;
}
}
fPreparedInterpolation= true;
fPreparedInterpolation = true;
}
void G4BogackiShampine45::PrepareConstants()
{
for(int i=1; i<= 11; i++)
for(auto i=1; i<= 11; ++i)
{
bi[i][1] = 0.0 ;
}
for(int i=1; i<=6; i++)
for(auto i=1; i<=6; ++i)
{
bi[2][i] = 0.0 ;
}
bi[1][6] = -12134338393.0 / 1050809760.0 ,
bi[1][5] = -1620741229.0 / 50038560.0 ,
@@ -547,61 +556,68 @@ void G4BogackiShampine45::PrepareConstants()
bi[11][4] = 117.0 ,
bi[11][3] = 59.0 ,
bi[11][2] = 12.0 ;
fPreparedConstants= true;
fPreparedConstants = true;
}
void G4BogackiShampine45::InterpolateHigh(G4double tau, G4double *yOut) const
// ( const G4double *yInput, const G4double *dydx, const G4double Step, G4double *yOut, G4double tau)
void G4BogackiShampine45::InterpolateHigh(G4double tau, G4double* yOut) const
{
G4int numberOfVariables = this->GetNumberOfVariables();
assert( fPreparedConstants);
G4int numberOfVariables = GetNumberOfVariables();
G4Exception("G4BogackiShampine45::InterpolateHigh()", "GeomField0001",
FatalException, "Method is not yet validated.");
FatalException, "Method is not yet validated.");
// const G4double *yIn= fLastInitialVector;
// const G4double *dydx= fLastDyDx;
const G4double Step = fLastStepLength;
// for(G4int i = 0; i< numberOfVariables; i++) yIn[i] = yInput[i];
#if 1
G4int nwant = numberOfVariables;
const G4int norder= 6;
G4int l, k;
for (l = 0; l < nwant; l++) {
for (l = 0; l < nwant; ++l)
{
yOut[l] = p[norder-1][l] * tau;
}
for (k = norder - 2; k >= 1; k--) {
for (l = 0; l < nwant; l++) {
for (k = norder - 2; k >= 1; --k)
{
for (l = 0; l < nwant; ++l)
{
yOut[l] = ( yOut[l] + p[k][l] ) * tau;
}
}
for (l = 0; l < nwant; l++) {
for (l = 0; l < nwant; ++l)
{
yOut[l] = ( yOut[l] + Step * ak8[l] ) * tau + yIn[l];
}
// The derivative at the end-point is nextDydx[i] = ak8[i];
#else
// The scheme tries to do the same as the DormandPrince745 routine, but fails
// The scheme tries to do the same as the DormandPrince745 routine,
// but fails
G4double b[12];
const G4double *dydx= fLastDyDx;
const G4double* dydx = fLastDyDx;
G4double tau0 = tau;
for(int iStage=1; iStage<=11; iStage++){ // iStage = stage number
for(G4int iStage=1; iStage<=11; ++iStage) // iStage = stage number
{
b[iStage] = 0.0;
tau = tau0;
for(int j=6; j>=1; j--){ // j reversed
for(G4int j=6; j>=1; --j) // j reversed
{
b[iStage] += bi[iStage][j] * tau;
tau *= tau0;
}
}
for(int i=0; i<numberOfVariables; i++){
yOut[i] = yIn[i] + Step*(b[1] * dydx[i] + b[2] * ak2[i] + b[3] * ak3[i] +
b[4] * ak4[i] + b[5] * ak5[i] + b[6] * ak6[i] +
b[7] * ak7[i] + b[8] * ak8[i] + b[9] * ak9[i] +
b[10] * ak10[i] + b[11] * ak11[i] );
for(G4int i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*(b[1]*dydx[i] + b[2]*ak2[i] + b[3]*ak3[i] +
b[4]*ak4[i] + b[5]*ak5[i] + b[6]*ak6[i] +
b[7]*ak7[i] + b[8]*ak8[i] + b[9]*ak9[i] +
b[10]*ak10[i] + b[11]*ak11[i] );
}
#endif
}
@@ -22,14 +22,11 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// G4BulirschStoer class implementation
// Based on bulirsch_stoer.hpp from boost
//
// Author: Dmitry Sorokin - GSoC 2016
//
///////////////////////////////////////////////////////////////////////////////
// Author: Dmitry Sorokin, Google Summer of Code 2016
// --------------------------------------------------------------------
#include "G4BulirschStoer.hh"
@@ -23,29 +23,25 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4CachedMagneticField implementation
//
//
// Author: J.Apostolakis, 20 July 2009.
// --------------------------------------------------------------------
#include "G4CachedMagneticField.hh"
G4CachedMagneticField::G4CachedMagneticField(G4MagneticField *pMagField,
G4double distance)
: G4MagneticField(),
fLastLocation(DBL_MAX,DBL_MAX,DBL_MAX),
fLastValue(DBL_MAX,DBL_MAX,DBL_MAX),
fCountCalls(0), fCountEvaluations(0)
G4CachedMagneticField::G4CachedMagneticField(G4MagneticField* pMagField,
G4double distance)
: G4MagneticField(), fpMagneticField(pMagField), fDistanceConst(distance),
fLastLocation(DBL_MAX,DBL_MAX,DBL_MAX), fLastValue(DBL_MAX,DBL_MAX,DBL_MAX)
{
fpMagneticField= pMagField;
fDistanceConst= distance;
// G4cout << " Cached-B-Field constructor> Distance = " << distance << G4endl;
this->ClearCounts();
ClearCounts();
}
G4Field* G4CachedMagneticField::Clone() const
{
// Cannot use copy constructor: I need to clone the associated magnetic field
// Cannot use copy constructor: need to clone the associated magnetic field
G4MagneticField* aF = static_cast<G4MagneticField*>(fpMagneticField->Clone());
G4CachedMagneticField* cloned = new G4CachedMagneticField(aF, fDistanceConst);
@@ -62,54 +58,53 @@ void
G4CachedMagneticField::ReportStatistics()
{
G4cout << " Cached field: " << G4endl
<< " Number of calls: " << fCountCalls << G4endl
<< " Number of evaluations : " << fCountEvaluations << G4endl;
<< " Number of calls: " << fCountCalls << G4endl
<< " Number of evaluations : " << fCountEvaluations << G4endl;
}
G4CachedMagneticField::G4CachedMagneticField(const G4CachedMagneticField &rightCMF)
G4CachedMagneticField::
G4CachedMagneticField(const G4CachedMagneticField& rightCMF)
: G4MagneticField(rightCMF)
{
fpMagneticField= rightCMF.fpMagneticField; // NOTE: sharing pointer here!
fDistanceConst = rightCMF.fDistanceConst;
fLastLocation = rightCMF.fLastLocation;
fLastValue = rightCMF.fLastValue;
this->ClearCounts();
ClearCounts();
}
G4CachedMagneticField& G4CachedMagneticField::operator = (const G4CachedMagneticField &p)
G4CachedMagneticField&
G4CachedMagneticField::operator = (const G4CachedMagneticField& p)
{
if (&p == this) return *this;
if (&p == this) { return *this; }
G4MagneticField::operator=(p);
fpMagneticField= p.fpMagneticField; // NOTE: sharing pointer here!
fDistanceConst = p.fDistanceConst;
fLastLocation = p.fLastLocation;
fLastValue = p.fLastValue;
this->ClearCounts();
ClearCounts();
return *this;
}
void
G4CachedMagneticField::GetFieldValue( const G4double Point[4],
G4double *Bfield ) const
G4double* Bfield ) const
{
G4ThreeVector newLocation( Point[0], Point[1], Point[2] );
// G4cout << "Cache-B-field called at " << newLocation << G4endl;
G4double distSq= (newLocation-fLastLocation).mag2();
fCountCalls++;
if( distSq < fDistanceConst*fDistanceConst ) {
++fCountCalls;
if( distSq < fDistanceConst*fDistanceConst )
{
Bfield[0] = fLastValue.x();
Bfield[1] = fLastValue.y();
Bfield[2] = fLastValue.z();
}else{
// G4CachedMagneticField* thisNonC= const_cast<G4CachedMagneticField*>(this);
}
else
{
fpMagneticField->GetFieldValue( Point, Bfield );
// G4cout << " Evaluating. " << G4endl;
fCountEvaluations++;
// thisNonC->
fLastLocation= G4ThreeVector( Point[0], Point[1], Point[2] );
// thisNonC->
fLastValue= G4ThreeVector( Bfield[0], Bfield[1], Bfield[2] );
++fCountEvaluations;
fLastLocation = G4ThreeVector( Point[0], Point[1], Point[2] );
fLastValue = G4ThreeVector( Bfield[0], Bfield[1], Bfield[2] );
}
}
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// G4CashKarpRKF45 implementation
//
// 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.
@@ -32,8 +32,9 @@
// It is used to integrate the equations of the motion of a particle
// in a magnetic field.
//
// [ref. Numerical Recipes in C, 2nd Edition]
// [ref. Numerical Recipes in C, 2nd Edition]
//
// Authors: J.Apostolakis, V.Grichine - 30.01.1997
// -------------------------------------------------------------------
#include "G4CashKarpRKF45.hh"
@@ -42,12 +43,11 @@
/////////////////////////////////////////////////////////////////////
//
// Constructor
//
G4CashKarpRKF45::G4CashKarpRKF45(G4EquationOfMotion *EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables),
fLastStepLength(0.), fAuxStepper(0)
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables)
{
const G4int numberOfVariables =
std::max( noIntegrationVariables,
@@ -85,23 +85,23 @@ G4CashKarpRKF45::G4CashKarpRKF45(G4EquationOfMotion *EqRhs,
/////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4CashKarpRKF45::~G4CashKarpRKF45()
{
delete[] ak2;
delete[] ak3;
delete[] ak4;
delete[] ak5;
delete[] ak6;
// delete[] ak7;
delete[] yTemp;
delete[] yIn;
delete [] ak2;
delete [] ak3;
delete [] ak4;
delete [] ak5;
delete [] ak6;
// delete [] ak7;
delete [] yTemp;
delete [] yIn;
delete[] fLastInitialVector;
delete[] fLastFinalVector;
delete[] fLastDyDx;
delete[] fMidVector;
delete[] fMidError;
delete [] fLastInitialVector;
delete [] fLastFinalVector;
delete [] fLastDyDx;
delete [] fMidVector;
delete [] fMidError;
delete fAuxStepper;
}
@@ -115,7 +115,7 @@ G4CashKarpRKF45::~G4CashKarpRKF45()
// 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[],
@@ -125,100 +125,99 @@ G4CashKarpRKF45::Stepper(const G4double yInput[],
{
// const G4int nvar = 6 ;
// const G4double a2 = 0.2 , a3 = 0.3 , a4 = 0.6 , a5 = 1.0 , a6 = 0.875;
G4int i;
G4int i;
const G4double b21 = 0.2 ,
b31 = 3.0/40.0 , b32 = 9.0/40.0 ,
b41 = 0.3 , b42 = -0.9 , b43 = 1.2 ,
const G4double 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 ,
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 ,
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 ;
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 ;
const G4double dc1 = c1 - 2825.0/27648.0 , dc3 = c3 - 18575.0/48384.0 ,
dc4 = c4 - 13525.0/55296.0 , dc6 = c6 - 0.25 ;
// Initialise time to t0, needed when it is not updated by the integration.
// [ Note: Only for time dependent fields (usually electric)
// is it neccessary to integrate the time.]
yOut[7] = yTemp[7] = yIn[7] = yInput[7];
// Initialise time to t0, needed when it is not updated by the integration.
// [ Note: Only for time dependent fields (usually electric)
// is it neccessary to integrate the time.]
yOut[7] = yTemp[7] = yIn[7] = yInput[7];
const G4int numberOfVariables= this->GetNumberOfVariables();
// The number of variables to be integrated over
const G4int numberOfVariables= this->GetNumberOfVariables();
// The number of variables to be integrated over
// Saving yInput because yInput and yOut can be aliases for same array
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<numberOfVariables;i++)
{
yIn[i]=yInput[i];
}
// RightHandSide(yIn, dydx) ; // 1st Step
for(i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
}
// RightHandSide(yIn, dydx) ; // 1st Step
for(i=0;i<numberOfVariables;i++)
{
yTemp[i] = yIn[i] + b21*Step*dydx[i] ;
}
RightHandSide(yTemp, ak2) ; // 2nd Step
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + b21*Step*dydx[i] ;
}
RightHandSide(yTemp, ak2) ; // 2nd Step
for(i=0;i<numberOfVariables;i++)
{
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b31*dydx[i] + b32*ak2[i]) ;
}
RightHandSide(yTemp, ak3) ; // 3rd Step
}
RightHandSide(yTemp, ak3) ; // 3rd Step
for(i=0;i<numberOfVariables;i++)
{
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b41*dydx[i] + b42*ak2[i] + b43*ak3[i]) ;
}
RightHandSide(yTemp, ak4) ; // 4th Step
}
RightHandSide(yTemp, ak4) ; // 4th Step
for(i=0;i<numberOfVariables;i++)
{
yTemp[i] = yIn[i] + Step*(b51*dydx[i] + b52*ak2[i] + b53*ak3[i] +
b54*ak4[i]) ;
}
RightHandSide(yTemp, ak5) ; // 5th Step
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b51*dydx[i]
+ b52*ak2[i] + b53*ak3[i] + b54*ak4[i]) ;
}
RightHandSide(yTemp, ak5) ; // 5th Step
for(i=0;i<numberOfVariables;i++)
{
yTemp[i] = yIn[i] + Step*(b61*dydx[i] + b62*ak2[i] + b63*ak3[i] +
b64*ak4[i] + b65*ak5[i]) ;
}
RightHandSide(yTemp, ak6) ; // 6th Step
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b61*dydx[i]
+ b62*ak2[i] + b63*ak3[i] + b64*ak4[i] + b65*ak5[i]) ;
}
RightHandSide(yTemp, ak6) ; // 6th Step
for(i=0;i<numberOfVariables;i++)
{
for(i=0; i<numberOfVariables; ++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]) ;
// 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]) ;
// Store Input and Final values, for possible use in calculating chord
//
fLastInitialVector[i] = yIn[i] ;
fLastFinalVector[i] = yOut[i];
fLastDyDx[i] = dydx[i];
}
// NormaliseTangentVector( yOut ); // Not wanted
}
// NormaliseTangentVector( yOut ); // Not wanted
fLastStepLength =Step;
fLastStepLength = Step;
return ;
return;
}
///////////////////////////////////////////////////////////////////////////////
//
void
G4CashKarpRKF45::StepWithEst( const G4double*,
const G4double*,
@@ -235,29 +234,30 @@ G4CashKarpRKF45::StepWithEst( const G4double*,
}
/////////////////////////////////////////////////////////////////
//
G4double G4CashKarpRKF45::DistChord() const
{
G4double distLine, distChord;
G4ThreeVector initialPoint, finalPoint, midPoint;
// Store last initial and final points (they will be overwritten in self-Stepper call!)
// Store last initial and final points
// (they will be overwritten in self-Stepper call!)
//
initialPoint = G4ThreeVector( fLastInitialVector[0],
fLastInitialVector[1], fLastInitialVector[2]);
finalPoint = G4ThreeVector( fLastFinalVector[0],
fLastFinalVector[1], fLastFinalVector[2]);
// Do half a step using StepNoErr
fAuxStepper->Stepper( fLastInitialVector, fLastDyDx, 0.5 * fLastStepLength,
fMidVector, fMidError );
//
fAuxStepper->Stepper( fLastInitialVector, fLastDyDx,
0.5 * fLastStepLength, fMidVector, fMidError );
midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2]);
// Use stored values of Initial and Endpoint + new Midpoint to evaluate
// distance of Chord
// distance of Chord
//
if (initialPoint != finalPoint)
{
distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
@@ -269,5 +269,3 @@ G4double G4CashKarpRKF45::DistChord() const
}
return distChord;
}
@@ -23,13 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ChargeState implementation
//
// History
// - First version: Apr 10, 2013 John Apostolakis, Peter Gumplinger
// - Modified:
//
//
//
// Authors: J.Apostolakis, P.Gumplinger - 10 April 2013
// -------------------------------------------------------------------
#include "G4ChargeState.hh"
@@ -39,8 +35,8 @@ void G4ChargeState::SetChargeSpinMoments(G4double charge,
G4double magnetic_dipole_moment,
G4double electric_dipole_moment,
G4double magnetic_charge )
// Revise the charge and potentially all moments.
// By default do not change mdm, edm, mag charge.
// Revise the charge and potentially all moments.
// By default do not change mdm, edm, mag charge.
{
fCharge = charge;
fSpin = spin;
@@ -23,10 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ChordFinder implementation
//
//
//
// 25.02.97 - John Apostolakis - Design and implementation
// Author: J.Apostolakis - Design and implementation - 25.02.1997
// -------------------------------------------------------------------
#include <iomanip>
@@ -55,21 +54,19 @@
#include "G4InterpolationDriver.hh"
// #include "G4FSALBogackiShampine45.hh"
// #include "G4FSALDormandPrince745.hh"
#include "G4HelixHeum.hh"
#include "G4BFieldIntegrationDriver.hh"
#include <cassert>
// ..........................................................................
G4ChordFinder::G4ChordFinder(G4VIntegrationDriver* pIntegrationDriver)
: fDefaultDeltaChord( 0.25 * mm ), // Parameters
fDeltaChord( fDefaultDeltaChord ), // Internal parameters
fStatsVerbose(0),
fRegularStepperOwned(nullptr), // Dependent objects
fEquation(0)
: fDefaultDeltaChord(0.25 * mm), fIntgrDriver(pIntegrationDriver)
{
// Simple constructor -- it does not create equation
fIntgrDriver= pIntegrationDriver;
fDeltaChord = fDefaultDeltaChord; // Parameters
}
@@ -77,22 +74,20 @@ G4ChordFinder::G4ChordFinder(G4VIntegrationDriver* pIntegrationDriver)
G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
G4double stepMinimum,
G4MagIntegratorStepper* pItsStepper, // nullptr is default
G4bool useFSALstepper ) // false by default
: fDefaultDeltaChord( 0.25 * mm ), // Constants
fDeltaChord( fDefaultDeltaChord ), // Parameters
fStatsVerbose(0),
// fRegularStepperOwned(nullptr), // Dependent objects
fEquation(0)
G4MagIntegratorStepper* pItsStepper,
G4bool useFSALstepper )
: fDefaultDeltaChord(0.25 * mm)
{
// Construct the Chord Finder
// by creating in inverse order the Driver, the Stepper and EqRhs ...
// Construct the Chord Finder
// by creating in inverse order the Driver, the Stepper and EqRhs ...
fDeltaChord = fDefaultDeltaChord; // Parameters
using NewFsalStepperType = G4RK547FEq1; // or 2 or 3
const char* NewFSALStepperName =
"G4RK574FEq1> FSAL 4th/5th order 7-stage 'Equilibrium-type' #1.";
using RegularStepperType =
G4DormandPrince745; // DOPRI5 (MatLab) 5th order embedded method. High efficiency.
G4DormandPrince745; // 5th order embedded method. High efficiency.
// G4ClassicalRK4; // The old default
// G4CashKarpRKF45; // First embedded method in G4
// G4BogackiShampine45; // High efficiency 5th order embedded method
@@ -104,7 +99,7 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
// "Nystrom stepper 4th order";
// Configurable
G4bool forceFSALstepper= false; // Choice - true to enable !!
G4bool forceFSALstepper = false; // Choice - true to enable !!
G4bool recallFSALflag = useFSALstepper;
useFSALstepper = forceFSALstepper || useFSALstepper;
@@ -118,12 +113,11 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
// useHigherStepper = forceHigherEffiencyStepper || useHigherStepper;
G4Mag_EqRhs *pEquation = new G4Mag_UsualEqRhs(theMagField);
G4Mag_EqRhs* pEquation = new G4Mag_UsualEqRhs(theMagField);
fEquation = pEquation;
// G4MagIntegratorStepper* regularStepper = nullptr;
// G4VFSALIntegrationStepper* fsalSepper = nullptr; // for new-type FSAL steppers only
// NewFsalStepperType* fsalStepper = nullptr;
// G4VFSALIntegrationStepper* fsalStepper = nullptr; // for FSAL steppers only
// G4MagIntegratorStepper* oldFSALStepper = nullptr;
G4bool errorInStepperCreation = false;
@@ -138,12 +132,12 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
}
else if ( !useFSALstepper )
{
// RegularStepperType* regularStepper =nullptr; // To check the exception
// RegularStepperType* regularStepper = nullptr; // To check the exception
auto regularStepper = new RegularStepperType(pEquation);
// *** ******************
// *** ******************
//
// Alternative - for G4NystromRK4:
// = new G4NystromRK4(pEquation, 0.1*millimeter ); // *clhep::millimeter );
// = new G4NystromRK4(pEquation, 0.1*mm );
fRegularStepperOwned = regularStepper;
if( regularStepper == nullptr )
@@ -157,12 +151,20 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
}
else
{
fIntgrDriver = new G4IntegrationDriver<RegularStepperType>(
stepMinimum, regularStepper, regularStepper->GetNumberOfVariables());
using SmallStepDriver = G4InterpolationDriver<G4DormandPrince745>;
using LargeStepDriver = G4IntegrationDriver<G4HelixHeum>;
fLongStepper = std::unique_ptr<G4HelixHeum>(new G4HelixHeum(pEquation));
if( fIntgrDriver==nullptr)
fIntgrDriver = new G4BFieldIntegrationDriver(
std::unique_ptr<SmallStepDriver>(new SmallStepDriver(stepMinimum,
regularStepper, regularStepper->GetNumberOfVariables())),
std::unique_ptr<LargeStepDriver>(new LargeStepDriver(stepMinimum,
fLongStepper.get(), regularStepper->GetNumberOfVariables())) );
if( fIntgrDriver == nullptr)
{
message << "Using G4IntegrationDriver with "
message << "Using G4BFieldIntegrationDriver with "
<< RegularStepperName << " type stepper " << G4endl;
message << "Driver instantiation FAILED." << G4endl;
G4Exception("G4ChordFinder::G4ChordFinder()",
@@ -173,7 +175,7 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
else
{
auto fsalStepper= new NewFsalStepperType(pEquation);
// ******************
// *** ******************
fNewFSALStepperOwned = fsalStepper;
if( fsalStepper == nullptr )
@@ -188,12 +190,11 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
else
{
fIntgrDriver = new
G4FSALIntegrationDriver<NewFsalStepperType>(stepMinimum,
fsalStepper,
fsalStepper->GetNumberOfVariables() );
G4FSALIntegrationDriver<NewFsalStepperType>(stepMinimum, fsalStepper,
fsalStepper->GetNumberOfVariables() );
// ==== Create the driver which knows the class type
if( fIntgrDriver==nullptr )
if( fIntgrDriver == nullptr )
{
message << "Using G4FSALIntegrationDriver with stepper type: "
<< NewFSALStepperName << G4endl;
@@ -210,9 +211,10 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
// To test failure to create driver
// delete fIntgrDriver;
// fIntgrDriver= nullptr;
// fIntgrDriver = nullptr;
// Detect and report Error conditions
//
if( errorInStepperCreation || (fIntgrDriver == nullptr ))
{
std::ostringstream errmsg;
@@ -224,24 +226,27 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
}
if (fIntgrDriver == nullptr )
{
errmsg << "ERROR> Failure to create Integration-Driver object." << G4endl
<< " -------------------------------------------" << G4endl;
errmsg << "ERROR> Failure to create Integration-Driver object."
<< G4endl
<< " -------------------------------------------"
<< G4endl;
}
const std::string BoolName[2]= { "False", "True" };
errmsg << " Configuration: (constructor arguments) " << G4endl
<< " provided Stepper = " << pItsStepper << G4endl
<< " use FSAL stepper = " << BoolName[useFSALstepper]
<< " (request = " << BoolName[recallFSALflag]
<< " force FSAL = " << BoolName[forceFSALstepper] << " )" << G4endl;
<< " force FSAL = " << BoolName[forceFSALstepper] << " )"
<< G4endl;
errmsg << message.str();
errmsg << "Aborting.";
G4Exception("G4ChordFinder::G4ChordFinder() - constructor 2",
"GeomField0003", FatalException, errmsg);
}
assert( ( pItsStepper != nullptr )
assert( ( pItsStepper != nullptr )
|| ( fRegularStepperOwned != nullptr )
|| ( fNewFSALStepperOwned != nullptr )
|| ( fNewFSALStepperOwned != nullptr )
);
assert( fIntgrDriver != nullptr );
}
@@ -251,11 +256,11 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
G4ChordFinder::~G4ChordFinder()
{
delete fEquation;
delete fRegularStepperOwned;
delete fNewFSALStepperOwned;
delete fCachedField;
delete fIntgrDriver;
delete fEquation;
delete fRegularStepperOwned;
delete fNewFSALStepperOwned;
delete fCachedField;
delete fIntgrDriver;
}
// ...........................................................................
@@ -267,7 +272,7 @@ G4ChordFinder::ApproxCurvePointS( const G4FieldTrack& CurveA_PointVelocity,
const G4ThreeVector& CurrentE_Point,
const G4ThreeVector& CurrentF_Point,
const G4ThreeVector& PointG,
G4bool first, G4double eps_step)
G4bool first, G4double eps_step)
{
// ApproxCurvePointS is 2nd implementation of ApproxCurvePoint.
// Use Brent Algorithm (or InvParabolic) when possible.
@@ -279,7 +284,7 @@ G4ChordFinder::ApproxCurvePointS( const G4FieldTrack& CurveA_PointVelocity,
// relative accuracy of each Step.
G4FieldTrack EndPoint(CurveA_PointVelocity);
if(!first){EndPoint= ApproxCurveV;}
if(!first) { EndPoint = ApproxCurveV; }
G4ThreeVector Point_A,Point_B;
Point_A=CurveA_PointVelocity.GetPosition();
@@ -308,14 +313,13 @@ G4ChordFinder::ApproxCurvePointS( const G4FieldTrack& CurveA_PointVelocity,
yc=-(Point_B-PointG).mag();
if(xb==0.)
{
EndPoint=
ApproxCurvePointV(CurveA_PointVelocity, CurveB_PointVelocity,
CurrentE_Point, eps_step);
EndPoint = ApproxCurvePointV(CurveA_PointVelocity, CurveB_PointVelocity,
CurrentE_Point, eps_step);
return EndPoint;
}
}
const G4double tolerance= 1.e-12;
const G4double tolerance = 1.e-12;
if(std::abs(ya)<=tolerance||std::abs(yc)<=tolerance)
{
; // What to do for the moment: return the same point as at start
@@ -332,10 +336,10 @@ G4ChordFinder::ApproxCurvePointS( const G4FieldTrack& CurveA_PointVelocity,
}
else
{
test_step=(test_step-xb);
test_step = test_step - xb;
curve=std::abs(EndPoint.GetCurveLength()
-CurveB_PointVelocity.GetCurveLength());
xb=(CurrentF_Point-Point_B).mag();
xb = (CurrentF_Point-Point_B).mag();
}
if(test_step<=0) { test_step=0.1*xb; }
@@ -396,7 +400,7 @@ ApproxCurvePointV( const G4FieldTrack& CurveA_PointVelocity,
curve_length= CurveB_PointVelocity.GetCurveLength()
- CurveA_PointVelocity.GetCurveLength();
G4double integrationInaccuracyLimit= std::max( perMillion, 0.5*eps_step );
G4double integrationInaccuracyLimit= std::max( perMillion, 0.5*eps_step );
if( curve_length < ABdist * (1. - integrationInaccuracyLimit) )
{
#ifdef G4DEBUG_FIELD
@@ -424,7 +428,7 @@ ApproxCurvePointV( const G4FieldTrack& CurveA_PointVelocity,
// curve_length = ABdist;
}
G4double new_st_length;
G4double new_st_length;
if ( ABdist > 0.0 )
{
@@ -460,7 +464,7 @@ ApproxCurvePointV( const G4FieldTrack& CurveA_PointVelocity,
AE_fraction = 0.5; // Default value
}
new_st_length= AE_fraction * curve_length;
new_st_length = AE_fraction * curve_length;
if ( AE_fraction > 0.0 )
{
@@ -478,7 +482,4 @@ ApproxCurvePointV( const G4FieldTrack& CurveA_PointVelocity,
return Current_PointVelocity;
}
// ...........................................................................
@@ -23,8 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ClassicalRK4 implementation
//
//
// Created: J.Apostolakis, V.Grichine - 30.01.1997
// -------------------------------------------------------------------
#include "G4ClassicalRK4.hh"
@@ -33,7 +34,7 @@
//////////////////////////////////////////////////////////////////
//
// Constructor sets the number of variables (default = 6)
//
G4ClassicalRK4::
G4ClassicalRK4(G4EquationOfMotion* EqRhs, G4int numberOfVariables)
: G4MagErrorStepper(EqRhs, numberOfVariables)
@@ -48,12 +49,12 @@ G4ClassicalRK4(G4EquationOfMotion* EqRhs, G4int numberOfVariables)
////////////////////////////////////////////////////////////////
//
// Destructor
//
G4ClassicalRK4::~G4ClassicalRK4()
{
delete[] dydxm;
delete[] dydxt;
delete[] yt;
delete [] dydxm;
delete [] dydxt;
delete [] yt;
}
//////////////////////////////////////////////////////////////////////
@@ -65,16 +66,16 @@ G4ClassicalRK4::~G4ClassicalRK4()
// 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[],
G4double h,
G4double yOut[])
G4ClassicalRK4::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[])
{
const G4int nvar = this->GetNumberOfVariables(); // fNumberOfVariables();
const G4int nvar = GetNumberOfVariables(); // fNumberOfVariables();
G4int i;
G4double hh = h*0.5 , h6 = h/6.0 ;
G4double hh = h*0.5, h6 = h/6.0;
// Initialise time to t0, needed when it is not updated by the integration.
// [ Note: Only for time dependent fields (usually electric)
@@ -82,26 +83,26 @@ G4ClassicalRK4::DumbStepper( const G4double yIn[],
yt[7] = yIn[7];
yOut[7] = yIn[7];
for(i=0;i<nvar;i++)
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++)
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++)
for(i=0; i<nvar; ++i)
{
yt[i] = yIn[i] + h*dydxm[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
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
}
@@ -127,4 +128,3 @@ G4ClassicalRK4::StepWithEst( const G4double*,
FatalException, "Method no longer used.");
} // end of StepWithEst ......................................................
+13 -14
View File
@@ -23,10 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ConstRK4 implementation
//
//
//
// - 18.09.2008 - J.Apostolakis, T.Nikitina - Created
// Created: J.Apostolakis, T.Nikitina - 18.09.2008
// -------------------------------------------------------------------
#include "G4ConstRK4.hh"
@@ -37,7 +36,7 @@
//
// Constructor sets the number of *State* variables (default = 8)
// The number of variables integrated is always 6
//
G4ConstRK4::G4ConstRK4(G4Mag_EqRhs* EqRhs, G4int numStateVariables)
: G4MagErrorStepper(EqRhs, 6, numStateVariables)
{
@@ -87,11 +86,11 @@ G4ConstRK4::~G4ConstRK4()
// array from y. The user supplies the routine RightHandSide(x,y,dydx),
// which returns derivatives dydx at x. The source is routine rk4 from
// NRC p. 712-713 .
void G4ConstRK4::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[])
//
void G4ConstRK4::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[])
{
G4double hh = h*0.5 , h6 = h/6.0 ;
@@ -151,7 +150,7 @@ G4ConstRK4::Stepper( const G4double yInput[],
G4double yError [] )
{
const G4int nvar = 6; // number of variables integrated
const G4int maxvar= GetNumberOfStateVariables();
const G4int maxvar = GetNumberOfStateVariables();
// Correction for Richardson extrapolation
G4double correction = 1. / ( (1 << IntegratorOrder()) -1 );
@@ -159,10 +158,10 @@ G4ConstRK4::Stepper( const G4double yInput[],
G4int i;
// Saving yInput because yInput and yOutput can be aliases for same array
for (i=0; i<maxvar; i++) { yInitial[i]= yInput[i]; }
for (i=0; i<maxvar; ++i) { yInitial[i]= yInput[i]; }
// Must copy the part of the state *not* integrated to the output
for (i=nvar; i<maxvar; i++) { yOutput[i]= yInput[i]; }
for (i=nvar; i<maxvar; ++i) { yOutput[i]= yInput[i]; }
// yInitial[7]= yInput[7]; // The time is typically needed
yMiddle[7] = yInput[7]; // Copy the time from initial value
@@ -186,7 +185,7 @@ G4ConstRK4::Stepper( const G4double yInput[],
// Do a full Step
//
DumbStepper(yInitial, dydx, hstep, yOneStep);
for(i=0;i<nvar;i++)
for(i=0; i<nvar; ++i)
{
yError [i] = yOutput[i] - yOneStep[i] ;
yOutput[i] += yError[i]*correction ;
@@ -208,7 +207,7 @@ G4ConstRK4::Stepper( const G4double yInput[],
// The method below is good only for angle deviations < 2 pi;
// this restriction should not be a problem for the Runge Kutta methods,
// which generally cannot integrate accurately for large angle deviations
//
G4double G4ConstRK4::DistChord() const
{
G4double distLine, distChord;
@@ -23,7 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4DELPHIMagField implementation
//
// Created: V.Grichine - 03.02.1997
// -------------------------------------------------------------------
#include "G4DELPHIMagField.hh"
@@ -34,10 +36,6 @@ G4DELPHIMagField::G4DELPHIMagField()
{
}
G4Field* G4DELPHIMagField::Clone() const
{
return new G4DELPHIMagField;
}
////////////////////////////////////////////////////////////////////////
G4DELPHIMagField::~G4DELPHIMagField()
@@ -46,6 +44,12 @@ G4DELPHIMagField::~G4DELPHIMagField()
///////////////////////////////////////////////////////////////////////
G4Field* G4DELPHIMagField::Clone() const
{
return new G4DELPHIMagField;
}
///////////////////////////////////////////////////////////////////////
void G4DELPHIMagField::GetFieldValue( const G4double yTrack[7],
G4double B[3] ) const
@@ -59,7 +63,8 @@ void G4DELPHIMagField::GetFieldValue( const G4double yTrack[7],
G4double rz = z*std::sqrt(r2), r = std::sqrt(r2+a*a) ;
G4double Br ;
G4double P[8], Q[8] ;
static G4ThreadLocal G4double c[8] = {
static G4ThreadLocal G4double c[8] =
{
-9.26e-5, -3.51e-5, 2.94e-6, -1.10e-6,
6.25e-8, -1.77e-8, -6.88e-10, -7.52e-11
} ;
@@ -85,7 +90,7 @@ void G4DELPHIMagField::GetFieldValue( const G4double yTrack[7],
Br = 0 ;
B[2] = 1.2*tesla ; // the principal Bz value of DELPHI detector
for(i=0;i<n;i++)
for(i=0; i<n; ++i)
{
Br += c[i]*P[i] ;
B[2] += c[i]*Q[i] ;
@@ -23,44 +23,28 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Dormand-Lockyer-McGorrigan-Prince-6-3-4 non-FSAL implementation
// RK4(3)6FD - forced Non-FSAL
// G4DoLoMcPriRK34 implementation
//
// Design/implementation by Somnath Banerjee
// Sponsored by Google in Google Summer of Code 2015.
// Supervision / code review: John Apostolakis
//
// First version: 7 July 2015
//
// G4DoLoMcPriRK34.cc
// Geant4
//
// History
// -----------------------------
// Created by Somnath on 7 July 2015
//
// This is the source file of G4DoLoMcPriRK34 class containing the
// definition of the Stepper() method that evaluates one Step in
// field propagation.
//
// The Butcher table of the Dormand-Lockyer-McGorrigan-Prince-6-3-4 method is as follows :
// [ to be added here ]
// Created: Somnath Banerjee, Google Summer of Code 2015, 7 July 2015
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4DoLoMcPriRK34.hh"
#include "G4LineSection.hh"
// Constructor
G4DoLoMcPriRK34::G4DoLoMcPriRK34(G4EquationOfMotion *EqRhs,
//
G4DoLoMcPriRK34::G4DoLoMcPriRK34(G4EquationOfMotion* EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables),
fLastStepLength( -1.0 ), fAuxStepper( nullptr )
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables)
{
const G4int numberOfVariables = noIntegrationVariables;
//New Chunk of memory being created for use by the Stepper
// New Chunk of memory being created for use by the Stepper
//aki - for storing intermediate RHS
// aki - for storing intermediate RHS
//
ak2 = new G4double[numberOfVariables];
ak3 = new G4double[numberOfVariables];
ak4 = new G4double[numberOfVariables];
@@ -75,150 +59,136 @@ G4DoLoMcPriRK34::G4DoLoMcPriRK34(G4EquationOfMotion *EqRhs,
fLastDyDx = new G4double[numberOfVariables];
fMidVector = new G4double[numberOfVariables];
fMidError = new G4double[numberOfVariables];
fMidError = new G4double[numberOfVariables];
if( primary )
{
fAuxStepper = new G4DoLoMcPriRK34(EqRhs, numberOfVariables,
!primary);
fAuxStepper = new G4DoLoMcPriRK34(EqRhs, numberOfVariables, !primary);
}
}
//Destructor
// Destructor
//
G4DoLoMcPriRK34::~G4DoLoMcPriRK34()
{
//clear all previously allocated memory for Stepper and DistChord
delete[] ak2;
delete[] ak3;
delete[] ak4;
delete[] ak5;
delete[] ak6;
// clear all previously allocated memory for Stepper and DistChord
delete [] ak2;
delete [] ak3;
delete [] ak4;
delete [] ak5;
delete [] ak6;
delete[] yTemp;
delete[] yIn;
delete [] yTemp;
delete [] yIn;
delete[] fLastInitialVector;
delete[] fLastFinalVector;
delete[] fLastDyDx;
delete[] fMidVector;
delete[] fMidError;
delete [] fLastInitialVector;
delete [] fLastFinalVector;
delete [] fLastDyDx;
delete [] fMidVector;
delete [] fMidError;
delete fAuxStepper;
}
//Stepper :
// Stepper
//
// Passing in the value of yInput[],the first time dydx[] and Step length
// Giving back yOut and yErr arrays for output and error respectively
//
void G4DoLoMcPriRK34::Stepper(const G4double yInput[],
const G4double DyDx[],
G4double Step,
G4double yOut[],
G4double yErr[] )
const G4double DyDx[],
G4double Step,
G4double yOut[],
G4double yErr[] )
{
G4int i;
//The various constants defined on the basis of butcher tableu
const G4double //G4double - only once
// The various constants defined on the basis of butcher tableu
//
const G4double b21 = 7.0/27.0 ,
b31 = 7.0/72.0 ,
b32 = 7.0/24.0 ,
b21 = 7.0/27.0 ,
b41 = 3043.0/3528.0 ,
b42 = -3757.0/1176.0 ,
b43 = 1445.0/441.0,
b51 = 17617.0/11662.0 ,
b52 = -4023.0/686.0 ,
b53 = 9372.0/1715.0 ,
b54 = -66.0/595.0 ,
b61 = 29.0/238.0 ,
b62 = 0.0 ,
b63 = 216.0/385.0 ,
b64 = 54.0/85.0 ,
b65 = -7.0/22.0 ,
b31 = 7.0/72.0 ,
b32 = 7.0/24.0 ,
b41 = 3043.0/3528.0 ,
b42 = -3757.0/1176.0 ,
b43 = 1445.0/441.0,
b51 = 17617.0/11662.0 ,
b52 = -4023.0/686.0 ,
b53 = 9372.0/1715.0 ,
b54 = -66.0/595.0 ,
b61 = 29.0/238.0 ,
b62 = 0.0 ,
b63 = 216.0/385.0 ,
b64 = 54.0/85.0 ,
b65 = -7.0/22.0 ,
dc1 = 363.0/2975.0 - b61 ,
dc2 = 0.0 - b62 ,
dc3 = 981.0/1750.0 - b63,
dc4 = 2709.0/4250.0 - b64 ,
dc5 = -3.0/10.0 - b65 ,
dc6 = -1.0/50.0 ; // end of declaration
dc1 = 363.0/2975.0 - b61 ,
dc2 = 0.0 - b62 ,
dc3 = 981.0/1750.0 - b63,
dc4 = 2709.0/4250.0 - b64 ,
dc5 = -3.0/10.0 - b65 ,
dc6 = -1.0/50.0 ; //end of declaration
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
// The number of variables to be integrated over
//
yOut[7] = yTemp[7] = yIn[7];
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<numberOfVariables;i++)
// Saving yInput because yInput and yOut can be aliases for same array
//
for(i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
}
// RightHandSide(yIn, DyDx) ; // 1st stage - Not doing, getting passed
// RightHandSide(yIn, DyDx) ;
// 1st stage - Not doing, getting passed
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + b21*Step*DyDx[i] ;
}
RightHandSide(yTemp, ak2) ; // 2nd stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b31*DyDx[i] + b32*ak2[i]) ;
}
RightHandSide(yTemp, ak3) ; // 3rd stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b41*DyDx[i] + b42*ak2[i] + b43*ak3[i]) ;
}
RightHandSide(yTemp, ak4) ; // 4th stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b51*DyDx[i] + b52*ak2[i] + b53*ak3[i] +
b54*ak4[i]) ;
yTemp[i] = yIn[i] + Step*(b51*DyDx[i] + b52*ak2[i]
+ b53*ak3[i] + b54*ak4[i]) ;
}
RightHandSide(yTemp, ak5) ; // 5th stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*(b61*DyDx[i] + b62*ak2[i] + b63*ak3[i] +
b64*ak4[i] + b65*ak5[i]) ;
yOut[i] = yIn[i] + Step*(b61*DyDx[i] + b62*ak2[i] + b63*ak3[i]
+ b64*ak4[i] + b65*ak5[i]) ;
}
RightHandSide(yOut, ak6) ; // 6th and Final stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yErr[i] = Step*(dc1*DyDx[i] + dc2*ak2[i] + dc3*ak3[i] + dc4*ak4[i] +
dc5*ak5[i] + dc6*ak6[i] ) ;
yErr[i] = Step*(dc1*DyDx[i] + dc2*ak2[i] + dc3*ak3[i] + dc4*ak4[i]
+ dc5*ak5[i] + dc6*ak6[i] ) ;
// Store Input and Final values, for possible use in calculating chord
//
fLastInitialVector[i] = yIn[i] ;
fLastFinalVector[i] = yOut[i];
fLastDyDx[i] = DyDx[i];
}
fLastStepLength = Step;
@@ -226,83 +196,81 @@ void G4DoLoMcPriRK34::Stepper(const G4double yInput[],
return ;
}
//The following has not been tested
//The DistChord() function fot the class - must define it here.
// DistChord
//
G4double G4DoLoMcPriRK34::DistChord() const
{
G4double distLine, distChord;
G4ThreeVector initialPoint, finalPoint, midPoint;
// Store last initial and final points (they will be overwritten in self-Stepper call!)
// Store last initial and final points
// (they will be overwritten in self-Stepper call!)
//
initialPoint = G4ThreeVector( fLastInitialVector[0],
fLastInitialVector[1], fLastInitialVector[2]);
fLastInitialVector[1], fLastInitialVector[2] );
finalPoint = G4ThreeVector( fLastFinalVector[0],
fLastFinalVector[1], fLastFinalVector[2]);
fLastFinalVector[1], fLastFinalVector[2] );
// Do half a Step using StepNoErr
fAuxStepper->Stepper( fLastInitialVector, fLastDyDx, 0.5 * fLastStepLength,
fMidVector, fMidError );
fMidVector, fMidError );
midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2]);
// Use stored values of Initial and Endpoint + new Midpoint to evaluate
// distance of Chord
// distance of Chord
//
if (initialPoint != finalPoint)
{
distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
distChord = distLine;
distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
distChord = distLine;
}
else
{
distChord = (midPoint-initialPoint).mag();
distChord = (midPoint-initialPoint).mag();
}
return distChord;
}
void G4DoLoMcPriRK34::SetupInterpolation()
{}
void G4DoLoMcPriRK34::SetupInterpolate( const G4double /* yInput */ [] ,
const G4double /* dydx */ [] ,
const G4double /* Step */ )
{
//Do Nothing
}
void G4DoLoMcPriRK34::SetupInterpolate( const G4double /* yInput */ [] ,
const G4double /* dydx */ [] ,
const G4double /* Step */ )
{
// Do Nothing
}
void G4DoLoMcPriRK34::Interpolate( G4double tau,
G4double yOut[])
G4double yOut[] )
{
Interpolate( fLastInitialVector, fLastDyDx, fLastStepLength, yOut, tau );
Interpolate( fLastInitialVector, fLastDyDx, fLastStepLength, yOut, tau );
}
// Function to evaluate the interpolation at tau fraction of the step
//
void G4DoLoMcPriRK34::Interpolate( const G4double yInput[],
const G4double dydx[],
const G4double Step,
G4double yOut[],
G4double tau ){
G4double
bf1, bf2, bf3, bf4, bf5, bf6;
const G4double dydx[],
const G4double Step,
G4double yOut[],
G4double tau )
{
G4double bf1, bf2, bf3, bf4, bf5, bf6;
const G4int numberOfVariables = GetNumberOfVariables();
const G4int numberOfVariables= this->GetNumberOfVariables();
for(int i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
yIn[i]=yInput[i];
}
G4double
tau_2 = tau*tau ,
tau_3 = tau*tau_2;
G4double tau_2 = tau*tau, tau_3 = tau*tau_2;
//Calculating the polynomials (coefficients for the respective stages)
// Calculating the polynomials (coefficients for the respective stages)
//
bf1 = -(162.0*tau_3 - 504.0*tau_2 + 551.0*tau - 238.0)/238.0 ,
bf2 = 0.0 ,
bf3 = 27.0*tau*(27.0*tau_2 - 70.0*tau + 51.0 )/385.0 ,
@@ -310,15 +278,9 @@ void G4DoLoMcPriRK34::Interpolate( const G4double yInput[],
bf5 = 7.0*tau*(2232.0*tau_2 - 4166.0*tau + 1785.0 )/3278.0 ,
bf6 = tau*(tau - 1.0)*(387.0*tau - 238.0)/149.0 ;
for( int i=0; i<numberOfVariables; i++){
yOut[i] = yIn[i] + Step*tau*(bf1*dydx[i] + bf2*ak2[i] + bf3*ak3[i] +
bf4*ak4[i] + bf5*ak5[i] + bf6*ak6[i] ) ;
for( G4int i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*tau*(bf1*dydx[i] + bf2*ak2[i] + bf3*ak3[i]
+ bf4*ak4[i] + bf5*ak5[i] + bf6*ak6[i] ) ;
}
}
//-------Verified------- - hackabot
@@ -23,104 +23,74 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4DormandPrince745 implementation
//
// Class description:
// DormandPrince7 - 5(4) non-FSAL
// definition of the stepper() method that evaluates one step in
// field propagation.
// The coefficients and the algorithm have been adapted from
//
// DormandPrince7 - 5(4) non-FSAL
// J. R. Dormand and P. J. Prince, "A family of embedded Runge-Kutta formulae"
// Journal of computational and applied Math., vol.6, no.1, pp.19-26, 1980.
//
// This is the source file of G4DormandPrince745 class containing the
// definition of the stepper() method that evaluates one step in
// field propagation.
// The coefficients and the algorithm have been adapted from
//
// Table 2 : Coefficients of RK5(4)7M
// ---Ref---
// J. R. Dormand and P. J. Prince, “A family of embedded Runge-Kutta formulae,”
// Journal of computational and applied …, vol. 6, no. 1, pp. 1926, 1980.
// ------------------
//
// The Butcher table of the Dormand-Prince-7-4-5 method is as follows :
// The Butcher table of the Dormand-Prince-7-4-5 method is as follows :
//
// 0 |
// 1/5 | 1/5
// 3/10| 3/40 9/40
// 4/5 | 44/45 56/15 32/9
// 8/9 | 19372/6561 25360/2187 64448/6561 212/729
// 1 | 9017/3168 355/33 46732/5247 49/176 5103/18656
// 1 | 35/384 0 500/1113 125/192 2187/6784 11/84
// 3/10| 3/40 9/40
// 4/5 | 44/45 56/15 32/9
// 8/9 | 19372/6561 25360/2187 64448/6561 212/729
// 1 | 9017/3168 355/33 46732/5247 49/176 5103/18656
// 1 | 35/384 0 500/1113 125/192 2187/6784 11/84
// ------------------------------------------------------------------------
// 35/384 0 500/1113 125/192 2187/6784 11/84 0
// 5179/57600 0 7571/16695 393/640 92097/339200 187/2100 1/40
//
//
// Implementation by Somnath Banerjee - GSoC 2015
// Work supported by Google as part of Google Summer of Code 2015.
// Supervision / code review: John Apostolakis
//
// First version: 25 May 2015 - Somnath Banerjee
// 35/384 0 500/1113 125/192 2187/6784 11/84 0
// 5179/57600 0 7571/16695 393/640 92097/339200 187/2100 1/40
//
// Created: Somnath Banerjee, Google Summer of Code 2015, 25 May 2015
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4DormandPrince745.hh"
#include "G4LineSection.hh"
#include <cstring>
using namespace field_utils;
G4DormandPrince745::G4DormandPrince745(G4EquationOfMotion* equation,
G4int noIntegrationVariables)
: G4MagIntegratorStepper(equation, noIntegrationVariables)
{}
{
}
void G4DormandPrince745::Stepper(const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[])
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[])
{
Stepper(yInput, dydx, hstep, yOutput, yError);
copy(dydxOutput, ak7);
Stepper(yInput, dydx, hstep, yOutput, yError);
copy(dydxOutput, ak7);
}
// The coefficients and the algorithm have been adapted from
// Table 2 : Coefficients of RK5(4)7M
// ---Ref---
// J. R. Dormand and P. J. Prince, “A family of embedded Runge-Kutta formulae,”
// Journal of computational and applied …, vol. 6, no. 1, pp. 1926, 1980.
// ------------------
// The Butcher table of the Dormand-Prince-7-4-5 method is as follows :
// Stepper
//
// 0 |
// 1/5 | 1/5
// 3/10| 3/40 9/40
// 4/5 | 44/45 56/15 32/9
// 8/9 | 19372/6561 25360/2187 64448/6561 212/729
// 1 | 9017/3168 355/33 46732/5247 49/176 5103/18656
// 1 | 35/384 0 500/1113 125/192 2187/6784 11/84
// ------------------------------------------------------------------------
// 35/384 0 500/1113 125/192 2187/6784 11/84 0
// 5179/57600 0 7571/16695 393/640 92097/339200 187/2100 1/40
//Stepper :
// Passing in the value of yInput[],the first time dydx[] and Step length
// Giving back yOut and yErr arrays for output and error respectively
//
void G4DormandPrince745::Stepper(const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOut[],
G4double yErr[])
{
//The various constants defined on the basis of butcher tableu
const G4double
b21 = 0.2,
b31 = 3.0 / 40.0, b32 = 9.0 / 40.0,
b41 = 44.0 / 45.0, b42 = -56.0 / 15.0, b43 = 32.0/9.0,
// The various constants defined on the basis of butcher tableu
//
const G4double b21 = 0.2,
b31 = 3.0 / 40.0, b32 = 9.0 / 40.0,
b41 = 44.0 / 45.0, b42 = -56.0 / 15.0, b43 = 32.0/9.0,
b51 = 19372.0 / 6561.0, b52 = -25360.0 / 2187.0, b53 = 64448.0 / 6561.0,
b54 = -212.0 / 729.0,
@@ -152,18 +122,20 @@ void G4DormandPrince745::Stepper(const G4double yInput[],
dc6 = -(b76 - 187.0 / 2100.0),
dc7 = -(- 1.0 / 40.0);
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
State yTemp;
// The number of variables to be integrated over
//
yOut[7] = yTemp[7] = yInput[7];
// Saving yInput because yInput and yOut can be aliases for same array
//
for(G4int i = 0; i < numberOfVariables; ++i)
{
fyIn[i] = yInput[i];
}
// RightHandSide(yIn, dydx);
// RightHandSide(yIn, dydx); // Not done! 1st stage
for(G4int i = 0; i < numberOfVariables; ++i)
{
@@ -179,7 +151,8 @@ void G4DormandPrince745::Stepper(const G4double yInput[],
for(G4int i = 0; i < numberOfVariables; ++i)
{
yTemp[i] = fyIn[i] + hstep * (b41 * dydx[i] + b42 * ak2[i] + b43 * ak3[i]);
yTemp[i] = fyIn[i] + hstep * (
b41 * dydx[i] + b42 * ak2[i] + b43 * ak3[i]);
}
RightHandSide(yTemp, ak4); // 4th stage
@@ -204,7 +177,7 @@ void G4DormandPrince745::Stepper(const G4double yInput[],
b71 * dydx[i] + b72 * ak2[i] + b73 * ak3[i] +
b74 * ak4[i] + b75 * ak5[i] + b76 * ak6[i]);
}
RightHandSide(yOut, ak7); //7th and Final stage
RightHandSide(yOut, ak7); // 7th and Final stage
for(G4int i = 0; i < numberOfVariables; ++i)
{
@@ -215,6 +188,7 @@ void G4DormandPrince745::Stepper(const G4double yInput[],
) + 1.5e-18;
// Store Input and Final values, for possible use in calculating chord
//
fyOut[i] = yOut[i];
fdydxIn[i] = dydx[i];
}
@@ -224,14 +198,15 @@ void G4DormandPrince745::Stepper(const G4double yInput[],
G4double G4DormandPrince745::DistChord() const
{
// Coefficients were taken from Some Practical Runge-Kutta Formulas by Lawrence F. Shampine, page 149, c*
const G4double
hf1 = 6025192743.0 / 30085553152.0,
hf3 = 51252292925.0 / 65400821598.0,
hf4 = - 2691868925.0 / 45128329728.0,
hf5 = 187940372067.0 / 1594534317056.0,
hf6 = - 1776094331.0 / 19743644256.0,
hf7 = 11237099.0 / 235043384.0;
// Coefficients were taken from Some Practical Runge-Kutta Formulas
// by Lawrence F. Shampine, page 149, c*
//
const G4double hf1 = 6025192743.0 / 30085553152.0,
hf3 = 51252292925.0 / 65400821598.0,
hf4 = - 2691868925.0 / 45128329728.0,
hf5 = 187940372067.0 / 1594534317056.0,
hf6 = - 1776094331.0 / 19743644256.0,
hf7 = 11237099.0 / 235043384.0;
G4ThreeVector mid;
@@ -248,21 +223,19 @@ G4double G4DormandPrince745::DistChord() const
return G4LineSection::Distline(mid, begin, end);
}
// The lower (4th) order interpolant given by Dormand and prince
// "An RK 5(4) triple"
//---Ref---
// J. R. Dormand and P. J. Prince, “Runge-Kutta triples,”
// Computers & Mathematics with Applications, vol. 12, no. 9,
// pp. 10071017, 1986.
//---------------------------
void G4DormandPrince745::Interpolate4thOrder(G4double yOut[], G4double tau) const
// The lower (4th) order interpolant given by Dormand and Prince:
// J. R. Dormand and P. J. Prince, "Runge-Kutta triples"
// Computers & Mathematics with Applications, vol. 12, no. 9,
// pp. 1007-1017, 1986.
//
void G4DormandPrince745::
Interpolate4thOrder(G4double yOut[], G4double tau) const
{
const G4int numberOfVariables = this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
const G4double
tau2 = tau * tau,
tau3 = tau * tau2,
tau4 = tau2 * tau2;
const G4double tau2 = tau * tau,
tau3 = tau * tau2,
tau4 = tau2 * tau2;
const G4double bf1 = 1.0 / 11282082432.0 * (
157015080.0 * tau4 - 13107642775.0 * tau3 + 34969693132.0 * tau2 -
@@ -295,180 +268,164 @@ void G4DormandPrince745::Interpolate4thOrder(G4double yOut[], G4double tau) cons
}
}
// Following interpolant of order 5 was given by Baker,Dormand,Gilmore, Prince :
//---Ref---
// T. S. Baker, J. R. Dormand, J. P. Gilmore, and P. J. Prince,
// “Continuous approximation with embedded Runge-Kutta methods,”
// Applied Numerical Mathematics, vol. 22, no. 1, pp. 5162, 1996.
//---------------------
// Calculating the extra stages for the interpolant :
void G4DormandPrince745::SetupInterpolation_high()
// T. S. Baker, J. R. Dormand, J. P. Gilmore, and P. J. Prince,
// "Continuous approximation with embedded Runge-Kutta methods"
// Applied Numerical Mathematics, vol. 22, no. 1, pp. 51-62, 1996.
//
// Calculating the extra stages for the interpolant
//
void G4DormandPrince745::SetupInterpolation5thOrder()
{
//Coefficients for the additional stages :
const G4double
b81 = 6245.0/62208.0 ,
b82 = 0.0 ,
b83 = 8875.0/103032.0 ,
b84 = -125.0/1728.0 ,
b85 = 801.0/13568.0 ,
b86 = -13519.0/368064.0 ,
b87 = 11105.0/368064.0 ,
// Coefficients for the additional stages
//
const G4double b81 = 6245.0 / 62208.0,
b82 = 0.0,
b83 = 8875.0 / 103032.0,
b84 = -125.0 / 1728.0,
b85 = 801.0 / 13568.0,
b86 = -13519.0 / 368064.0,
b87 = 11105.0 / 368064.0,
b91 = 632855.0 / 4478976.0,
b92 = 0.0,
b93 = 4146875.0 / 6491016.0,
b94 = 5490625.0 /14183424.0,
b95 = -15975.0 / 108544.0,
b96 = 8295925.0 / 220286304.0,
b97 = -1779595.0 / 62938944.0,
b98 = -805.0 / 4104.0;
b91 = 632855.0/4478976.0 ,
b92 = 0.0 ,
b93 = 4146875.0/6491016.0 ,
b94 = 5490625.0/14183424.0 ,
b95 = -15975.0/108544.0 ,
b96 = 8295925.0/220286304.0 ,
b97 = -1779595.0/62938944.0 ,
b98 = -805.0/4104.0 ;
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4double *dydx = fdydxIn;
const G4double Step = fLastStepLength;
const G4int numberOfVariables = GetNumberOfVariables();
State yTemp;
// Saving yInput because yInput and yOut can be aliases for same array
// for(int i=0;i<numberOfVariables;i++) { yIn[i]=yInput[i]; }
// yTemp[7] = yIn[7];
//Evaluate the extra stages :
for(int i=0;i<numberOfVariables;i++)
// Evaluate the extra stages
//
for(G4int i = 0; i < numberOfVariables; ++i)
{
yTemp[i] = fyIn[i] + Step*(b81*dydx[i] + b82*ak2[i] + b83*ak3[i] +
b84*ak4[i] + b85*ak5[i] + b86*ak6[i] +
b87*ak7[i]);
yTemp[i] = fyIn[i] + fLastStepLength * (
b81 * fdydxIn[i] + b82 * ak2[i] + b83 * ak3[i] +
b84 * ak4[i] + b85 * ak5[i] + b86 * ak6[i] +
b87 * ak7[i]
);
}
RightHandSide(yTemp, ak8); //8th Stage
RightHandSide(yTemp, ak8); // 8th Stage
for(int i=0;i<numberOfVariables;i++)
for(G4int i = 0; i < numberOfVariables; ++i)
{
yTemp[i] = fyIn[i] + Step*(b91*dydx[i] + b92*ak2[i] + b93*ak3[i] +
b94*ak4[i] + b95*ak5[i] + b96*ak6[i] +
b97*ak7[i] + b98*ak8[i] );
yTemp[i] = fyIn[i] + fLastStepLength * (
b91 * fdydxIn[i] + b92 * ak2[i] + b93 * ak3[i] +
b94 * ak4[i] + b95 * ak5[i] + b96 * ak6[i] +
b97 * ak7[i] + b98 * ak8[i]
);
}
RightHandSide(yTemp, ak9); //9th Stage
RightHandSide(yTemp, ak9); // 9th Stage
}
// Calculating the interpolated result yOut with the coefficients
void G4DormandPrince745::Interpolate_high(G4double yOut[], G4double tau )
//
void G4DormandPrince745::
Interpolate5thOrder(G4double yOut[], G4double tau) const
{
//Define the coefficients for the polynomials
G4double bi[10][5], b[10];
const G4int numberOfVariables = this->GetNumberOfVariables();
// const G4double fullStep = fLastStepLength;
// If given requestedStep in argument:
// G4double tau = requestedStep / fLastStepLength;
// Define the coefficients for the polynomials
//
G4double bi[10][5];
// COEFFICIENTS OF bi[1]
bi[1][0] = 1.0 ,
bi[1][1] = -38039.0/7040.0 ,
bi[1][2] = 125923.0/10560.0 ,
bi[1][3] = -19683.0/1760.0 ,
bi[1][4] = 3303.0/880.0 ,
bi[1][0] = 1.0,
bi[1][1] = -38039.0 / 7040.0,
bi[1][2] = 125923.0 / 10560.0,
bi[1][3] = -19683.0 / 1760.0,
bi[1][4] = 3303.0 / 880.0,
// --------------------------------------------------------
//
// COEFFICIENTS OF bi[2]
bi[2][0] = 0.0 ,
bi[2][1] = 0.0 ,
bi[2][2] = 0.0 ,
bi[2][3] = 0.0 ,
bi[2][4] = 0.0 ,
bi[2][0] = 0.0,
bi[2][1] = 0.0,
bi[2][2] = 0.0,
bi[2][3] = 0.0,
bi[2][4] = 0.0,
// --------------------------------------------------------
//
// COEFFICIENTS OF bi[3]
bi[3][0] = 0.0 ,
bi[3][1] = -12500.0/4081.0 ,
bi[3][2] = 205000.0/12243.0 ,
bi[3][3] = -90000.0/4081.0 ,
bi[3][4] = 36000.0/4081.0 ,
bi[3][0] = 0.0,
bi[3][1] = -12500.0 / 4081.0,
bi[3][2] = 205000.0 / 12243.0,
bi[3][3] = -90000.0 / 4081.0,
bi[3][4] = 36000.0 / 4081.0,
// --------------------------------------------------------
//
// COEFFICIENTS OF bi[4]
bi[4][0] = 0.0 ,
bi[4][1] = -3125.0/704.0 ,
bi[4][2] = 25625.0/1056.0 ,
bi[4][3] = -5625.0/176.0 ,
bi[4][4] = 1125.0/88.0 ,
bi[4][0] = 0.0,
bi[4][1] = -3125.0 / 704.0,
bi[4][2] = 25625.0 / 1056.0,
bi[4][3] = -5625.0 / 176.0,
bi[4][4] = 1125.0 / 88.0,
// --------------------------------------------------------
//
// COEFFICIENTS OF bi[5]
bi[5][0] = 0.0 ,
bi[5][1] = 164025.0/74624.0 ,
bi[5][2] = -448335.0/37312.0 ,
bi[5][3] = 295245.0/18656.0 ,
bi[5][4] = -59049.0/9328.0 ,
bi[5][0] = 0.0,
bi[5][1] = 164025.0 / 74624.0,
bi[5][2] = -448335.0 / 37312.0,
bi[5][3] = 295245.0 / 18656.0,
bi[5][4] = -59049.0 / 9328.0,
// --------------------------------------------------------
//
// COEFFICIENTS OF bi[6]
bi[6][0] = 0.0 ,
bi[6][1] = -25.0/28.0 ,
bi[6][2] = 205.0/42.0 ,
bi[6][3] = -45.0/7.0 ,
bi[6][4] = 18.0/7.0 ,
bi[6][0] = 0.0,
bi[6][1] = -25.0 / 28.0,
bi[6][2] = 205.0 / 42.0,
bi[6][3] = -45.0 / 7.0,
bi[6][4] = 18.0 / 7.0,
// --------------------------------------------------------
//
// COEFFICIENTS OF bi[7]
bi[7][0] = 0.0 ,
bi[7][1] = -2.0/11.0 ,
bi[7][2] = 73.0/55.0 ,
bi[7][3] = -171.0/55.0 ,
bi[7][4] = 108.0/55.0 ,
bi[7][0] = 0.0,
bi[7][1] = -2.0 / 11.0,
bi[7][2] = 73.0 / 55.0,
bi[7][3] = -171.0 / 55.0,
bi[7][4] = 108.0 / 55.0,
// --------------------------------------------------------
//
// COEFFICIENTS OF bi[8]
bi[8][0] = 0.0 ,
bi[8][1] = 189.0/22.0 ,
bi[8][2] = -1593.0/55.0 ,
bi[8][3] = 3537.0/110.0 ,
bi[8][4] = -648.0/55.0 ,
bi[8][0] = 0.0,
bi[8][1] = 189.0 / 22.0,
bi[8][2] = -1593.0 / 55.0,
bi[8][3] = 3537.0 / 110.0,
bi[8][4] = -648.0 / 55.0,
// --------------------------------------------------------
//
// COEFFICIENTS OF bi[9]
bi[9][0] = 0.0 ,
bi[9][1] = 351.0/110.0 ,
bi[9][2] = -999.0/55.0 ,
bi[9][3] = 2943.0/110.0 ,
bi[9][4] = -648.0/55.0 ;
bi[9][0] = 0.0,
bi[9][1] = 351.0 / 110.0,
bi[9][2] = -999.0 / 55.0,
bi[9][3] = 2943.0 / 110.0,
bi[9][4] = -648.0 / 55.0;
// --------------------------------------------------------
// for(G4int i = 0; i< numberOfVariables; i++) { yIn[i] = yInput[i]; }
// Calculating the polynomials :
#if 1
for(int iStage=1; iStage<=9; iStage++){
b[iStage] = 0;
}
// Calculating the polynomials
G4double b[10];
std::memset(b, 0.0, sizeof(b));
for(int j=0; j<=4; j++){
G4double tauPower = 1.0;
for(int iStage=1; iStage<=9; iStage++){
b[iStage] += bi[iStage][j]*tauPower;
G4double tauPower = 1.0;
for(G4int j = 0; j <= 4; ++j)
{
for(G4int iStage = 1; iStage <= 9; ++iStage)
{
b[iStage] += bi[iStage][j] * tauPower;
}
tauPower *= tau;
}
#else
G4double tau0 = tau;
for(int i=1; i<=9; i++){ //Here i is NOT the coordinate no. , it's stage no.
b[i] = 0;
tau = 1.0;
for(int j=0; j<=4; j++){
b[i] += bi[i][j]*tau;
tau*=tau0;
}
}
#endif
G4double stepLen = fLastStepLength * tau;
for(int i=0; i<numberOfVariables; i++){ //Here i IS the cooridnate no.
yOut[i] = fyIn[i] + stepLen *(b[1]*fdydxIn[i] + b[2]*ak2[i] + b[3]*ak3[i] +
b[4]*ak4[i] + b[5]*ak5[i] + b[6]*ak6[i] +
b[7]*ak7[i] + b[8]*ak8[i] + b[9]*ak9[i] );
const G4int numberOfVariables = GetNumberOfVariables();
const G4double stepLen = fLastStepLength * tau;
for(G4int i = 0; i < numberOfVariables; ++i)
{
yOut[i] = fyIn[i] + stepLen * (
b[1] * fdydxIn[i] + b[2] * ak2[i] + b[3] * ak3[i] +
b[4] * ak4[i] + b[5] * ak5[i] + b[6] * ak6[i] +
b[7] * ak7[i] + b[8] * ak8[i] + b[9] * ak9[i]
);
}
}
}
@@ -23,38 +23,28 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// FDormand-Prince RK 6(5) FSAL implementation by Somnath Banerjee
// Supervision / code review: John Apostolakis
// G4DormandPrinceRK56 implementation
//
// Sponsored by Google in Google Summer of Code 2015.
//
// First version: 26 June 2015
//
// G4DormandPrince745.cc
// Geant4
//
// History
// -----------------------------
// Created by Somnath on 26 June 2015
//
//
///////////////////////////////////////////////////////////////////////////////
// Created: Somnath Banerjee, Google Summer of Code 2015, 26 June 2015
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4DormandPrinceRK56.hh"
#include "G4LineSection.hh"
//Constructor
G4DormandPrinceRK56::G4DormandPrinceRK56(G4EquationOfMotion *EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables),
fLastStepLength(-1.0), fAuxStepper(nullptr)
// Constructor
//
G4DormandPrinceRK56::G4DormandPrinceRK56(G4EquationOfMotion* EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables)
{
const G4int numberOfVariables = noIntegrationVariables;
//New Chunk of memory being created for use by the stepper
// New Chunk of memory being created for use by the stepper
//aki - for storing intermediate RHS
// aki - for storing intermediate RHS
//
ak2 = new G4double[numberOfVariables];
ak3 = new G4double[numberOfVariables];
ak4 = new G4double[numberOfVariables];
@@ -65,6 +55,7 @@ G4DormandPrinceRK56::G4DormandPrinceRK56(G4EquationOfMotion *EqRhs,
ak9 = new G4double[numberOfVariables];
// Memory for Additional stages
//
ak10 = new G4double[numberOfVariables];
ak11 = new G4double[numberOfVariables];
ak12 = new G4double[numberOfVariables];
@@ -80,145 +71,136 @@ G4DormandPrinceRK56::G4DormandPrinceRK56(G4EquationOfMotion *EqRhs,
fLastDyDx = new G4double[numStateVars];
fMidVector = new G4double[numStateVars];
fMidError = new G4double[numStateVars];
fMidError = new G4double[numStateVars];
if( primary )
{
fAuxStepper = new G4DormandPrinceRK56(EqRhs, numberOfVariables,
!primary);
fAuxStepper = new G4DormandPrinceRK56(EqRhs, numberOfVariables, !primary);
}
}
// Destructor
//
G4DormandPrinceRK56::~G4DormandPrinceRK56()
{
// clear all previously allocated memory for stepper and DistChord
//Destructor
G4DormandPrinceRK56::~G4DormandPrinceRK56(){
//clear all previously allocated memory for stepper and DistChord
delete[] ak2;
delete[] ak3;
delete[] ak4;
delete[] ak5;
delete[] ak6;
delete[] ak7;
delete[] ak8;
delete[] ak9;
delete [] ak2;
delete [] ak3;
delete [] ak4;
delete [] ak5;
delete [] ak6;
delete [] ak7;
delete [] ak8;
delete [] ak9;
delete[] ak10;
delete[] ak10_low;
delete[] ak11;
delete[] ak12;
delete [] ak10;
delete [] ak10_low;
delete [] ak11;
delete [] ak12;
delete[] yTemp;
delete[] yIn;
delete [] yTemp;
delete [] yIn;
delete[] fLastInitialVector;
delete[] fLastFinalVector;
delete[] fLastDyDx;
delete[] fMidVector;
delete[] fMidError;
delete [] fLastInitialVector;
delete [] fLastFinalVector;
delete [] fLastDyDx;
delete [] fMidVector;
delete [] fMidError;
delete fAuxStepper;
}
//Stepper :
// Stepper
//
// Passing in the value of yInput[],the first time dydx[] and Step length
// Giving back yOut and yErr arrays for output and error respectively
//
void G4DormandPrinceRK56::Stepper(const G4double yInput[],
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[] )
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[] )
// G4double nextDydx[] ) -- Output:
// endpoint DyDx ( for future FSAL version )
// endpoint DyDx ( for future FSAL version )
{
G4int i;
//The various constants defined on the basis of butcher tableu
const G4double //G4double - only once
// The various constants defined on the basis of butcher tableu
// Old Coefficients from
// Table 1. RK6(5)8M
//---Ref---
//[P. J. Prince and J. R. Dormand, “High order embedded Runge-Kutta formulae,”
// Journal of Computational and Applied Mathematics, vol. 7, no. 1, pp. 6775,
// Dec. 1980.
//----------------
// P.J.Prince and J.R.Dormand, "High order embedded Runge-Kutta formulae"
// Journal of Computational and Applied Math., vol.7, no.1, pp.67-75, 1980.
//
const G4double b21 = 1.0/10.0 ,
b31 = -2.0/81.0 ,
b32 = 20.0/81.0 ,
b41 = 615.0/1372.0 ,
b42 = -270.0/343.0 ,
b43 = 1053.0/1372.0 ,
b51 = 3243.0/5500.0 ,
b52 = -54.0/55.0 ,
b53 = 50949.0/71500.0 ,
b54 = 4998.0/17875.0 ,
b61 = -26492.0/37125.0 ,
b62 = 72.0/55.0 ,
b63 = 2808.0/23375.0 ,
b64 = -24206.0/37125.0 ,
b65 = 338.0/459.0 ,
b71 = 5561.0/2376.0 ,
b72 = -35.0/11.0 ,
b73 = -24117.0/31603.0 ,
b74 = 899983.0/200772.0 ,
b75 = -5225.0/1836.0 ,
b76 = 3925.0/4056.0 ,
b81 = 465467.0/266112.0 ,
b82 = -2945.0/1232.0 ,
b83 = -5610201.0/14158144.0 ,
b84 = 10513573.0/3212352.0 ,
b85 = -424325.0/205632.0 ,
b86 = 376225.0/454272.0 ,
b87 = 0.0 ,
c1 = 61.0/864.0 ,
c2 = 0.0 ,
c3 = 98415.0/321776.0 ,
c4 = 16807.0/146016.0 ,
c5 = 1375.0/7344.0 ,
c6 = 1375.0/5408.0 ,
c7 = -37.0/1120.0 ,
c8 = 1.0/10.0 ,
b91 = 61.0/864.0 ,
b92 = 0.0 ,
b93 = 98415.0/321776.0 ,
b94 = 16807.0/146016.0 ,
b95 = 1375.0/7344.0 ,
b96 = 1375.0/5408.0 ,
b97 = -37.0/1120.0 ,
b98 = 1.0/10.0 ,
b21 = 1.0/10.0 ,
b31 = -2.0/81.0 ,
b32 = 20.0/81.0 ,
b41 = 615.0/1372.0 ,
b42 = -270.0/343.0 ,
b43 = 1053.0/1372.0 ,
b51 = 3243.0/5500.0 ,
b52 = -54.0/55.0 ,
b53 = 50949.0/71500.0 ,
b54 = 4998.0/17875.0 ,
b61 = -26492.0/37125.0 ,
b62 = 72.0/55.0 ,
b63 = 2808.0/23375.0 ,
b64 = -24206.0/37125.0 ,
b65 = 338.0/459.0 ,
b71 = 5561.0/2376.0 ,
b72 = -35.0/11.0 ,
b73 = -24117.0/31603.0 ,
b74 = 899983.0/200772.0 ,
b75 = -5225.0/1836.0 ,
b76 = 3925.0/4056.0 ,
b81 = 465467.0/266112.0 ,
b82 = -2945.0/1232.0 ,
b83 = -5610201.0/14158144.0 ,
b84 = 10513573.0/3212352.0 ,
b85 = -424325.0/205632.0 ,
b86 = 376225.0/454272.0 ,
b87 = 0.0 ,
c1 = 61.0/864.0 ,
c2 = 0.0 ,
c3 = 98415.0/321776.0 ,
c4 = 16807.0/146016.0 ,
c5 = 1375.0/7344.0 ,
c6 = 1375.0/5408.0 ,
c7 = -37.0/1120.0 ,
c8 = 1.0/10.0 ,
b91 = 61.0/864.0 ,
b92 = 0.0 ,
b93 = 98415.0/321776.0 ,
b94 = 16807.0/146016.0 ,
b95 = 1375.0/7344.0 ,
b96 = 1375.0/5408.0 ,
b97 = -37.0/1120.0 ,
b98 = 1.0/10.0 ,
dc1 = c1 - 821.0/10800.0 ,
dc2 = c2 - 0.0 ,
dc3 = c3 - 19683.0/71825,
dc4 = c4 - 175273.0/912600.0 ,
dc5 = c5 - 395.0/3672.0 ,
dc6 = c6 - 785.0/2704.0 ,
dc7 = c7 - 3.0/50.0 ,
dc8 = c8 - 0.0 ,
dc9 = 0.0;
dc1 = c1 - 821.0/10800.0 ,
dc2 = c2 - 0.0 ,
dc3 = c3 - 19683.0/71825,
dc4 = c4 - 175273.0/912600.0 ,
dc5 = c5 - 395.0/3672.0 ,
dc6 = c6 - 785.0/2704.0 ,
dc7 = c7 - 3.0/50.0 ,
dc8 = c8 - 0.0 ,
dc9 = 0.0;
// New Coefficients obtained from
// Table 3 RK6(5)9FM with corrected coefficients
//---Ref---
// Table 3 RK6(5)9FM with corrected coefficients
//
// T. S. Baker, J. R. Dormand, J. P. Gilmore, and P. J. Prince,
// Continuous approximation with embedded Runge-Kutta methods,”
// Applied Numerical Mathematics, vol. 22, no. 1, pp. 5162, 1996.
//------------------------------------
// "Continuous approximation with embedded Runge-Kutta methods"
// Applied Numerical Mathematics, vol. 22, no. 1, pp. 51-62, 1996.
//
// b21 = 1.0/9.0 ,
//
// b31 = 1.0/24.0 ,
@@ -273,101 +255,96 @@ void G4DormandPrinceRK56::Stepper(const G4double yInput[],
// dc7 = 262119736669.0/345979336560.0 - b97,
// dc8 = - 1.0/2.0 - b98 ,
// dc9 = -101.0/2294.0 ;
//end of declaration
// end of declaration
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
// The number of variables to be integrated over
//
yOut[7] = yTemp[7] = yIn[7] = yInput[7];
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<numberOfVariables;i++)
//
for(i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
}
// RightHandSide(yIn, dydx) ; // 1st Stage - Not doing, getting passed
// RightHandSide(yIn, dydx) ;
// 1st Step - Not doing, getting passed
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + b21*Step*dydx[i] ;
}
RightHandSide(yTemp, ak2) ; // 2nd Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b31*dydx[i] + b32*ak2[i]) ;
}
RightHandSide(yTemp, ak3) ; // 3rd Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b41*dydx[i] + b42*ak2[i] + b43*ak3[i]) ;
}
RightHandSide(yTemp, ak4) ; // 4th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b51*dydx[i] + b52*ak2[i] + b53*ak3[i] +
b54*ak4[i]) ;
}
RightHandSide(yTemp, ak5) ; // 5th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b61*dydx[i] + b62*ak2[i] + b63*ak3[i] +
b64*ak4[i] + b65*ak5[i]) ;
}
RightHandSide(yTemp, ak6) ; // 6th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b71*dydx[i] + b72*ak2[i] + b73*ak3[i] +
b74*ak4[i] + b75*ak5[i] + b76*ak6[i]);
}
RightHandSide(yTemp, ak7); //7th Stage
RightHandSide(yTemp, ak7); // 7th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b81*dydx[i] + b82*ak2[i] + b83*ak3[i] +
b84*ak4[i] + b85*ak5[i] + b86*ak6[i] +
b87*ak7[i]);
}
RightHandSide(yTemp, ak8); //8th Stage
RightHandSide(yTemp, ak8); // 8th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*(b91*dydx[i] + b92*ak2[i] + b93*ak3[i] +
b94*ak4[i] + b95*ak5[i] + b96*ak6[i] +
b97*ak7[i] + b98*ak8[i] );
}
RightHandSide(yOut, ak9); //9th Stage
RightHandSide(yOut, ak9); // 9th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
// Estimate error as difference between 5th and
// 6th order methods
//
yErr[i] = Step*( dc1*dydx[i] + dc2*ak2[i] + dc3*ak3[i] + dc4*ak4[i]
+ dc5*ak5[i] + dc6*ak6[i] + dc7*ak7[i] + dc8*ak8[i]
+ dc9*ak9[i] ) ;
// - Saving 'estimated' derivative at end-point
// Saving 'estimated' derivative at end-point
// nextDydx[i] = ak9[i];
// Store Input and Final values, for possible use in calculating chord
//
fLastInitialVector[i] = yIn[i] ;
fLastFinalVector[i] = yOut[i];
fLastDyDx[i] = dydx[i];
}
fLastStepLength = Step;
@@ -375,16 +352,16 @@ void G4DormandPrinceRK56::Stepper(const G4double yInput[],
return ;
}
//The following has not been tested
//The DistChord() function fot the class - must define it here.
// DistChord
//
G4double G4DormandPrinceRK56::DistChord() const
{
G4double distLine, distChord;
G4ThreeVector initialPoint, finalPoint, midPoint;
// Store last initial and final points (they will be overwritten in self-Stepper call!)
// Store last initial and final points
// (they will be overwritten in self-Stepper call!)
//
initialPoint = G4ThreeVector( fLastInitialVector[0],
fLastInitialVector[1], fLastInitialVector[2]);
finalPoint = G4ThreeVector( fLastFinalVector[0],
@@ -398,12 +375,11 @@ G4double G4DormandPrinceRK56::DistChord() const
midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2]);
// Use stored values of Initial and Endpoint + new Midpoint to evaluate
// distance of Chord
// distance of Chord
//
if (initialPoint != finalPoint)
{
distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
distLine = G4LineSection::Distline( midPoint,initialPoint,finalPoint );
distChord = distLine;
}
else
@@ -413,205 +389,195 @@ G4double G4DormandPrinceRK56::DistChord() const
return distChord;
}
// The following interpolation scheme has been obtained from
// Table 5. The RK6(5)9FM process and associated dense formula
//---Ref---
// J. R. Dormand, M. A. Lockyer, N. E. McGorrigan, and P. J. Prince,
//Global error estimation with runge-kutta triples,”
// Computers & Mathematics with Applications, vol. 18, no. 9, pp. 835846, 1989.
//-----------------------------
//
// J. R. Dormand, M. A. Lockyer, N. E. McGorrigan, and P. J. Prince,
// "Global error estimation with runge-kutta triples"
// Computers & Mathematics with Applications, vol.18, no.9, pp.835-846, 1989.
//
// Fifth order interpolant with one extra function evaluation per step
//
void G4DormandPrinceRK56::SetupInterpolate_low( const G4double yInput[],
const G4double dydx[],
const G4double Step ){
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4double dydx[],
const G4double Step )
{
const G4int numberOfVariables= this->GetNumberOfVariables();
G4double
b_101 = 33797.0/460800.0 ,
b_102 = 0. ,
b_103 = 0. ,
b_104 = 27757.0/70785.0 ,
b_105 = 7923501.0/26329600.0 ,
b_106 = -927.0/3760.0 ,
b_107 = -3314760575.0/23165835264.0 ,
b_108 = 2479.0/23040.0 ,
b_109 = 1.0/64.0 ;
G4double b_101 = 33797.0/460800.0 ,
b_102 = 0. ,
b_103 = 0. ,
b_104 = 27757.0/70785.0 ,
b_105 = 7923501.0/26329600.0 ,
b_106 = -927.0/3760.0 ,
b_107 = -3314760575.0/23165835264.0 ,
b_108 = 2479.0/23040.0 ,
b_109 = 1.0/64.0 ;
for(int i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
yIn[i]=yInput[i];
}
for(int i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b_101*dydx[i] + b_102*ak2[i] + b_103*ak3[i] +
b_104*ak4[i] + b_105*ak5[i] + b_106*ak6[i] +
b_107*ak7[i] + b_108*ak8[i] + b_109*ak9[i]);
yTemp[i] = yIn[i] + Step*(b_101*dydx[i] + b_102*ak2[i] + b_103*ak3[i] +
b_104*ak4[i] + b_105*ak5[i] + b_106*ak6[i] +
b_107*ak7[i] + b_108*ak8[i] + b_109*ak9[i]);
}
RightHandSide(yTemp, ak10_low); //10th Stage
RightHandSide(yTemp, ak10_low); // 10th Stage
}
void G4DormandPrinceRK56::Interpolate_low( const G4double yInput[],
const G4double dydx[],
const G4double Step,
G4double yOut[],
G4double tau ){
{
const G4double dydx[],
const G4double Step,
G4double yOut[],
G4double tau )
{
G4double bf1, bf4, bf5, bf6, bf7, bf8, bf9, bf10;
G4double
bf1, bf4, bf5, bf6, bf7, bf8, bf9, bf10;
G4double tau0 = tau;
const G4int numberOfVariables= this->GetNumberOfVariables();
G4double tau0 = tau;
const G4int numberOfVariables= this->GetNumberOfVariables();
for(int i=0;i<numberOfVariables;i++)
{
yIn[i]=yInput[i];
}
for(G4int i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
}
G4double
tau_2 = tau0*tau0 ,
tau_3 = tau0*tau_2,
tau_4 = tau_2*tau_2;
G4double tau_2 = tau0*tau0 ,
tau_3 = tau0*tau_2,
tau_4 = tau_2*tau_2;
//bf2 = bf3 = 0
bf1 = (66480.0*tau_4 - 206243.0*tau_3 + 237786.0*tau_2 - 124793.0*tau + 28800.0)/28800.0 ,
bf4 = -16.0*tau*(45312.0*tau_3 - 125933.0*tau_2 + 119706.0*tau -40973.0)/70785.0 ,
bf5 = -2187.0*tau*(19440.0*tau_3 - 45743.0*tau_2 + 34786.0*tau - 9293.0)/1645600.0 ,
bf6 = tau*(12864.0*tau_3 - 30653.0*tau_2 + 23786.0*tau - 6533.0)/705.0 ,
bf7 = -5764801.0*tau*(16464.0*tau_3 - 32797.0*tau_2 + 17574.0*tau - 1927.0)/7239323520.0 ,
bf8 = 37.0*tau*(336.0*tau_3 - 661.0*tau_2 + 342.0*tau -31.0)/1440.0 ,
bf9 = tau*(tau-1.0)*(16.0*tau_2 - 15.0*tau +3.0)/4.0 ,
bf10 = 8.0*tau*(tau - 1.0)*(tau - 1.0)*(2.0*tau - 1.0) ;
// bf2 = bf3 = 0.0
bf1 = (66480.0*tau_4-206243.0*tau_3+237786.0*tau_2-124793.0*tau+28800.0)
/ 28800.0 ;
bf4 = -16.0*tau*(45312.0*tau_3 - 125933.0*tau_2 + 119706.0*tau -40973.0)
/ 70785.0 ;
bf5 = -2187.0*tau*(19440.0*tau_3 - 45743.0*tau_2 + 34786.0*tau - 9293.0)
/ 1645600.0 ;
bf6 = tau*(12864.0*tau_3 - 30653.0*tau_2 + 23786.0*tau - 6533.0)
/ 705.0 ;
bf7 = -5764801.0*tau*(16464.0*tau_3 - 32797.0*tau_2 + 17574.0*tau - 1927.0)
/ 7239323520.0 ;
bf8 = 37.0*tau*(336.0*tau_3 - 661.0*tau_2 + 342.0*tau -31.0)
/ 1440.0 ;
bf9 = tau*(tau-1.0)*(16.0*tau_2 - 15.0*tau +3.0)
/ 4.0 ;
bf10 = 8.0*tau*(tau - 1.0)*(tau - 1.0)*(2.0*tau - 1.0) ;
for( int i=0; i<numberOfVariables; i++){
yOut[i] = yIn[i] + Step*tau*( bf1*dydx[i] + bf4*ak4[i] + bf5*ak5[i] +
bf6*ak6[i] + bf7*ak7[i] + bf8*ak8[i] +
bf9*ak9[i] + bf10*ak10_low[i] ) ;
}
}
for( G4int i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*tau*( bf1*dydx[i] + bf4*ak4[i] + bf5*ak5[i] +
bf6*ak6[i] + bf7*ak7[i] + bf8*ak8[i] +
bf9*ak9[i] + bf10*ak10_low[i] ) ;
}
}
//The following scheme and set of coefficients have been obtained from
//Table 2. Sixth order dense formula based on linear optimisation for RK6(5)9FM
//with extra stages C1O= 1/2, C11 =1/6, c12= 5/12
//---Ref---
// T. S. Baker, J. R. Dormand, J. P. Gilmore, and P. J. Prince,
// “Continuous approximation with embedded Runge-Kutta methods,”
// Applied Numerical Mathematics, vol. 22, no. 1, pp. 5162, 1996.
//--------------------
// --- Sixth order interpolant with 3 additional stages per step ---
//Function for calculating the additional stages :
// The following scheme and set of coefficients have been obtained from
// Table 2. Sixth order dense formula based on linear optimisation for
// RK6(5)9FM with extra stages C1O= 1/2, C11 =1/6, c12= 5/12
//
// T. S. Baker, J. R. Dormand, J. P. Gilmore, and P. J. Prince,
// "Continuous approximation with embedded Runge-Kutta methods"
// Applied Numerical Mathematics, vol. 22, no. 1, pp. 51-62, 1996.
//
// --- Sixth order interpolant with 3 additional stages per step ---
//
// Function for calculating the additional stages
//
void G4DormandPrinceRK56::SetupInterpolate_high( const G4double yInput[],
const G4double dydx[],
const G4double Step ){
const G4double dydx[],
const G4double Step )
{
// Coefficients for the additional stages
//
G4double b101 = 33797.0/460800.0 ,
b102 = 0.0 ,
b103 = 0.0 ,
b104 = 27757.0/70785.0 ,
b105 = 7923501.0/26329600.0 ,
b106 = -927.0/3760.0 ,
b107 = -3314760575.0/23165835264.0 ,
b108 = 2479.0/23040.0 ,
b109 = 1.0/64.0 ,
//Coefficients for the additional stages :
b111 = 5843.0/76800.0 ,
b112 = 0.0 ,
b113 = 0.0 ,
b114 = 464.0/2673.0 ,
b115 = 353997.0/1196800.0 ,
b116 = -15068.0/57105.0 ,
b117 = -282475249.0/3644974080.0 ,
b118 = 8678831.0/156245760.0 ,
b119 = 116113.0/11718432.0 ,
b1110 = -25.0/243.0 ,
G4double
b101 = 33797.0/460800.0 ,
b102 = 0.0 ,
b103 = 0.0 ,
b104 = 27757.0/70785.0 ,
b105 = 7923501.0/26329600.0 ,
b106 = -927.0/3760.0 ,
b107 = -3314760575.0/23165835264.0 ,
b108 = 2479.0/23040.0 ,
b109 = 1.0/64.0 ,
b121 = 15088049.0/199065600.0 ,
b122 = 0.0 ,
b123 = 0.0 ,
b124 = 2.0/5.0 ,
b125 = 92222037.0/268083200.0 ,
b126 = -433420501.0/1528586640.0 ,
b127 = -11549242677007.0/83630285291520.0 ,
b128 = 2725085557.0/26167173120.0 ,
b129 = 235429367.0/16354483200.0 ,
b1210 = -90924917.0/1040739840.0 ,
b1211 = -271149.0/21414400.0 ;
b111 = 5843.0/76800.0 ,
b112 = 0.0 ,
b113 = 0.0 ,
b114 = 464.0/2673.0 ,
b115 = 353997.0/1196800.0 ,
b116 = -15068.0/57105.0 ,
b117 = -282475249.0/3644974080.0 ,
b118 = 8678831.0/156245760.0 ,
b119 = 116113.0/11718432.0 ,
b1110 = -25.0/243.0 ,
const G4int numberOfVariables = GetNumberOfVariables();
b121 = 15088049.0/199065600.0 ,
b122 = 0.0 ,
b123 = 0.0 ,
b124 = 2.0/5.0 ,
b125 = 92222037.0/268083200.0 ,
b126 = -433420501.0/1528586640.0 ,
b127 = -11549242677007.0/83630285291520.0 ,
b128 = 2725085557.0/26167173120.0 ,
b129 = 235429367.0/16354483200.0 ,
b1210 = -90924917.0/1040739840.0 ,
b1211 = -271149.0/21414400.0 ;
const G4int numberOfVariables= this->GetNumberOfVariables();
// Saving yInput because yInput and yOut can be aliases for same array
for(int i=0;i<numberOfVariables;i++)
// Saving yInput because yInput and yOut can be aliases for same array
//
for(G4int i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
yIn[i]=yInput[i];
}
yTemp[7] = yIn[7];
//Evaluate the extra stages :
for(int i=0;i<numberOfVariables;i++)
// Evaluate the extra stages
//
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b101*dydx[i] + b102*ak2[i] + b103*ak3[i] +
b104*ak4[i] + b105*ak5[i] + b106*ak6[i] +
b107*ak7[i] + b108*ak8[i] + b109*ak9[i]);
}
RightHandSide(yTemp, ak10); //10th Stage
RightHandSide(yTemp, ak10); // 10th Stage
for(int i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b111*dydx[i] + b112*ak2[i] + b113*ak3[i] +
b114*ak4[i] + b115*ak5[i] + b116*ak6[i] +
b117*ak7[i] + b118*ak8[i] + b119*ak9[i] +
b1110*ak10[i]);
}
RightHandSide(yTemp, ak11); //11th Stage
RightHandSide(yTemp, ak11); // 11th Stage
for(int i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b121*dydx[i] + b122*ak2[i] + b123*ak3[i] +
b124*ak4[i] + b125*ak5[i] + b126*ak6[i] +
b127*ak7[i] + b128*ak8[i] + b129*ak9[i] +
b1210*ak10[i] + b1211*ak11[i]);
}
RightHandSide(yTemp, ak12); //12th Stage
RightHandSide(yTemp, ak12); // 12th Stage
}
//Function to interpolate to tau(passed in) fraction of the step
// Function to interpolate to tau(passed in) fraction of the step
//
void G4DormandPrinceRK56::Interpolate_high( const G4double yInput[],
const G4double dydx[],
const G4double Step,
G4double yOut[],
G4double tau )
const G4double dydx[],
const G4double Step,
G4double yOut[],
G4double tau )
{
//Define the coefficients for the polynomials
// Define the coefficients for the polynomials
//
G4double bi[13][6], b[13];
G4int numberOfVariables = this->GetNumberOfVariables();
G4int numberOfVariables = GetNumberOfVariables();
// COEFFICIENTS OF bi[ 1]
bi[1][0] = 1.0 ,
bi[1][1] = -18487.0/2880.0 ,
@@ -720,31 +686,34 @@ void G4DormandPrinceRK56::Interpolate_high( const G4double yInput[],
bi[12][5] = -13824.0/175.0 ;
// --------------------------------------------------------
for(G4int i = 0; i< numberOfVariables; i++)
for(G4int i = 0; i< numberOfVariables; ++i)
{
yIn[i] = yInput[i];
}
G4double tau0 = tau;
// Calculating the polynomials (coefficents for the respective stages) :
for(int i=1; i<=12; i++){ //Here i is NOT the coordinate no. , it's stage no.
// Calculating the polynomials (coefficents for the respective stages) :
//
for(auto i=1; i<=12; ++i) // i is NOT the coordinate no., it's stage no.
{
b[i] = 0;
tau = 1.0;
for(int j=0; j<=5; j++){
for(auto j=0; j<=5; ++j)
{
b[i] += bi[i][j]*tau;
tau*=tau0;
}
}
// Calculating the interpolation at the fraction tau of the step using the polynomial
// coefficients and the respective stages
for(int i=0; i<numberOfVariables; i++){ //Here i IS the cooridnate no.
yOut[i] = yIn[i] + Step*tau0*(b[1]*dydx[i] + b[2]*ak2[i] + b[3]*ak3[i] +
b[4]*ak4[i] + b[5]*ak5[i] + b[6]*ak6[i] +
b[7]*ak7[i] + b[8]*ak8[i] + b[9]*ak9[i] +
// Calculating the interpolation at the fraction tau of the step using
// the polynomial coefficients and the respective stages
//
for(G4int i=0; i<numberOfVariables; ++i) // Here i IS the coordinate no.
{
yOut[i] = yIn[i] + Step*tau0*(b[1]*dydx[i] + b[2]*ak2[i] + b[3]*ak3[i] +
b[4]*ak4[i] + b[5]*ak5[i] + b[6]*ak6[i] +
b[7]*ak7[i] + b[8]*ak8[i] + b[9]*ak9[i] +
b[10]*ak10[i] + b[11]*ak11[i] + b[12]*ak12[i]);
}
}
//-----Verified--------- - hackabot
@@ -23,41 +23,33 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Dormand-Prince 8(7)13M non-FSAL implementation by Somnath Banerjee
// Supported by Google as part of Google Summer of Code 2015.
// Supervision / code review: John Apostolakis
// G4DormandPrinceRK78 implementation
//
// First version: 28 June 2015
// Dormand-Prince 8(7)13M non-FSAL, based on RK scheme from:
// P.J. Prince, J.R. Dormand, "High order embedded Runge-Kutta formulae",
// Journal of Computational and Applied Mathematics, Volume 7, Issue 1, 1981,
// Pages 67-75, ISSN 0377-0427, DOI: 10.1016/0771-050X(81)90010-3
//
// Paper proposing this RK scheme:
// Title: "High order embedded Runge-Kutta formulae",
// Authors: P.J. Prince, J.R. Dormand
// Journal of Computational and Applied Mathematics, Volume 7, Issue 1, 1981,
// Pages 67-75, ISSN 0377-0427,
// Reference: DOI: 10.1016/0771-050X(81)90010-3
// http://dx.doi.org/10.1016/0771-050X(81)90010-3.
// (http://www.sciencedirect.com/science/article/pii/0771050X81900103)
//
// History (condensed)
// -----------------------------
// 28 June 2015: First version created - S. Banerjee
// 4 July 2017: Small fixes (Coverity issues) - J. Apostolakis
// Created: Somnath Banerjee, Google Summer of Code 2015, 28 June 2015
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4DormandPrinceRK78.hh"
#include "G4LineSection.hh"
//Constructor
G4DormandPrinceRK78::G4DormandPrinceRK78(G4EquationOfMotion *EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables),
fLastStepLength(-1.0), fAuxStepper(nullptr)
// Constructor
//
G4DormandPrinceRK78::G4DormandPrinceRK78(G4EquationOfMotion* EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables)
{
const G4int numberOfVariables = noIntegrationVariables;
//New Chunk of memory being created for use by the stepper
// New Chunk of memory being created for use by the stepper
//aki - for storing intermediate RHS
// aki - for storing intermediate RHS
//
ak2 = new G4double[numberOfVariables];
ak3 = new G4double[numberOfVariables];
ak4 = new G4double[numberOfVariables];
@@ -85,303 +77,299 @@ G4DormandPrinceRK78::G4DormandPrinceRK78(G4EquationOfMotion *EqRhs,
if( primary )
{
fAuxStepper = new G4DormandPrinceRK78(EqRhs, numberOfVariables,
!primary);
fAuxStepper = new G4DormandPrinceRK78(EqRhs, numberOfVariables, !primary);
}
}
//Destructor
G4DormandPrinceRK78::~G4DormandPrinceRK78(){
//clear all previously allocated memory for stepper and DistChord
delete[] ak2;
delete[] ak3;
delete[] ak4;
delete[] ak5;
delete[] ak6;
delete[] ak7;
delete[] ak8;
delete[] ak9;
delete[] ak10;
delete[] ak11;
delete[] ak12;
delete[] ak13;
delete[] yTemp;
delete[] yIn;
// Destructor
//
G4DormandPrinceRK78::~G4DormandPrinceRK78()
{
// Clear all previously allocated memory for stepper and DistChord
delete [] ak2;
delete [] ak3;
delete [] ak4;
delete [] ak5;
delete [] ak6;
delete [] ak7;
delete [] ak8;
delete [] ak9;
delete [] ak10;
delete [] ak11;
delete [] ak12;
delete [] ak13;
delete [] yTemp;
delete [] yIn;
delete[] fLastInitialVector;
delete[] fLastFinalVector;
delete[] fLastDyDx;
delete[] fMidVector;
delete[] fMidError;
delete [] fLastInitialVector;
delete [] fLastFinalVector;
delete [] fLastDyDx;
delete [] fMidVector;
delete [] fMidError;
delete fAuxStepper;
}
// The following scheme and the set of coefficients have been obtained from
//Table2. RK8(7)13M (Rational approximations
//---Ref---
// P. J. Prince and J. R. Dormand, “High order embedded Runge-Kutta formulae,”
// Journal of Computational and Applied Mathematics,
// vol. 7, no. 1, pp. 6775, Dec. 1980.
//------------------------------
//Stepper :
// The following scheme and the set of coefficients have been obtained from
// Table2. RK8(7)13M (Rational approximations) from:
// P. J. Prince and J. R. Dormand, "High order embedded Runge-Kutta formulae"
// Journal of Computational and Applied Math., vol.7, no.1, pp.67-75, 1980.
//
// Stepper :
//
// Passing in the value of yInput[],the first time dydx[] and Step length
// Giving back yOut and yErr arrays for output and error respectively
//
void G4DormandPrinceRK78::Stepper(const G4double yInput[],
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[])
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[])
{
G4int i;
//The various constants defined on the basis of butcher tableu
//G4double - only once
const G4double
// The various constants defined on the basis of butcher tableu
//
const G4double b21 = 1.0/18,
b31 = 1.0/48.0 ,
b32 = 1.0/16.0 ,
b21 = 1.0/18,
b41 = 1.0/32.0 ,
b42 = 0.0 ,
b43 = 3.0/32.0 ,
b31 = 1.0/48.0 ,
b32 = 1.0/16.0 ,
b51 = 5.0/16.0 ,
b52 = 0.0 ,
b53 = -75.0/64.0 ,
b54 = 75.0/64.0 ,
b41 = 1.0/32.0 ,
b42 = 0.0 ,
b43 = 3.0/32.0 ,
b61 = 3.0/80.0 ,
b62 = 0.0 ,
b63 = 0.0 ,
b64 = 3.0/16.0 ,
b65 = 3.0/20.0 ,
b51 = 5.0/16.0 ,
b52 = 0.0 ,
b53 = -75.0/64.0 ,
b54 = 75.0/64.0 ,
b71 = 29443841.0/614563906.0 ,
b72 = 0.0 ,
b73 = 0.0 ,
b74 = 77736538.0/692538347.0 ,
b75 = -28693883.0/1125000000.0 ,
b76 = 23124283.0/1800000000.0 ,
b61 = 3.0/80.0 ,
b62 = 0.0 ,
b63 = 0.0 ,
b64 = 3.0/16.0 ,
b65 = 3.0/20.0 ,
b81 = 16016141.0/946692911.0 ,
b82 = 0.0 ,
b83 = 0.0 ,
b84 = 61564180.0/158732637.0 ,
b85 = 22789713.0/633445777.0 ,
b86 = 545815736.0/2771057229.0 ,
b87 = -180193667.0/1043307555.0 ,
b71 = 29443841.0/614563906.0 ,
b72 = 0.0 ,
b73 = 0.0 ,
b74 = 77736538.0/692538347.0 ,
b75 = -28693883.0/1125000000.0 ,
b76 = 23124283.0/1800000000.0 ,
b91 = 39632708.0/573591083.0 ,
b92 = 0.0 ,
b93 = 0.0 ,
b94 = -433636366.0/683701615.0 ,
b95 = -421739975.0/2616292301.0 ,
b96 = 100302831.0/723423059.0 ,
b97 = 790204164.0/839813087.0 ,
b98 = 800635310.0/3783071287.0 ,
b81 = 16016141.0/946692911.0 ,
b82 = 0.0 ,
b83 = 0.0 ,
b84 = 61564180.0/158732637.0 ,
b85 = 22789713.0/633445777.0 ,
b86 = 545815736.0/2771057229.0 ,
b87 = -180193667.0/1043307555.0 ,
b101 = 246121993.0/1340847787.0 ,
b102 = 0.0 ,
b103 = 0.0 ,
b104 = -37695042795.0/15268766246.0 ,
b105 = -309121744.0/1061227803.0 ,
b106 = -12992083.0/490766935.0 ,
b107 = 6005943493.0/2108947869.0 ,
b108 = 393006217.0/1396673457.0 ,
b109 = 123872331.0/1001029789.0 ,
b91 = 39632708.0/573591083.0 ,
b92 = 0.0 ,
b93 = 0.0 ,
b94 = -433636366.0/683701615.0 ,
b95 = -421739975.0/2616292301.0 ,
b96 = 100302831.0/723423059.0 ,
b97 = 790204164.0/839813087.0 ,
b98 = 800635310.0/3783071287.0 ,
b111 = -1028468189.0/846180014.0 ,
b112 = 0.0 ,
b113 = 0.0 ,
b114 = 8478235783.0/508512852.0 ,
b115 = 1311729495.0/1432422823.0 ,
b116 = -10304129995.0/1701304382.0 ,
b117 = -48777925059.0/3047939560.0 ,
b118 = 15336726248.0/1032824649.0 ,
b119 = -45442868181.0/3398467696.0 ,
b1110 = 3065993473.0/597172653.0 ,
b101 = 246121993.0/1340847787.0 ,
b102 = 0.0 ,
b103 = 0.0 ,
b104 = -37695042795.0/15268766246.0 ,
b105 = -309121744.0/1061227803.0 ,
b106 = -12992083.0/490766935.0 ,
b107 = 6005943493.0/2108947869.0 ,
b108 = 393006217.0/1396673457.0 ,
b109 = 123872331.0/1001029789.0 ,
b121 = 185892177.0/718116043.0 ,
b122 = 0.0 ,
b123 = 0.0 ,
b124 = -3185094517.0/667107341.0 ,
b125 = -477755414.0/1098053517.0 ,
b126 = -703635378.0/230739211.0 ,
b127 = 5731566787.0/1027545527.0 ,
b128 = 5232866602.0/850066563.0 ,
b129 = -4093664535.0/808688257.0 ,
b1210 = 3962137247.0/1805957418.0 ,
b1211 = 65686358.0/487910083.0 ,
b111 = -1028468189.0/846180014.0 ,
b112 = 0.0 ,
b113 = 0.0 ,
b114 = 8478235783.0/508512852.0 ,
b115 = 1311729495.0/1432422823.0 ,
b116 = -10304129995.0/1701304382.0 ,
b117 = -48777925059.0/3047939560.0 ,
b118 = 15336726248.0/1032824649.0 ,
b119 = -45442868181.0/3398467696.0 ,
b1110 = 3065993473.0/597172653.0 ,
b131 = 403863854.0/491063109.0 ,
b132 = 0.0 ,
b133 = 0.0 ,
b134 = -5068492393.0/434740067.0 ,
b135 = -411421997.0/543043805.0 ,
b136 = 652783627.0/914296604.0 ,
b137 = 11173962825.0/925320556.0 ,
b138 = -13158990841.0/6184727034.0 ,
b139 = 3936647629.0/1978049680.0 ,
b1310 = -160528059.0/685178525.0 ,
b1311 = 248638103.0/1413531060.0 ,
b1312 = 0.0 ,
b121 = 185892177.0/718116043.0 ,
b122 = 0.0 ,
b123 = 0.0 ,
b124 = -3185094517.0/667107341.0 ,
b125 = -477755414.0/1098053517.0 ,
b126 = -703635378.0/230739211.0 ,
b127 = 5731566787.0/1027545527.0 ,
b128 = 5232866602.0/850066563.0 ,
b129 = -4093664535.0/808688257.0 ,
b1210 = 3962137247.0/1805957418.0 ,
b1211 = 65686358.0/487910083.0 ,
c1 = 14005451.0/335480064.0 ,
// c2 = 0.0 ,
// c3 = 0.0 ,
// c4 = 0.0 ,
// c5 = 0.0 ,
c6 = -59238493.0/1068277825.0 ,
c7 = 181606767.0/758867731.0 ,
c8 = 561292985.0/797845732.0 ,
c9 = -1041891430.0/1371343529.0 ,
c10 = 760417239.0/1151165299.0 ,
c11 = 118820643.0/751138087.0 ,
c12 = - 528747749.0/2220607170.0 ,
c13 = 1.0/4.0 ,
b131 = 403863854.0/491063109.0 ,
b132 = 0.0 ,
b133 = 0.0 ,
b134 = -5068492393.0/434740067.0 ,
b135 = -411421997.0/543043805.0 ,
b136 = 652783627.0/914296604.0 ,
b137 = 11173962825.0/925320556.0 ,
b138 = -13158990841.0/6184727034.0 ,
b139 = 3936647629.0/1978049680.0 ,
b1310 = -160528059.0/685178525.0 ,
b1311 = 248638103.0/1413531060.0 ,
b1312 = 0.0 ,
c_1 = 13451932.0/455176623.0 ,
// c_2 = 0.0 ,
// c_3 = 0.0 ,
// c_4 = 0.0 ,
// c_5 = 0.0 ,
c_6 = -808719846.0/976000145.0 ,
c_7 = 1757004468.0/5645159321.0 ,
c_8 = 656045339.0/265891186.0 ,
c_9 = -3867574721.0/1518517206.0 ,
c_10 = 465885868.0/322736535.0 ,
c_11 = 53011238.0/667516719.0 ,
c_12 = 2.0/45.0 ,
c_13 = 0.0 ,
c1 = 14005451.0/335480064.0 ,
// c2 = 0.0 ,
// c3 = 0.0 ,
// c4 = 0.0 ,
// c5 = 0.0 ,
c6 = -59238493.0/1068277825.0 ,
c7 = 181606767.0/758867731.0 ,
c8 = 561292985.0/797845732.0 ,
c9 = -1041891430.0/1371343529.0 ,
c10 = 760417239.0/1151165299.0 ,
c11 = 118820643.0/751138087.0 ,
c12 = - 528747749.0/2220607170.0 ,
c13 = 1.0/4.0 ,
dc1 = c_1 - c1 ,
// dc2 = c_2 - c2 ,
// dc3 = c_3 - c3 ,
// dc4 = c_4 - c4 ,
// dc5 = c_5 - c5 ,
dc6 = c_6 - c6 ,
dc7 = c_7 - c7 ,
dc8 = c_8 - c8 ,
dc9 = c_9 - c9 ,
dc10 = c_10 - c10 ,
dc11 = c_11 - c11 ,
dc12 = c_12 - c12 ,
dc13 = c_13 - c13 ;
//
// end of declaration !
c_1 = 13451932.0/455176623.0 ,
// c_2 = 0.0 ,
// c_3 = 0.0 ,
// c_4 = 0.0 ,
// c_5 = 0.0 ,
c_6 = -808719846.0/976000145.0 ,
c_7 = 1757004468.0/5645159321.0 ,
c_8 = 656045339.0/265891186.0 ,
c_9 = -3867574721.0/1518517206.0 ,
c_10 = 465885868.0/322736535.0 ,
c_11 = 53011238.0/667516719.0 ,
c_12 = 2.0/45.0 ,
c_13 = 0.0 ,
dc1 = c_1 - c1 ,
// dc2 = c_2 - c2 ,
// dc3 = c_3 - c3 ,
// dc4 = c_4 - c4 ,
// dc5 = c_5 - c5 ,
dc6 = c_6 - c6 ,
dc7 = c_7 - c7 ,
dc8 = c_8 - c8 ,
dc9 = c_9 - c9 ,
dc10 = c_10 - c10 ,
dc11 = c_11 - c11 ,
dc12 = c_12 - c12 ,
dc13 = c_13 - c13 ;
//end of declaration !
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
// The number of variables to be integrated over
//
yOut[7] = yTemp[7] = yIn[7] = yInput[7];
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<numberOfVariables;i++)
// Saving yInput because yInput and yOut can be aliases for same array
//
for(i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
}
// RightHandSide(yIn, dydx) ; // 1st Stage - Not doing, getting passed
// RightHandSide(yIn, dydx) ;
// 1st Stage - Not doing, getting passed
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + b21*Step*dydx[i] ;
}
RightHandSide(yTemp, ak2) ; // 2nd Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b31*dydx[i] + b32*ak2[i]) ;
}
RightHandSide(yTemp, ak3) ; // 3rd Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b41*dydx[i] + b42*ak2[i] + b43*ak3[i]) ;
}
RightHandSide(yTemp, ak4) ; // 4th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b51*dydx[i] + b52*ak2[i] + b53*ak3[i] +
b54*ak4[i]) ;
}
RightHandSide(yTemp, ak5) ; // 5th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b61*dydx[i] + b62*ak2[i] + b63*ak3[i] +
b64*ak4[i] + b65*ak5[i]) ;
}
RightHandSide(yTemp, ak6) ; // 6th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b71*dydx[i] + b72*ak2[i] + b73*ak3[i] +
b74*ak4[i] + b75*ak5[i] + b76*ak6[i]);
}
RightHandSide(yTemp, ak7); //7th Stage
RightHandSide(yTemp, ak7); // 7th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b81*dydx[i] + b82*ak2[i] + b83*ak3[i] +
b84*ak4[i] + b85*ak5[i] + b86*ak6[i] +
b87*ak7[i]);
}
RightHandSide(yTemp, ak8); //8th Stage
RightHandSide(yTemp, ak8); // 8th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b91*dydx[i] + b92*ak2[i] + b93*ak3[i] +
b94*ak4[i] + b95*ak5[i] + b96*ak6[i] +
b97*ak7[i] + b98*ak8[i] );
}
RightHandSide(yTemp, ak9); //9th Stage
RightHandSide(yTemp, ak9); // 9th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b101*dydx[i] + b102*ak2[i] + b103*ak3[i] +
b104*ak4[i] + b105*ak5[i] + b106*ak6[i] +
b107*ak7[i] + b108*ak8[i] + b109*ak9[i]);
}
RightHandSide(yTemp, ak10); //10th Stage
RightHandSide(yTemp, ak10); // 10th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b111*dydx[i] + b112*ak2[i] + b113*ak3[i] +
b114*ak4[i] + b115*ak5[i] + b116*ak6[i] +
b117*ak7[i] + b118*ak8[i] + b119*ak9[i] +
b1110*ak10[i]);
}
RightHandSide(yTemp, ak11); //11th Stage
RightHandSide(yTemp, ak11); // 11th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b121*dydx[i] + b122*ak2[i] + b123*ak3[i] +
b124*ak4[i] + b125*ak5[i] + b126*ak6[i] +
b127*ak7[i] + b128*ak8[i] + b129*ak9[i] +
b1210*ak10[i] + b1211*ak11[i]);
}
RightHandSide(yTemp, ak12); //12th Stage
RightHandSide(yTemp, ak12); // 12th Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b131*dydx[i] + b132*ak2[i] + b133*ak3[i] +
b134*ak4[i] + b135*ak5[i] + b136*ak6[i] +
b137*ak7[i] + b138*ak8[i] + b139*ak9[i] +
b1310*ak10[i] + b1311*ak11[i] + b1312*ak12[i]);
yTemp[i] = yIn[i]+Step*(b131*dydx[i] + b132*ak2[i] + b133*ak3[i] +
b134*ak4[i] + b135*ak5[i] + b136*ak6[i] +
b137*ak7[i] + b138*ak8[i] + b139*ak9[i] +
b1310*ak10[i] + b1311*ak11[i] + b1312*ak12[i]);
}
RightHandSide(yTemp, ak13); //13th and final Stage
RightHandSide(yTemp, ak13); // 13th and final Stage
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
// Accumulate increments with proper weights
@@ -391,36 +379,35 @@ void G4DormandPrinceRK78::Stepper(const G4double yInput[],
c7*ak7[i] + c8*ak8[i] +c9*ak9[i] + c10*ak10[i]
+ c11*ak11[i] + c12*ak12[i] + c13*ak13[i]) ;
// Estimate error as difference between 7th and
// 8th order methods
// Estimate error as difference between 7th and 8th order methods
//
yErr[i] = Step*(dc1*dydx[i] + // dc2*ak2[i] + dc3*ak3[i] + dc4*ak4[i]
// + dc5*ak5[i]
+ dc6*ak6[i] + dc7*ak7[i] + dc8*ak8[i]
+ dc9*ak9[i] + dc10*ak10[i] + dc11*ak11[i] + dc12*ak12[i]
+ dc13*ak13[i] ) ;
+ dc6*ak6[i] + dc7*ak7[i] + dc8*ak8[i]
+ dc9*ak9[i] + dc10*ak10[i] + dc11*ak11[i] + dc12*ak12[i]
+ dc13*ak13[i] ) ;
// Store Input and Final values, for possible use in calculating chord
//
fLastInitialVector[i] = yIn[i] ;
fLastFinalVector[i] = yOut[i];
fLastDyDx[i] = dydx[i];
}
fLastStepLength = Step;
return ;
}
//The DistChord() function fot the class - must define it here.
// DistChord
//
G4double G4DormandPrinceRK78::DistChord() const
{
G4double distLine, distChord;
G4ThreeVector initialPoint, finalPoint, midPoint;
// Store last initial and final points (they will be overwritten in self-Stepper call!)
// Store last initial and final points
// (they will be overwritten in self-Stepper call!)
//
initialPoint = G4ThreeVector( fLastInitialVector[0],
fLastInitialVector[1], fLastInitialVector[2]);
finalPoint = G4ThreeVector( fLastFinalVector[0],
@@ -434,12 +421,11 @@ G4double G4DormandPrinceRK78::DistChord() const
midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2]);
// Use stored values of Initial and Endpoint + new Midpoint to evaluate
// distance of Chord
// distance of Chord
//
if (initialPoint != finalPoint)
{
distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
distLine = G4LineSection::Distline(midPoint, initialPoint, finalPoint);
distChord = distLine;
}
else
@@ -448,9 +434,3 @@ G4double G4DormandPrinceRK78::DistChord() const
}
return distChord;
}
//------Verified------- - hackabot
@@ -23,8 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ElectricField implementation
//
//
// Created: J.Apostolakis - 04.11.2003
// --------------------------------------------------------------------
#include "G4ElectricField.hh"
@@ -37,12 +38,12 @@ G4ElectricField::~G4ElectricField()
{
}
G4ElectricField::G4ElectricField(const G4ElectricField &p)
G4ElectricField::G4ElectricField(const G4ElectricField& p)
: G4ElectroMagneticField(p)
{
}
G4ElectricField& G4ElectricField::operator = (const G4ElectricField &p)
G4ElectricField& G4ElectricField::operator = (const G4ElectricField& p)
{
if (&p == this) return *this;
G4ElectroMagneticField::operator=(p);
@@ -23,8 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ElectroMagneticField implementation
//
//
// Created: J.Apostolakis, 12.11.1998
// --------------------------------------------------------------------
#include "G4ElectroMagneticField.hh"
@@ -38,13 +39,13 @@ G4ElectroMagneticField::~G4ElectroMagneticField()
{
}
G4ElectroMagneticField::G4ElectroMagneticField(const G4ElectroMagneticField &r)
G4ElectroMagneticField::G4ElectroMagneticField(const G4ElectroMagneticField& r)
: G4Field( r ) // To allow extension to joint EM & g field
{
}
G4ElectroMagneticField&
G4ElectroMagneticField::operator = (const G4ElectroMagneticField &p)
G4ElectroMagneticField::operator = (const G4ElectroMagneticField& p)
{
if (&p == this) return *this;
G4Field::operator=(p);
@@ -23,15 +23,13 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// G4EqEMFieldWithEDM implementation
//
// This is the standard right-hand side for equation of motion.
//
// 19.02.2009 Kevin Lynch, based on G4EqEMFieldWithSpin
// 06.11.2009 Hiromi Iinuma see:
// http://hypernews.slac.stanford.edu/HyperNews/geant4/get/emfields/161.html
//
// Created: Kevin Lynch, 19.02.2009 - Based on G4EqEMFieldWithSpin
// Modified: Hiromi Iinuma, 06.11.2009 - see:
// http://hypernews.slac.stanford.edu/HyperNews/geant4/get/emfields/161.html
// -------------------------------------------------------------------
#include "G4EqEMFieldWithEDM.hh"
@@ -41,7 +39,7 @@
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
G4EqEMFieldWithEDM::G4EqEMFieldWithEDM(G4ElectroMagneticField *emField )
G4EqEMFieldWithEDM::G4EqEMFieldWithEDM(G4ElectroMagneticField* emField )
: G4EquationOfMotion( emField ), charge(0.), mass(0.), magMoment(0.),
spin(0.), fElectroMagCof(0.), fMassCof(0.), omegac(0.),
anomaly(0.0011659208), eta(0.), beta(0.), gamma(0.)
@@ -57,7 +55,7 @@ G4EqEMFieldWithEDM::SetChargeMomentumMass(G4ChargeState particleCharge,
G4double MomentumXc,
G4double particleMass)
{
charge = particleCharge.GetCharge();
charge = particleCharge.GetCharge();
mass = particleMass;
magMoment = particleCharge.GetMagneticDipoleMoment();
spin = particleCharge.GetSpin();
@@ -82,8 +80,8 @@ G4EqEMFieldWithEDM::SetChargeMomentumMass(G4ChargeState particleCharge,
void
G4EqEMFieldWithEDM::EvaluateRhsGivenB(const G4double y[],
const G4double Field[],
G4double dydx[] ) const
const G4double Field[],
G4double dydx[] ) const
{
// Components of y:
@@ -158,9 +156,9 @@ G4EqEMFieldWithEDM::EvaluateRhsGivenB(const G4double y[],
else pcharge = charge;
G4ThreeVector dSpin(0.,0.,0.);
if (Spin.mag2() != 0.) {
dSpin =
pcharge*omegac*( ucb*(Spin.cross(BField))-udb*(Spin.cross(u))
if (Spin.mag2() != 0.)
{
dSpin = pcharge*omegac*( ucb*(Spin.cross(BField))-udb*(Spin.cross(u))
// from Jackson
// -uce*Spin.cross(u.cross(EField)) )
// but this form has one less operation
@@ -174,5 +172,5 @@ G4EqEMFieldWithEDM::EvaluateRhsGivenB(const G4double y[],
dydx[10] = dSpin.y();
dydx[11] = dSpin.z();
return ;
return;
}
@@ -23,15 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4EqEMFieldWithSpin implementation
//
//
//
// This is the standard right-hand side for equation of motion.
//
// 30.08.2007 Chris Gong, Peter Gumplinger
// 14.02.2009 Kevin Lynch
// 06.11.2009 Hiromi Iinuma
//
// Created: Chris Gong & Peter Gumplinger, 30.08.2007
// -------------------------------------------------------------------
#include "G4EqEMFieldWithSpin.hh"
@@ -54,8 +48,8 @@ G4EqEMFieldWithSpin::~G4EqEMFieldWithSpin()
void
G4EqEMFieldWithSpin::SetChargeMomentumMass(G4ChargeState particleCharge,
G4double MomentumXc,
G4double particleMass)
G4double MomentumXc,
G4double particleMass)
{
charge = particleCharge.GetCharge();
mass = particleMass;
@@ -112,7 +106,7 @@ G4EqEMFieldWithSpin::EvaluateRhsGivenB(const G4double y[],
G4double inverse_velocity = Energy * pModuleInverse / c_light;
G4double cof1 = fElectroMagCof*pModuleInverse ;
G4double cof1 = fElectroMagCof*pModuleInverse ;
dydx[0] = y[3]*pModuleInverse ;
dydx[1] = y[4]*pModuleInverse ;
@@ -144,13 +138,19 @@ G4EqEMFieldWithSpin::EvaluateRhsGivenB(const G4double y[],
G4ThreeVector Spin(y[9],y[10],y[11]);
G4double pcharge;
if (charge == 0.) pcharge = 1.;
else pcharge = charge;
if (charge == 0.)
{
pcharge = 1.;
}
else
{
pcharge = charge;
}
G4ThreeVector dSpin(0.,0.,0.);
if (Spin.mag2() != 0.) {
dSpin =
pcharge*omegac*( ucb*(Spin.cross(BField))-udb*(Spin.cross(u))
if (Spin.mag2() != 0.)
{
dSpin = pcharge*omegac*( ucb*(Spin.cross(BField))-udb*(Spin.cross(u))
// from Jackson
// -uce*Spin.cross(u.cross(EField)) );
// but this form has one less operation
@@ -161,5 +161,5 @@ G4EqEMFieldWithSpin::EvaluateRhsGivenB(const G4double y[],
dydx[10] = dSpin.y();
dydx[11] = dSpin.z();
return ;
return;
}
@@ -23,23 +23,28 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4EqGravityField implementation
//
// This is the right-hand side for equation of motion for a
// massive particle in a gravitational field.
// This is the right-hand side for equation of motion for a
// massive particle in a gravitational field.
//
// History:
// - 14.06.11 P.Gumplinger, Created.
// -------------------------------------------------------------------
// Adopted from G4EqMagElectricField.hh
//
// Thanks to Peter Fierlinger (PSI) and
// A. Capra and A. Fontana (INFN Pavia)
// Created: P.Gumplinger, 14.06.11 - Adopted from G4EqMagElectricField
// Thanks to P.Fierlinger (PSI) and A.Capra and A.Fontana (INFN Pavia)
// -------------------------------------------------------------------
#include "G4EqGravityField.hh"
#include "globals.hh"
#include "G4PhysicalConstants.hh"
G4EqGravityField::G4EqGravityField(G4UniformGravityField* gField)
: G4EquationOfMotion( gField )
{
}
G4EqGravityField::~G4EqGravityField()
{
}
void
G4EqGravityField::SetChargeMomentumMass(G4ChargeState,
G4double,
@@ -51,7 +56,7 @@ G4EqGravityField::SetChargeMomentumMass(G4ChargeState,
void
G4EqGravityField::EvaluateRhsGivenB(const G4double y[],
const G4double G[],
G4double dydx[] ) const
G4double dydx[] ) const
{
// Components of y:
@@ -75,6 +80,7 @@ G4EqGravityField::EvaluateRhsGivenB(const G4double y[],
dydx[5] = G[2]*cof1*cof2/c_light;
// Lab Time of flight
//
dydx[7] = inverse_velocity;
return;
@@ -23,17 +23,15 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4EqMagElectricField implementation
//
// 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,
// e.g., an electric field
//
// 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
//
// Created: V.Grichine, 10.11.1998
// -------------------------------------------------------------------
#include "G4EqMagElectricField.hh"
@@ -41,9 +39,18 @@
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
G4EqMagElectricField::G4EqMagElectricField(G4ElectroMagneticField* emField )
: G4EquationOfMotion( emField )
{
}
G4EqMagElectricField::~G4EqMagElectricField()
{
}
void
G4EqMagElectricField::SetChargeMomentumMass(G4ChargeState particleCharge,
G4double,
G4double,
G4double particleMass)
{
G4double pcharge = particleCharge.GetCharge();
@@ -51,14 +58,11 @@ G4EqMagElectricField::SetChargeMomentumMass(G4ChargeState particleCharge,
fMassCof = particleMass*particleMass ;
}
void
G4EqMagElectricField::EvaluateRhsGivenB(const G4double y[],
const G4double Field[],
G4double dydx[] ) const
const G4double Field[],
G4double dydx[] ) const
{
// Components of y:
// 0-2 dr/ds,
// 3-5 dp/ds - momentum derivatives
@@ -70,14 +74,10 @@ G4EqMagElectricField::EvaluateRhsGivenB(const G4double y[],
G4double pModuleInverse = 1.0/std::sqrt(pSquared) ;
// G4double inverse_velocity = Energy * c_light * pModuleInverse;
G4double inverse_velocity = Energy * pModuleInverse / c_light;
G4double cof1 = fElectroMagCof*pModuleInverse ;
// G4double vDotE = y[3]*Field[3] + y[4]*Field[4] + y[5]*Field[5] ;
dydx[0] = y[3]*pModuleInverse ;
dydx[1] = y[4]*pModuleInverse ;
dydx[2] = y[5]*pModuleInverse ;
@@ -91,6 +91,8 @@ G4EqMagElectricField::EvaluateRhsGivenB(const G4double y[],
dydx[6] = 0.;//not used
// Lab Time of flight
//
dydx[7] = inverse_velocity;
return ;
return;
}
@@ -23,36 +23,18 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4EquationOfMotion implementation
//
//
// Created: J.Apostolakis, 1998
// -------------------------------------------------------------------
#include "G4EquationOfMotion.hh"
G4EquationOfMotion::G4EquationOfMotion(G4Field* pField)
: itsField(pField)
{
}
G4EquationOfMotion::~G4EquationOfMotion()
{}
void
G4EquationOfMotion::EvaluateRhsReturnB( const G4double y[],
G4double dydx[],
G4double Field[] ) const
{
G4double PositionAndTime[4];
// Position
PositionAndTime[0] = y[0];
PositionAndTime[1] = y[1];
PositionAndTime[2] = y[2];
// Global Time
PositionAndTime[3] = y[7]; // See G4FieldTrack::LoadFromArray
GetFieldValue(PositionAndTime, Field) ;
EvaluateRhsGivenB( y, Field, dydx );
}
#if HELP_THE_COMPILER
void
G4EquationOfMotion::doNothing()
{
}
#endif
@@ -23,11 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ErrorMag_UsualEqRhs implementation
//
//
//
// --------------------------------------------------------------------
// GEANT 4 class implementation file
// Created: P.Arce, September 2004.
// --------------------------------------------------------------------
#include "G4ErrorMag_UsualEqRhs.hh"
@@ -45,6 +43,7 @@ G4ErrorMag_UsualEqRhs::~G4ErrorMag_UsualEqRhs()
}
//---------------------------------------------------------------------
void
G4ErrorMag_UsualEqRhs::EvaluateRhsGivenB( const G4double y[],
const G4double B[3],
@@ -23,17 +23,10 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ExactHelixStepper implementation
//
//
// Helix a-la-Explicity Euler: x_1 = x_0 + helix(h)
// with helix(h) being a helix piece of length h
// simplest approach for solving linear differential equations.
// Take the current derivative and add it to the current position.
//
// As the field is assumed constant, an error is not calculated.
//
// Author: J. Apostolakis, 28 Jan 2005
// Implementation adapted from ExplicitEuler of W.Wander
// Author: J.Apostolakis, 28.01.2005.
// Implementation adapted from ExplicitEuler by W.Wander
// -------------------------------------------------------------------
#include "G4ExactHelixStepper.hh"
@@ -41,46 +34,50 @@
#include "G4ThreeVector.hh"
#include "G4LineSection.hh"
G4ExactHelixStepper::G4ExactHelixStepper(G4Mag_EqRhs *EqRhs)
G4ExactHelixStepper::G4ExactHelixStepper(G4Mag_EqRhs* EqRhs)
: G4MagHelicalStepper(EqRhs),
fBfieldValue(DBL_MAX, DBL_MAX, DBL_MAX),
fPtrMagEqOfMot(EqRhs)
fBfieldValue(DBL_MAX, DBL_MAX, DBL_MAX)
{
;
}
G4ExactHelixStepper::~G4ExactHelixStepper() {}
G4ExactHelixStepper::~G4ExactHelixStepper()
{
}
// ---------------------------------------------------------------------------
void
G4ExactHelixStepper::Stepper( const G4double yInput[],
const G4double*,
G4double hstep,
G4double yOut[],
G4double yErr[] )
G4double yErr[] )
{
const G4int nvar = 6;
const G4int nvar = 6;
G4int i;
G4ThreeVector Bfld_value;
G4int i;
G4ThreeVector Bfld_value;
MagFieldEvaluate(yInput, Bfld_value);
AdvanceHelix(yInput, Bfld_value, hstep, yOut);
MagFieldEvaluate(yInput, Bfld_value);
AdvanceHelix(yInput, Bfld_value, hstep, yOut);
// We are assuming a constant field: helix is exact
//
for(i=0;i<nvar;i++)
for(i=0; i<nvar; ++i)
{
yErr[i] = 0.0 ;
}
fBfieldValue=Bfld_value;
fBfieldValue = Bfld_value;
}
// ---------------------------------------------------------------------------
void
G4ExactHelixStepper::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[])
G4ExactHelixStepper::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[])
{
// Assuming a constant field: solution is a helix
@@ -120,6 +117,8 @@ G4ExactHelixStepper::DistChord() const
return distChord;
}
// ---------------------------------------------------------------------------
G4int
G4ExactHelixStepper::IntegratorOrder() const
{
@@ -23,15 +23,14 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ExplicitEuler implementation
//
// 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.
//
// 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
// Created: W.Wander <wwc@mit.edu>, 12.09.1997
// -------------------------------------------------------------------
#include "G4ExplicitEuler.hh"
@@ -40,7 +39,7 @@
//////////////////////////////////////////////////////////////////////////
//
// Constructor
//
G4ExplicitEuler::G4ExplicitEuler(G4EquationOfMotion* EqRhs,
G4int numberOfVariables)
: G4MagErrorStepper(EqRhs, numberOfVariables)
@@ -51,7 +50,7 @@ G4ExplicitEuler::G4ExplicitEuler(G4EquationOfMotion* EqRhs,
///////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4ExplicitEuler::~G4ExplicitEuler()
{
}
@@ -60,24 +59,21 @@ G4ExplicitEuler::~G4ExplicitEuler()
///////////////////////////////////////////////////////////////////////
//
//
//
void
G4ExplicitEuler::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[] )
G4ExplicitEuler::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[] )
{
const G4int numberOfVariables= GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
// Initialise time to t0, needed when it is not updated by the integration.
// yOut[7] = yIn[7]; // Better to set it to NaN; // TODO
G4int i;
for(i=0;i< numberOfVariables;i++)
for(G4int i=0; i< numberOfVariables; ++i)
{
yOut[i] = yIn[i] + h*dydx[i] ; // 1st and only Step
}
return ;
return;
}
@@ -23,62 +23,50 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Bogacki-Shampine - 8 - 5(4) FSAL implementation by Somnath Banerjee
// Supervision / code review: John Apostolakis
// G4FSALBogackiShampine45 implementation
//
// Sponsored by Google in Google Summer of Code 2015.
//
// First version: 26 May 2015
// The Butcher table of the Bogacki-Shampine-8-4-5 method is as follows:
//
// History
// -----------------------------
// Created by Somnath on 26 May 2015
//
///////////////////////////////////////////////////////////////////////////////
// Renamed to G4 standard naming
// Plan is that this source file / class will be merged with the updated
// BogackiShampine45 class, which contains improvements (May 2016)
// J. Apostolakis, 31 May 2016
///////////////////////////////////////////////////////////////////////////////
// 0 |
// 1/6 | 1/6
// 2/9 | 2/27 4/27
// 3/7 | 183/1372 -162/343 1053/1372
// 2/3 | 68/297 -4/11 42/143 1960/3861
// 3/4 | 597/22528 81/352 63099/585728 58653/366080 4617/20480
// 1 | 174197/959244 -30942/79937 8152137/19744439 666106/1039181 -29421/29068 482048/414219
// 1 | 587/8064 0 4440339/15491840 24353/124800 387/44800 2152/5985 7267/94080
// -------------------------------------------------------------------------------------------------------------------
// 587/8064 0 4440339/15491840 24353/124800 387/44800 2152/5985 7267/94080 0
// 2479/34992 0 123/416 612941/3411720 43/1440 2272/6561 79937/1113912 3293/556956
//
//
//This is the source file of BogackiShampine45 class containing the
//definition of the stepper() method that evaluates one step in
//field propagation.
//The Butcher table of the Bogacki-Shampine-8-4-5 method is as follows :
//
//0 |
//1/6 | 1/6
//2/9 | 2/27 4/27
//3/7 | 183/1372 -162/343 1053/1372
//2/3 | 68/297 -4/11 42/143 1960/3861
//3/4 | 597/22528 81/352 63099/585728 58653/366080 4617/20480
//1 | 174197/959244 -30942/79937 8152137/19744439 666106/1039181 -29421/29068 482048/414219
//1 | 587/8064 0 4440339/15491840 24353/124800 387/44800 2152/5985 7267/94080
//-------------------------------------------------------------------------------------------------------------------
// 587/8064 0 4440339/15491840 24353/124800 387/44800 2152/5985 7267/94080 0
// 2479/34992 0 123/416 612941/3411720 43/1440 2272/6561 79937/1113912 3293/556956
// Created: Somnath Banerjee, Google Summer of Code 2015, 26 May 2015
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
// Plan is that this source file / class will be merged with the updated
// BogackiShampine45 class, which contains improvements (May 2016)
#include <cassert>
#include "G4FSALBogackiShampine45.hh"
#include "G4LineSection.hh"
G4bool G4FSALBogackiShampine45::fPreparedConstants= false;
G4bool G4FSALBogackiShampine45::fPreparedConstants = false;
G4double G4FSALBogackiShampine45::bi[12][7];
//Constructor
G4FSALBogackiShampine45::G4FSALBogackiShampine45(G4EquationOfMotion *EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4VFSALIntegrationStepper(EqRhs, noIntegrationVariables),
fLastStepLength( -1.0 ), fAuxStepper( nullptr )
// Constructor
//
G4FSALBogackiShampine45::G4FSALBogackiShampine45(G4EquationOfMotion* EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4VFSALIntegrationStepper(EqRhs, noIntegrationVariables)
{
const G4int numberOfVariables = noIntegrationVariables;
//New Chunk of memory being created for use by the stepper
// New Chunk of memory being created for use by the stepper
//aki - for storing intermediate RHS
// aki - for storing intermediate RHS
//
ak2 = new G4double[numberOfVariables];
ak3 = new G4double[numberOfVariables];
ak4 = new G4double[numberOfVariables];
@@ -97,6 +85,7 @@ G4FSALBogackiShampine45::G4FSALBogackiShampine45(G4EquationOfMotion *EqRhs,
GetNumberOfStateVariables() );
// Must ensure space extra 'state' variables exists - i.e. yIn[7]
//
yTemp = new G4double[numStateVars];
yIn = new G4double[numStateVars] ;
@@ -113,207 +102,202 @@ G4FSALBogackiShampine45::G4FSALBogackiShampine45(G4EquationOfMotion *EqRhs,
fMidError = new G4double[numberOfVariables];
if( primary )
{
fAuxStepper = new G4FSALBogackiShampine45(EqRhs, numberOfVariables,
!primary);
fAuxStepper = new G4FSALBogackiShampine45(EqRhs, numberOfVariables,
!primary);
}
if( ! fPreparedConstants )
if( !fPreparedConstants )
{
PrepareConstants();
}
}
// Destructor
//
G4FSALBogackiShampine45::~G4FSALBogackiShampine45()
{
// Clear all previously allocated memory for stepper and DistChord
//Destructor
G4FSALBogackiShampine45::~G4FSALBogackiShampine45(){
//clear all previously allocated memory for stepper and DistChord
delete[] ak2;
delete[] ak3;
delete[] ak4;
delete[] ak5;
delete[] ak6;
delete[] ak7;
delete[] ak8;
delete[] ak9;
delete[] ak10;
delete[] ak11;
delete[] DyDx;
delete[] yTemp;
delete[] yIn;
delete [] ak2;
delete [] ak3;
delete [] ak4;
delete [] ak5;
delete [] ak6;
delete [] ak7;
delete [] ak8;
delete [] ak9;
delete [] ak10;
delete [] ak11;
delete [] DyDx;
delete [] yTemp;
delete [] yIn;
delete[] fLastInitialVector;
delete[] fLastFinalVector;
delete[] fLastDyDx;
delete[] fMidVector;
delete[] fMidError;
delete [] fLastInitialVector;
delete [] fLastFinalVector;
delete [] fLastDyDx;
delete [] fMidVector;
delete [] fMidError;
delete fAuxStepper;
delete[] pseudoDydx_for_DistChord;
delete [] pseudoDydx_for_DistChord;
}
//Stepper :
// Stepper
//
// Passing in the value of yInput[],the first time dydx[] and Step length
// Giving back yOut and yErr arrays for output and error respectively
//
void G4FSALBogackiShampine45::Stepper(const G4double yInput[],
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[],
G4double nextDydx[])
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[],
G4double nextDydx[])
{
G4int i;
//The various constants defined on the basis of butcher tableu
const G4double //G4double - only once
// The various constants defined on the basis of butcher tableu
const G4double b21 = 1.0/6.0 ,
b31 = 2.0/27.0 , b32 = 4.0/27.0,
b21 = 1.0/6.0 ,
b31 = 2.0/27.0 , b32 = 4.0/27.0,
b41 = 183.0/1372.0 , b42 = -162.0/343.0, b43 = 1053.0/1372.0,
b41 = 183.0/1372.0 , b42 = -162.0/343.0, b43 = 1053.0/1372.0,
b51 = 68.0/297.0, b52 = -4.0/11.0,
b53 = 42.0/143.0, b54 = 1960.0/3861.0,
b51 = 68.0/297.0, b52 = -4.0/11.0,
b53 = 42.0/143.0, b54 = 1960.0/3861.0,
b61 = 597.0/22528.0, b62 = 81.0/352.0,
b63 = 63099.0/585728.0, b64 = 58653.0/366080.0,
b65 = 4617.0/20480.0,
b61 = 597.0/22528.0, b62 = 81.0/352.0,
b63 = 63099.0/585728.0, b64 = 58653.0/366080.0,
b65 = 4617.0/20480.0,
b71 = 174197.0/959244.0, b72 = -30942.0/79937.0,
b73 = 8152137.0/19744439.0, b74 = 666106.0/1039181.0,
b75 = -29421.0/29068.0, b76 = 482048.0/414219.0,
b71 = 174197.0/959244.0, b72 = -30942.0/79937.0,
b73 = 8152137.0/19744439.0, b74 = 666106.0/1039181.0,
b75 = -29421.0/29068.0, b76 = 482048.0/414219.0,
b81 = 587.0/8064.0, b82 = 0.0,
b83 = 4440339.0/15491840.0, b84 = 24353.0/124800.0,
b85 = 387.0/44800.0, b86 = 2152.0/5985.0,
b87 = 7267.0/94080.0,
b81 = 587.0/8064.0, b82 = 0.0,
b83 = 4440339.0/15491840.0, b84 = 24353.0/124800.0,
b85 = 387.0/44800.0, b86 = 2152.0/5985.0,
b87 = 7267.0/94080.0,
// c1 = 2479.0/34992.0,
// c2 = 0.0,
// c3 = 123.0/416.0,
// c4 = 612941.0/3411720.0,
// c5 = 43.0/1440.0,
// c6 = 2272.0/6561.0,
// c7 = 79937.0/1113912.0,
// c8 = 3293.0/556956.0,
// c1 = 2479.0/34992.0,
// c2 = 0.0,
// c3 = 123.0/416.0,
// c4 = 612941.0/3411720.0,
// c5 = 43.0/1440.0,
// c6 = 2272.0/6561.0,
// c7 = 79937.0/1113912.0,
// c8 = 3293.0/556956.0,
//For the embedded higher order method only the difference of values
// For the embedded higher order method only the difference of values
// taken and is used directly later instead of defining the last row
// of butcher table in a separate set of variables and taking the
// difference there
dc1 = b81 - 2479.0/34992.0 ,
dc2 = 0.0,
dc3 = b83 - 123.0/416.0 ,
dc4 = b84 - 612941.0/3411720.0,
dc5 = b85 - 43.0/1440.0,
dc6 = b86 - 2272.0/6561.0,
dc7 = b87 - 79937.0/1113912.0,
dc8 = -3293.0/556956.0; // end of declaration
dc1 = b81 - 2479.0/34992.0 ,
dc2 = 0.0,
dc3 = b83 - 123.0/416.0 ,
dc4 = b84 - 612941.0/3411720.0,
dc5 = b85 - 43.0/1440.0,
dc6 = b86 - 2272.0/6561.0,
dc7 = b87 - 79937.0/1113912.0,
dc8 = -3293.0/556956.0; //end of declaration
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
// The number of variables to be integrated over
//
yOut[7] = yTemp[7] = yIn[7];
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<numberOfVariables;i++)
//
for(i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
DyDx[i] = dydx[i];
}
// RightHandSide(yIn, dydx) ; // 1st Step - Not doing, getting passed
// RightHandSide(yIn, dydx) ;
// 1st Step - Not doing, getting passed
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + b21*Step*DyDx[i] ;
}
RightHandSide(yTemp, ak2) ; // 2nd Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b31*DyDx[i] + b32*ak2[i]) ;
}
RightHandSide(yTemp, ak3) ; // 3rd Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b41*DyDx[i] + b42*ak2[i] + b43*ak3[i]) ;
}
RightHandSide(yTemp, ak4) ; // 4th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b51*DyDx[i] + b52*ak2[i] + b53*ak3[i] +
b54*ak4[i]) ;
}
RightHandSide(yTemp, ak5) ; // 5th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b61*DyDx[i] + b62*ak2[i] + b63*ak3[i] +
b64*ak4[i] + b65*ak5[i]) ;
}
RightHandSide(yTemp, ak6) ; // 6th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b71*DyDx[i] + b72*ak2[i] + b73*ak3[i] +
b74*ak4[i] + b75*ak5[i] + b76*ak6[i]);
}
RightHandSide(yTemp, ak7); //7th Step
RightHandSide(yTemp, ak7); // 7th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*(b81*DyDx[i] + b82*ak2[i] + b83*ak3[i] +
b84*ak4[i] + b85*ak5[i] + b86*ak6[i] +
b87*ak7[i]);
}
RightHandSide(yOut, ak8); //8th Step - Final one Using FSAL
RightHandSide(yOut, ak8); // 8th Step - Final one Using FSAL
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yErr[i] = Step*(dc1*DyDx[i] + dc2*ak2[i] + dc3*ak3[i] + dc4*ak4[i] +
dc5*ak5[i] + dc6*ak6[i] + dc7*ak7[i] + dc8*ak8[i]) ;
//FSAL stepper : Must pass the last DyDx for the next step, here ak8
// FSAL stepper : Must pass the last DyDx for the next step, here ak8
//
nextDydx[i] = ak8[i];
// Store Input and Final values, for possible use in calculating chord
//
fLastInitialVector[i] = yIn[i] ;
fLastFinalVector[i] = yOut[i];
fLastDyDx[i] = DyDx[i];
}
fLastStepLength = Step;
return ;
return;
}
// DistChord
//
//G4double* G4FSALBogackiShampine45::getLastDydx(){
// return ak8;
//}
//The following has not been tested
//The DistChord() function fot the class - must define it here.
G4double G4FSALBogackiShampine45::DistChord() const
G4double G4FSALBogackiShampine45::DistChord() const
{
G4double distLine, distChord;
G4ThreeVector initialPoint, finalPoint, midPoint;
// Store last initial and final points (they will be overwritten in self-Stepper call!)
// Store last initial and final points
// (they will be overwritten in self-Stepper call!)
//
initialPoint = G4ThreeVector( fLastInitialVector[0],
fLastInitialVector[1], fLastInitialVector[2]);
finalPoint = G4ThreeVector( fLastFinalVector[0],
@@ -322,17 +306,16 @@ G4double G4FSALBogackiShampine45::DistChord() const
// Do half a step using StepNoErr
fAuxStepper->Stepper( fLastInitialVector, fLastDyDx, 0.5 * fLastStepLength,
fMidVector, fMidError, pseudoDydx_for_DistChord );
fMidVector, fMidError, pseudoDydx_for_DistChord );
midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2]);
midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2] );
// Use stored values of Initial and Endpoint + new Midpoint to evaluate
// distance of Chord
// distance of Chord
//
if (initialPoint != finalPoint)
{
distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
distLine = G4LineSection::Distline(midPoint, initialPoint, finalPoint);
distChord = distLine;
}
else
@@ -342,17 +325,20 @@ G4double G4FSALBogackiShampine45::DistChord() const
return distChord;
}
// ---------------------------------------------------------------------------------------
// PrepareConstants
//
void G4FSALBogackiShampine45::PrepareConstants()
{
// --------------------------------------------------------
// COEFFICIENTS FOR INTERPOLANT bi WITH 11 STAGES
// --------------------------------------------------------
// Initialise all values of G4double bi[12][7]
for(int i=1; i<12; i++){
for(int j=1; j<7; j++){
// Initialise all values of G4double bi[12][7]
//
for(auto i=1; i<12; ++i)
{
for(auto j=1; j<7; ++j)
{
bi[i][j] = 0.0 ;
}
}
@@ -422,56 +408,58 @@ void G4FSALBogackiShampine45::PrepareConstants()
// ---------------------------------------------------------------------------------------
void G4FSALBogackiShampine45::interpolate( const G4double yInput[],
const G4double dydx[],
G4double yOut[],
G4double Step,
G4double tau
)
const G4double dydx[],
G4double yOut[],
G4double Step,
G4double tau )
{
const G4double
a91 = 455.0/6144.0 ,
a92 = 0.0 ,
a93 = 10256301.0/35409920.0 ,
a94 = 2307361.0/17971200.0 ,
a95 = -387.0/102400.0 ,
a96 = 73.0/5130.0 ,
a97 = -7267.0/215040.0 ,
a98 = 1.0/32.0 ,
const G4double a91 = 455.0/6144.0 ,
a92 = 0.0 ,
a93 = 10256301.0/35409920.0 ,
a94 = 2307361.0/17971200.0 ,
a95 = -387.0/102400.0 ,
a96 = 73.0/5130.0 ,
a97 = -7267.0/215040.0 ,
a98 = 1.0/32.0 ,
a101 = -837888343715.0/13176988637184.0 ,
a102 = 30409415.0/52955362.0 ,
a103 = -48321525963.0/759168069632.0 ,
a104 = 8530738453321.0/197654829557760.0 ,
a105 = 1361640523001.0/1626788720640.0 ,
a106 = -13143060689.0/38604458898.0 ,
a107 = 18700221969.0/379584034816.0 ,
a108 = -5831595.0/847285792.0 ,
a109 = -5183640.0/26477681.0 ,
a101 = -837888343715.0/13176988637184.0 ,
a102 = 30409415.0/52955362.0 ,
a103 = -48321525963.0/759168069632.0 ,
a104 = 8530738453321.0/197654829557760.0 ,
a105 = 1361640523001.0/1626788720640.0 ,
a106 = -13143060689.0/38604458898.0 ,
a107 = 18700221969.0/379584034816.0 ,
a108 = -5831595.0/847285792.0 ,
a109 = -5183640.0/26477681.0 ,
a111 = 98719073263.0/1551965184000.0 ,
a112 = 1307.0/123552.0 ,
a113 = 4632066559387.0/70181753241600.0 ,
a114 = 7828594302389.0/382182512025600.0 ,
a115 = 40763687.0/11070259200.0 ,
a116 = 34872732407.0/224610586200.0 ,
a117 = -2561897.0/30105600.0 ,
a118 = 1.0/10.0 ,
a119 = -1.0/10.0 ,
a1110 = -1403317093.0/11371610250.0 ;
a111 = 98719073263.0/1551965184000.0 ,
a112 = 1307.0/123552.0 ,
a113 = 4632066559387.0/70181753241600.0 ,
a114 = 7828594302389.0/382182512025600.0 ,
a115 = 40763687.0/11070259200.0 ,
a116 = 34872732407.0/224610586200.0 ,
a117 = -2561897.0/30105600.0 ,
a118 = 1.0/10.0 ,
a119 = -1.0/10.0 ,
a1110 = -1403317093.0/11371610250.0 ;
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
// Saving yInput because yInput and yOut can be aliases for same array
for(int i=0;i<numberOfVariables;i++)
// Saving yInput because yInput and yOut can be aliases for same array
//
for(G4int i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
}
// The number of variables to be integrated over
//
yOut[7] = yTemp[7] = yIn[7];
// calculating extra stages
for(int i=0; i<numberOfVariables; i++){
// Calculating extra stages
//
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(a91*dydx[i] + a92*ak2[i] + a93*ak3[i] +
a94*ak4[i] + a95*ak5[i] + a96*ak6[i] +
a97*ak7[i] + a98*ak8[i] );
@@ -479,7 +467,8 @@ void G4FSALBogackiShampine45::interpolate( const G4double yInput[],
RightHandSide(yTemp, ak9);
for(int i=0; i<numberOfVariables; i++){
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(a101*dydx[i] + a102*ak2[i] + a103*ak3[i] +
a104*ak4[i] + a105*ak5[i] + a106*ak6[i] +
a107*ak7[i] + a108*ak8[i] + a109*ak9[i] );
@@ -487,7 +476,8 @@ void G4FSALBogackiShampine45::interpolate( const G4double yInput[],
RightHandSide(yTemp, ak10);
for(int i=0; i<numberOfVariables; i++){
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(a111*dydx[i] + a112*ak2[i] + a113*ak3[i] +
a114*ak4[i] + a115*ak5[i] + a116*ak6[i] +
a117*ak7[i] + a118*ak8[i] + a119*ak9[i] +
@@ -497,24 +487,25 @@ void G4FSALBogackiShampine45::interpolate( const G4double yInput[],
RightHandSide(yTemp, ak11);
G4double tau0 = tau;
// Calculating the polynomials :
for(int i=1; i<=11; i++){ //Here i is NOT the coordinate no. , it's stage no.
// Calculating the polynomials
//
for(auto i=1; i<=11; ++i) // i is NOT the coordinate no., it's stage no.
{
b[i] = 0.0;
tau = tau0;
for(int j=1; j<=6; j++){
for(auto j=1; j<=6; ++j)
{
b[i] += bi[i][j]*tau;
tau*=tau0;
}
}
for(int i=0; i<numberOfVariables; i++){
for(G4int i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*(b[1]*dydx[i] + b[2]*ak2[i] + b[3]*ak3[i] +
b[4]*ak4[i] + b[5]*ak5[i] + b[6]*ak6[i] +
b[7]*ak7[i] + b[8]*ak8[i] + b[9]*ak9[i] +
b[10]*ak10[i] + b[11]*ak11[i] );
}
}
@@ -23,268 +23,249 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// DormandPrince7 - 5(4) implementation by Somnath Banerjee
// Supervision / code review: John Apostolakis
// G4FSALDormandPrince745 implementation
//
// Sponsored by Google in Google Summer of Code 2015.
// The Butcher table of the FDormand-Prince-7-4-5 method is as follows:
//
// First version: 25 May 2015
// 0 |
// 1/5 | 1/5
// 3/10| 3/40 9/40
// 4/5 | 44/45 56/15 32/9
// 8/9 | 19372/6561 25360/2187 64448/6561 212/729
// 1 | 9017/3168 355/33 46732/5247 49/176 5103/18656
// 1 | 35/384 0 500/1113 125/192 2187/6784 11/84
// ---------------------------------------------------------------------------
// 35/384 0 500/1113 125/192 2187/6784 11/84 0
// 5179/57600 0 7571/16695 393/640 92097/339200 187/2100 1/40
//
// G4FSALDormandPrince745.cc
// Geant4
//
// This is the source file of G4FSALDormandPrince745 class containing the
// definition of the stepper() method that evaluates one step in
// field propagation.
// The Butcher table of the FDormand-Prince-7-4-5 method is as follows :
//
// 0 |
// 1/5 | 1/5
// 3/10| 3/40 9/40
// 4/5 | 44/45 56/15 32/9
// 8/9 | 19372/6561 25360/2187 64448/6561 212/729
// 1 | 9017/3168 355/33 46732/5247 49/176 5103/18656
// 1 | 35/384 0 500/1113 125/192 2187/6784 11/84
// ---------------------------------------------------------------------------
// 35/384 0 500/1113 125/192 2187/6784 11/84 0
// 5179/57600 0 7571/16695 393/640 92097/339200 187/2100 1/40
//
// Implementation by Somnath Banerjee - GSoC 2015
// Work supported by Google as part of Google Summer of Code 2015.
// Supervision / code review: John Apostolakis
//
// First version: June 2015 - Somnath Banerjee
// Created: Somnath Banerjee, Google Summer of Code 2015, 25 May 2015
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4FSALDormandPrince745.hh"
#include "G4LineSection.hh"
#include <cmath>
//Constructor
G4FSALDormandPrince745::G4FSALDormandPrince745(G4EquationOfMotion *EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4VFSALIntegrationStepper(EqRhs, noIntegrationVariables)
// Constructor
//
G4FSALDormandPrince745::G4FSALDormandPrince745(G4EquationOfMotion* EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4VFSALIntegrationStepper(EqRhs, noIntegrationVariables)
{
const G4int numberOfVariables = noIntegrationVariables;
const G4int numberOfVariables = noIntegrationVariables;
// New Chunk of memory being created for use by the stepper
//New Chunk of memory being created for use by the stepper
//aki - for storing intermediate RHS
ak2 = new G4double[numberOfVariables];
ak3 = new G4double[numberOfVariables];
ak4 = new G4double[numberOfVariables];
ak5 = new G4double[numberOfVariables];
ak6 = new G4double[numberOfVariables];
ak7 = new G4double[numberOfVariables];
// Also always allocate arrays for interpolation stages
ak8 = new G4double[numberOfVariables];
ak9 = new G4double[numberOfVariables];
yTemp = new G4double[numberOfVariables] ;
yIn = new G4double[numberOfVariables] ;
pseudoDydx_for_DistChord = new G4double[numberOfVariables];
// aki - for storing intermediate RHS
//
ak2 = new G4double[numberOfVariables];
ak3 = new G4double[numberOfVariables];
ak4 = new G4double[numberOfVariables];
ak5 = new G4double[numberOfVariables];
ak6 = new G4double[numberOfVariables];
ak7 = new G4double[numberOfVariables];
fInitialDyDx = new G4double[numberOfVariables];
fLastInitialVector = new G4double[numberOfVariables] ;
fLastFinalVector = new G4double[numberOfVariables] ;
fLastDyDx = new G4double[numberOfVariables];
// Also always allocate arrays for interpolation stages
//
ak8 = new G4double[numberOfVariables];
ak9 = new G4double[numberOfVariables];
fMidVector = new G4double[numberOfVariables];
fMidError = new G4double[numberOfVariables];
yTemp = new G4double[numberOfVariables] ;
yIn = new G4double[numberOfVariables] ;
fAuxStepper = nullptr;
if( primary )
{
fAuxStepper = new G4FSALDormandPrince745(EqRhs, numberOfVariables,
!primary);
}
fLastStepLength = -1.0;
pseudoDydx_for_DistChord = new G4double[numberOfVariables];
fInitialDyDx = new G4double[numberOfVariables];
fLastInitialVector = new G4double[numberOfVariables] ;
fLastFinalVector = new G4double[numberOfVariables] ;
fLastDyDx = new G4double[numberOfVariables];
fMidVector = new G4double[numberOfVariables];
fMidError = new G4double[numberOfVariables];
if( primary )
{
fAuxStepper = new G4FSALDormandPrince745(EqRhs,numberOfVariables,!primary);
}
}
//Destructor
// Destructor
//
G4FSALDormandPrince745::~G4FSALDormandPrince745()
{
//clear all previously allocated memory for stepper and DistChord
delete[] ak2; ak2=nullptr;
delete[] ak3; ak3=nullptr;
delete[] ak4; ak4=nullptr;
delete[] ak5; ak5=nullptr;
delete[] ak6; ak6=nullptr;
delete[] ak7; ak7=nullptr;
delete[] ak8; ak8=nullptr;
delete[] ak9; ak9=nullptr;
delete[] yTemp; yTemp= nullptr;
delete[] yIn; yIn= nullptr;
// Clear all previously allocated memory for stepper and DistChord
delete[] pseudoDydx_for_DistChord; pseudoDydx_for_DistChord= nullptr;
delete[] fInitialDyDx; fInitialDyDx= nullptr;
delete [] ak2; ak2 = nullptr;
delete [] ak3; ak3 = nullptr;
delete [] ak4; ak4 = nullptr;
delete [] ak5; ak5 = nullptr;
delete [] ak6; ak6 = nullptr;
delete [] ak7; ak7 = nullptr;
delete [] ak8; ak8 = nullptr;
delete [] ak9; ak9 = nullptr;
delete[] fLastInitialVector; fLastInitialVector= nullptr;
delete[] fLastFinalVector; fLastFinalVector = nullptr;
delete[] fLastDyDx; fLastDyDx = nullptr;
delete[] fMidVector; fMidVector = nullptr;
delete[] fMidError; fMidError = nullptr;
delete [] yTemp; yTemp = nullptr;
delete [] yIn; yIn = nullptr;
delete [] pseudoDydx_for_DistChord; pseudoDydx_for_DistChord = nullptr;
delete [] fInitialDyDx; fInitialDyDx = nullptr;
delete fAuxStepper; fAuxStepper= nullptr;
delete [] fLastInitialVector; fLastInitialVector = nullptr;
delete [] fLastFinalVector; fLastFinalVector = nullptr;
delete [] fLastDyDx; fLastDyDx = nullptr;
delete [] fMidVector; fMidVector = nullptr;
delete [] fMidError; fMidError = nullptr;
delete fAuxStepper; fAuxStepper = nullptr;
}
//Stepper :
// Stepper
//
// Passing in the value of yInput[],the first time dydx[] and Step length
// Giving back yOut and yErr arrays for output and error respectively
//
void G4FSALDormandPrince745::Stepper(const G4double yInput[],
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[],
G4double nextDydx[]
)
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[],
G4double nextDydx[] )
{
G4int i;
//The various constants defined on the basis of butcher tableu
const G4double //G4double - only once
b21 = 0.2 ,
b31 = 3.0/40.0, b32 = 9.0/40.0 ,
b41 = 44.0/45.0, b42 = -56.0/15.0, b43 = 32.0/9.0,
b51 = 19372.0/6561.0, b52 = -25360.0/2187.0, b53 = 64448.0/6561.0,
b54 = -212.0/729.0 ,
b61 = 9017.0/3168.0 , b62 = -355.0/33.0,
b63 = 46732.0/5247.0 , b64 = 49.0/176.0 ,
b65 = -5103.0/18656.0 ,
b71 = 35.0/384.0, b72 = 0.,
b73 = 500.0/1113.0, b74 = 125.0/192.0,
b75 = -2187.0/6784.0, b76 = 11.0/84.0,
// c1 = 35.0/384.0, c2 = .0,
// c3 = 500.0/1113.0, c4 = 125.0/192.0,
// c5 = -2187.0/6784.0, c6 = 11.0/84.0,
// c7 = 0,
dc1 = b71 - 5179.0/57600.0,
dc2 = b72 - .0,
dc3 = b73 - 7571.0/16695.0,
dc4 = b74 - 393.0/640.0,
dc5 = b75 + 92097.0/339200.0,
dc6 = b76 - 187.0/2100.0,
dc7 = - 1.0/40.0 ; //end of declaration
const G4int numberOfVariables= this->GetNumberOfVariables();
// The number of variables to be integrated over
// The various constants defined on the basis of butcher tableu
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<numberOfVariables;i++)
const G4double b21 = 0.2 ,
b31 = 3.0/40.0, b32 = 9.0/40.0 ,
b41 = 44.0/45.0, b42 = -56.0/15.0, b43 = 32.0/9.0,
b51 = 19372.0/6561.0, b52 = -25360.0/2187.0,
b53 = 64448.0/6561.0, b54 = -212.0/729.0 ,
b61 = 9017.0/3168.0 , b62 = -355.0/33.0,
b63 = 46732.0/5247.0 , b64 = 49.0/176.0 ,
b65 = -5103.0/18656.0 ,
b71 = 35.0/384.0, b72 = 0.,
b73 = 500.0/1113.0, b74 = 125.0/192.0,
b75 = -2187.0/6784.0, b76 = 11.0/84.0,
// c1 = 35.0/384.0, c2 = .0,
// c3 = 500.0/1113.0, c4 = 125.0/192.0,
// c5 = -2187.0/6784.0, c6 = 11.0/84.0,
// c7 = 0,
dc1 = b71 - 5179.0/57600.0,
dc2 = b72 - .0,
dc3 = b73 - 7571.0/16695.0,
dc4 = b74 - 393.0/640.0,
dc5 = b75 + 92097.0/339200.0,
dc6 = b76 - 187.0/2100.0,
dc7 = - 1.0/40.0 ; //end of declaration
const G4int numberOfVariables = GetNumberOfVariables();
// The number of variables to be integrated over
// Saving yInput because yInput and yOut can be aliases for same array
//
for(i=0; i<numberOfVariables; ++i)
{
yIn[i] = yInput[i];
fInitialDyDx[i] = dydx[i];
}
// Ensure that time is initialised - in case it is not integrated
//
yOut[7] = yTemp[7] = yInput[7];
// RightHandSide(yIn, DyDx) ; // 1st Step - Not doing, getting passed
// RightHandSide(yIn, DyDx) ;
// 1st Step - Not doing, getting passed
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + b21*Step*fInitialDyDx[i] ;
}
RightHandSide(yTemp, ak2) ; // 2nd Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b31*fInitialDyDx[i] + b32*ak2[i]) ;
}
RightHandSide(yTemp, ak3) ; // 3rd Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b41*fInitialDyDx[i] + b42*ak2[i] + b43*ak3[i]) ;
yTemp[i] = yIn[i] + Step*(b41*fInitialDyDx[i]
+ b42*ak2[i] + b43*ak3[i]) ;
}
RightHandSide(yTemp, ak4) ; // 4th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b51*fInitialDyDx[i] + b52*ak2[i] + b53*ak3[i] +
b54*ak4[i]) ;
yTemp[i] = yIn[i] + Step*(b51*fInitialDyDx[i]
+ b52*ak2[i] + b53*ak3[i] + b54*ak4[i]) ;
}
RightHandSide(yTemp, ak5) ; // 5th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b61*fInitialDyDx[i] + b62*ak2[i] + b63*ak3[i] +
b64*ak4[i] + b65*ak5[i]) ;
yTemp[i] = yIn[i] + Step*(b61*fInitialDyDx[i] + b62*ak2[i]
+ b63*ak3[i] + b64*ak4[i] + b65*ak5[i]) ;
}
RightHandSide(yTemp, ak6) ; // 6th Step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*(b71*fInitialDyDx[i] + b72*ak2[i] + b73*ak3[i] +
b74*ak4[i] + b75*ak5[i] + b76*ak6[i]);
yOut[i] = yIn[i] + Step*(b71*fInitialDyDx[i] + b72*ak2[i] + b73*ak3[i]
+ b74*ak4[i] + b75*ak5[i] + b76*ak6[i]);
}
RightHandSide(yOut, ak7); //7th and Final step
for(i=0;i<numberOfVariables;i++)
for(i=0; i<numberOfVariables; ++i)
{
yErr[i] = Step*(dc1*fInitialDyDx[i] + dc2*ak2[i] + dc3*ak3[i] + dc4*ak4[i] +
dc5*ak5[i] + dc6*ak6[i] + dc7*ak7[i] ) ;
yErr[i] = Step*(dc1*fInitialDyDx[i] + dc2*ak2[i] + dc3*ak3[i]
+ dc4*ak4[i] + dc5*ak5[i] + dc6*ak6[i] + dc7*ak7[i] ) ;
// Store Input and Final values, for possible use in calculating chord
//
fLastInitialVector[i] = yIn[i] ;
fLastFinalVector[i] = yOut[i];
fLastDyDx[i] = fInitialDyDx[i];
nextDydx[i] = ak7[i];
}
fLastStepLength = Step;
return ;
}
//The following has not been tested
//The DistChord() function fot the class - must define it here.
G4double G4FSALDormandPrince745::DistChord() const
// DistChord
//
G4double G4FSALDormandPrince745::DistChord() const
{
G4double distLine, distChord;
G4ThreeVector initialPoint, finalPoint, midPoint;
// Store last initial and final points (they will be overwritten in self-Stepper call!)
initialPoint = G4ThreeVector( fLastInitialVector[0],
// Store last initial and final points
// (they will be overwritten in self-Stepper call!)
//
initialPoint = G4ThreeVector(fLastInitialVector[0],
fLastInitialVector[1], fLastInitialVector[2]);
finalPoint = G4ThreeVector( fLastFinalVector[0],
finalPoint = G4ThreeVector(fLastFinalVector[0],
fLastFinalVector[1], fLastFinalVector[2]);
// Do half a step using StepNoErr
fAuxStepper->Stepper( fLastInitialVector, fLastDyDx, 0.5 * fLastStepLength,
fMidVector, fMidError, pseudoDydx_for_DistChord );
fMidVector, fMidError, pseudoDydx_for_DistChord );
midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2]);
midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2] );
// Use stored values of Initial and Endpoint + new Midpoint to evaluate
// distance of Chord
// distance of Chord
//
if (initialPoint != finalPoint)
{
distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
distLine = G4LineSection::Distline( midPoint,initialPoint,finalPoint );
distChord = distLine;
}
else
@@ -294,118 +275,122 @@ G4double G4FSALDormandPrince745::DistChord() const
return distChord;
}
// interpolate
//
void G4FSALDormandPrince745::interpolate( const G4double yInput[],
const G4double dydx[],
G4double yOut[],
G4double Step,
G4double tau)
{
G4double bf1, bf2, bf3, bf4, bf5, bf6, bf7;
void G4FSALDormandPrince745::interpolate( const G4double yInput[],
const G4double dydx[],
G4double yOut[],
G4double Step,
G4double tau){
G4double
bf1, bf2, bf3, bf4, bf5, bf6, bf7;
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
G4double tau0 = tau;
for(int i=0;i<numberOfVariables;i++)
for(G4int i=0;i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
}
G4double
tau_2 = tau0*tau0 ,
tau_3 = tau0*tau_2,
tau_4 = tau_2*tau_2;
G4double tau_2 = tau0*tau0 ,
tau_3 = tau0*tau_2,
tau_4 = tau_2*tau_2;
bf1 = (157015080.0*tau_4 - 13107642775.0*tau_3+ 34969693132.0*tau_2- 32272833064.0*tau
+ 11282082432.0)/11282082432.0,
bf2 = 0.0 ,
bf3 = - 100.0*tau*(15701508.0*tau_3 - 914128567.0*tau_2 + 2074956840.0*tau
- 1323431896.0)/32700410799.0,
bf4 = 25.0*tau*(94209048.0*tau_3- 1518414297.0*tau_2+ 2460397220.0*tau - 889289856.0)/5641041216.0 ,
bf5 = -2187.0*tau*(52338360.0*tau_3 - 451824525.0*tau_2 + 687873124.0*tau - 259006536.0)/199316789632.0 ,
bf6 = 11.0*tau*(106151040.0*tau_3- 661884105.0*tau_2 + 946554244.0*tau - 361440756.0)/2467955532.0 ,
bf7 = tau*(1.0 - tau)*(8293050.0*tau_2 - 82437520.0*tau + 44764047.0)/ 29380423.0 ;
bf1 = (157015080.0*tau_4 - 13107642775.0*tau_3
+ 34969693132.0*tau_2- 32272833064.0*tau + 11282082432.0)
/ 11282082432.0;
bf2 = 0.0;
bf3 = - 100.0*tau*(15701508.0*tau_3 - 914128567.0*tau_2
+ 2074956840.0*tau - 1323431896.0) / 32700410799.0;
bf4 = 25.0*tau*(94209048.0*tau_3- 1518414297.0*tau_2
+ 2460397220.0*tau - 889289856.0)
/ 5641041216.0;
bf5 = -2187.0*tau*(52338360.0*tau_3 - 451824525.0*tau_2
+ 687873124.0*tau - 259006536.0)
/ 199316789632.0;
bf6 = 11.0*tau*(106151040.0*tau_3- 661884105.0*tau_2
+ 946554244.0*tau - 361440756.0)
/ 2467955532.0;
bf7 = tau*(1.0 - tau)*(8293050.0*tau_2 - 82437520.0*tau + 44764047.0)
/ 29380423.0;
for( int i=0; i<numberOfVariables; i++){
yOut[i] = yIn[i] + Step*tau*(bf1*dydx[i] + bf2*ak2[i] + bf3*ak3[i] + bf4*ak4[i]
+ bf5*ak5[i] + bf6*ak6[i] + bf7*ak7[i] ) ;
for(G4int i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*tau*(bf1*dydx[i] + bf2*ak2[i] + bf3*ak3[i]
+ bf4*ak4[i] + bf5*ak5[i] + bf6*ak6[i]
+ bf7*ak7[i] );
}
}
// SetupInterpolate
//
void G4FSALDormandPrince745::SetupInterpolate(const G4double yInput[],
const G4double dydx[],
const G4double Step ){
const G4double dydx[],
const G4double Step )
{
// Coefficients for the additional stages
//
G4double b81 = 6245.0/62208.0 ,
b82 = 0.0 ,
b83 = 8875.0/103032.0 ,
b84 = -125.0/1728.0 ,
b85 = 801.0/13568.0 ,
b86 = -13519.0/368064.0 ,
b87 = 11105.0/368064.0 ,
//Coefficients for the additional stages :
G4double
b81 = 6245.0/62208.0 ,
b82 = 0.0 ,
b83 = 8875.0/103032.0 ,
b84 = -125.0/1728.0 ,
b85 = 801.0/13568.0 ,
b86 = -13519.0/368064.0 ,
b87 = 11105.0/368064.0 ,
b91 = 632855.0/4478976.0 ,
b92 = 0.0 ,
b93 = 4146875.0/6491016.0 ,
b94 = 5490625.0/14183424.0 ,
b95 = -15975.0/108544.0 ,
b96 = 8295925.0/220286304.0 ,
b97 = -1779595.0/62938944.0 ,
b98 = -805.0/4104.0 ;
b91 = 632855.0/4478976.0 ,
b92 = 0.0 ,
b93 = 4146875.0/6491016.0 ,
b94 = 5490625.0/14183424.0 ,
b95 = -15975.0/108544.0 ,
b96 = 8295925.0/220286304.0 ,
b97 = -1779595.0/62938944.0 ,
b98 = -805.0/4104.0 ;
const G4int numberOfVariables = GetNumberOfVariables();
const G4int numberOfVariables= this->GetNumberOfVariables();
// Saving yInput because yInput and yOut can be aliases for same array
for(int i=0;i<numberOfVariables;i++)
// Saving yInput because yInput and yOut can be aliases for same array
//
for(G4int i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
yIn[i] = yInput[i];
}
yTemp[7] = yIn[7];
yTemp[7] = yIn[7];
//Evaluate the extra stages :
for(int i=0;i<numberOfVariables;i++)
// Evaluate the extra stages
//
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*( b81*dydx[i] + b82*ak2[i] + b83*ak3[i] +
b84*ak4[i] + b85*ak5[i] + b86*ak6[i] +
b87*ak7[i] );
}
RightHandSide( yTemp, ak8 ); //8th Stage
RightHandSide( yTemp, ak8 ); // 8th Stage
for(int i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step * ( b91*dydx[i] + b92*ak2[i] + b93*ak3[i] +
b94*ak4[i] + b95*ak5[i] + b96*ak6[i] +
b97*ak7[i] + b98*ak8[i] );
}
RightHandSide( yTemp, ak9 ); //9th Stage
RightHandSide( yTemp, ak9 ); // 9th Stage
}
// Interpolate
//
void G4FSALDormandPrince745::Interpolate( const G4double yInput[],
const G4double dydx[],
const G4double Step,
G4double yOut[],
G4double tau ){
//Define the coefficients for the polynomials
const G4double dydx[],
const G4double Step,
G4double yOut[],
G4double tau )
{
// Define the coefficients for the polynomials
G4double bi[10][5], b[10];
G4int numberOfVariables = this->GetNumberOfVariables();
G4int numberOfVariables = GetNumberOfVariables();
// COEFFICIENTS OF bi[1]
bi[1][0] = 1.0 ,
@@ -478,35 +463,31 @@ void G4FSALDormandPrince745::Interpolate( const G4double yInput[],
bi[9][3] = 2943.0/110.0 ,
bi[9][4] = -648.0/55.0 ;
// --------------------------------------------------------
for(G4int i = 0; i< numberOfVariables; i++)
for(G4int i = 0; i< numberOfVariables; ++i)
{
yIn[i] = yInput[i];
}
G4double tau0 = tau;
// Calculating the polynomials :
for(int i=1; i<=9; i++){ //Here i is NOT the coordinate no. , it's stage no.
// Calculating the polynomials
//
for(auto i=1; i<=9; ++i) // i is NOT the coordinate no., it's stage no.
{
b[i] = 0;
tau = 1.0;
for(int j=0; j<=4; j++){
for(auto j=0; j<=4; ++j)
{
b[i] += bi[i][j]*tau;
tau*=tau0;
}
}
for(int i=0; i<numberOfVariables; i++){ //Here i IS the cooridnate no.
for(G4int i=0; i<numberOfVariables; ++i) // Here i IS the coordinate no.
{
yOut[i] = yIn[i] + Step*tau0*(b[1]*dydx[i] + b[2]*ak2[i] + b[3]*ak3[i] +
b[4]*ak4[i] + b[5]*ak5[i] + b[6]*ak6[i] +
b[7]*ak7[i] + b[8]*ak8[i] + b[9]*ak9[i] );
}
}
+7 -6
View File
@@ -23,15 +23,15 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4Field implementation
//
// First implementation class for G4Field
// J. Apostolakis, 4 Nov 2011 - to add fGravityActive data member
// Created: John Apostolakis, 10.03.1997
// -------------------------------------------------------------------
#include "G4Field.hh"
G4Field::G4Field( G4bool gravityOn):
fGravityActive( gravityOn )
G4Field::G4Field( G4bool gravityOn )
: fGravityActive( gravityOn )
{
}
@@ -39,7 +39,7 @@ G4Field::~G4Field()
{
}
G4Field& G4Field::operator = (const G4Field &p)
G4Field& G4Field::operator = (const G4Field& p)
{
if (&p == this) return *this;
fGravityActive= p.fGravityActive;
@@ -58,6 +58,7 @@ G4Field* G4Field::Clone() const
<< "but Clone method called.\n"
<< "Cannot continue;";
G4Exception("G4Field::Clone", "GeomField004", FatalException,msg );
return NULL;
return nullptr;
}
// ------------------------------------------------------------------------
@@ -23,8 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4FieldManager implementation
//
//
// Author: John Apostolakis, 10.03.97 - design and implementation
// -------------------------------------------------------------------
#include "G4FieldManager.hh"
@@ -37,79 +38,91 @@
G4double G4FieldManager::fDefault_Delta_One_Step_Value= 0.01 * millimeter;
G4double G4FieldManager::fDefault_Delta_Intersection_Val= 0.001 * millimeter;
G4FieldManager::G4FieldManager(G4Field *detectorField,
G4ChordFinder *pChordFinder,
G4bool fieldChangesEnergy
)
G4FieldManager::G4FieldManager(G4Field* detectorField,
G4ChordFinder* pChordFinder,
G4bool fieldChangesEnergy )
: fDetectorField(detectorField),
fChordFinder(pChordFinder),
fAllocatedChordFinder(false),
fDelta_One_Step_Value( fDefault_Delta_One_Step_Value ),
fDelta_One_Step_Value( fDefault_Delta_One_Step_Value ),
fDelta_Intersection_Val( fDefault_Delta_Intersection_Val ),
fEpsilonMin( fEpsilonMinDefault ),
fEpsilonMax( fEpsilonMaxDefault)
{
if ( detectorField )
fFieldChangesEnergy= detectorField->DoesFieldChangeEnergy();
if ( detectorField != nullptr )
{
fFieldChangesEnergy = detectorField->DoesFieldChangeEnergy();
}
else
fFieldChangesEnergy= fieldChangesEnergy;
{
fFieldChangesEnergy = fieldChangesEnergy;
}
// Add to store
//
G4FieldManagerStore::Register(this);
}
G4FieldManager::G4FieldManager(G4MagneticField *detectorField)
G4FieldManager::G4FieldManager(G4MagneticField* detectorField)
: fDetectorField(detectorField), fAllocatedChordFinder(true),
fFieldChangesEnergy(false),
fDelta_One_Step_Value( fDefault_Delta_One_Step_Value ),
fDelta_Intersection_Val( fDefault_Delta_Intersection_Val ),
fEpsilonMin( fEpsilonMinDefault ),
fEpsilonMax( fEpsilonMaxDefault )
{
fChordFinder= new G4ChordFinder( detectorField );
fChordFinder = new G4ChordFinder( detectorField );
// Add to store
//
G4FieldManagerStore::Register(this);
}
G4FieldManager* G4FieldManager::Clone() const
{
G4Field* aField = 0;
G4FieldManager* aFM = 0;
G4ChordFinder* aCF = 0;
G4Field* aField = nullptr;
G4FieldManager* aFM = nullptr;
G4ChordFinder* aCF = nullptr;
try {
if ( this->fDetectorField )
aField = this->fDetectorField->Clone();
if ( fDetectorField != nullptr )
{
aField = fDetectorField->Clone();
}
//Create a new field manager, note that we do not set any chordfinder now.
aFM = new G4FieldManager( aField , 0 , this->fFieldChangesEnergy );
// Create a new field manager, note that we do not set
// any chordfinder now
//
aFM = new G4FieldManager( aField , nullptr , fFieldChangesEnergy );
//Check if orignally we have the fAllocatedChordFinder variable set, in case, call chord
//constructor
if ( this->fAllocatedChordFinder )
// Check if originally we have the fAllocatedChordFinder variable
// set, in case, call chord constructor
//
if ( fAllocatedChordFinder )
{
aFM->CreateChordFinder( dynamic_cast<G4MagneticField*>(aField) );
}
else
{
//Chord was specified by user, should we clone?
//TODO: For the moment copy pointer, to be understood if cloning of ChordFinder is needed
aCF = this->fChordFinder;/*->Clone*/
// Chord was specified by user, should we clone?
// TODO: For the moment copy pointer, to be understood
// if cloning of ChordFinder is needed
//
aCF = fChordFinder; /*->Clone*/
aFM->fChordFinder = aCF;
}
//Copy values of other variables
aFM->fEpsilonMax = this->fEpsilonMax;
aFM->fEpsilonMin = this->fEpsilonMin;
// aFM->fDefault_Delta_Intersection_Val = this->fDefault_Delta_Intersection_Val; // now static
// aFM->fDefault_Delta_One_Step_Value = this->fDefault_Delta_One_Step_Value; // now static
aFM->fDelta_Intersection_Val = this->fDelta_Intersection_Val;
aFM->fDelta_One_Step_Value = this->fDelta_One_Step_Value;
//TODO: Should we really add to the store the cloned FM? Who will use this?
// Copy values of other variables
aFM->fEpsilonMax = fEpsilonMax;
aFM->fEpsilonMin = fEpsilonMin;
aFM->fDelta_Intersection_Val = fDelta_Intersection_Val;
aFM->fDelta_One_Step_Value = fDelta_One_Step_Value;
// TODO: Should we really add to the store the cloned FM?
// Who will use this?
}
catch ( ... )
{
//Failed creating clone: probably user did not implement Clone method
//in derived classes?
//Perform clean-up after ourselves...
// Failed creating clone: probably user did not implement Clone method
// in derived classes?
// Perform clean-up after ourselves...
delete aField;
delete aFM;
delete aCF;
@@ -121,84 +134,103 @@ G4FieldManager* G4FieldManager::Clone() const
void G4FieldManager::ConfigureForTrack( const G4Track * )
{
// Default is to do nothing!
;
}
G4FieldManager::~G4FieldManager()
{
if( fAllocatedChordFinder ){
if( fAllocatedChordFinder )
{
delete fChordFinder;
}
G4FieldManagerStore::DeRegister(this);
}
void
G4FieldManager::CreateChordFinder(G4MagneticField *detectorMagField)
G4FieldManager::CreateChordFinder(G4MagneticField* detectorMagField)
{
if ( fAllocatedChordFinder )
if ( fAllocatedChordFinder )
{
delete fChordFinder;
fAllocatedChordFinder= false;
}
fAllocatedChordFinder = false;
if( detectorMagField ) {
fChordFinder= new G4ChordFinder( detectorMagField );
fAllocatedChordFinder= true;
} else {
if( detectorMagField != nullptr )
{
fChordFinder = new G4ChordFinder( detectorMagField );
fAllocatedChordFinder = true;
}
else
{
fChordFinder = nullptr;
}
}
void G4FieldManager::InitialiseFieldChangesEnergy()
{
if ( fDetectorField )
fFieldChangesEnergy= fDetectorField->DoesFieldChangeEnergy();
if ( fDetectorField != nullptr )
{
fFieldChangesEnergy = fDetectorField->DoesFieldChangeEnergy();
}
else
fFieldChangesEnergy= false; // No field , no change!
{
fFieldChangesEnergy = false; // No field, no change!
}
}
G4bool G4FieldManager::SetDetectorField(G4Field *pDetectorField, int failMode )
G4bool G4FieldManager::SetDetectorField(G4Field* pDetectorField,
G4int failMode )
{
G4VIntegrationDriver* driver = nullptr;
G4EquationOfMotion* equation = nullptr;
// G4bool compatibleField= false;
G4bool ableToSet= false;
// G4bool compatibleField = false;
G4bool ableToSet = false;
fDetectorField= pDetectorField;
fDetectorField = pDetectorField;
InitialiseFieldChangesEnergy();
// Must 'propagate' the field to the dependent classes
//
if( fChordFinder )
if( fChordFinder != nullptr )
{
failMode= std::max( failMode, 1) ; // If a chord finder exists, warn in case of error!
failMode= std::max( failMode, 1) ;
// If a chord finder exists, warn in case of error!
driver = fChordFinder->GetIntegrationDriver();
if( driver ){
equation = driver->GetEquationOfMotion();
// Should check the compatibility between the field and the equation HERE
if( equation ) {
equation->SetFieldObj(pDetectorField);
ableToSet = true;
}
if( driver != nullptr )
{
equation = driver->GetEquationOfMotion();
// Should check the compatibility between the
// field and the equation HERE
if( equation != nullptr )
{
equation->SetFieldObj(pDetectorField);
ableToSet = true;
}
}
}
if( !ableToSet && (failMode > 0) )
{
// If this fails, report the issue !
G4ExceptionDescription msg;
msg << "Unable to set the field in the dependent objects of G4FieldManager" << G4endl;
msg << "All the dependent classes must be fully initialised, before it is possible to call this method." << G4endl;
msg << "The problem encountered was the following: " << G4endl;
if( !fChordFinder ) { msg << " No ChordFinder. " ; }
else if( !driver) { msg << " No Integration Driver set. ";}
else if( !equation) { msg << " No Equation found. " ; }
// else if( !compatibleField ) { msg << " Field not compatible. ";}
else { msg << " Can NOT find reason for failure. ";}
msg << G4endl;
G4ExceptionSeverity severity= (failMode != 1) ? FatalException : JustWarning ;
G4Exception("G4FieldManager::SetDetectorField", "Geometry001",
severity, msg);
// If this fails, report the issue !
G4ExceptionDescription msg;
msg << "Unable to set the field in the dependent objects of G4FieldManager"
<< G4endl;
msg << "All the dependent classes must be fully initialised,"
<< "before it is possible to call this method." << G4endl;
msg << "The problem encountered was the following: " << G4endl;
if( fChordFinder == nullptr ) { msg << " No ChordFinder. " ; }
else if( driver == nullptr ) { msg << " No Integration Driver set. ";}
else if( equation == nullptr ) { msg << " No Equation found. " ; }
// else if( !compatibleField ) { msg << " Field not compatible. ";}
else { msg << " Can NOT find reason for failure. ";}
msg << G4endl;
G4ExceptionSeverity severity = (failMode != 1)
? FatalException : JustWarning ;
G4Exception("G4FieldManager::SetDetectorField", "Geometry001",
severity, msg);
}
return ableToSet;
}
@@ -23,14 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4FieldManagerStore implementation
//
//
// G4FieldManagerStore
//
// Implementation for singleton container
//
// History:
// 07.12.07 J.Apostolakis Adapted from G4LogicalVolumeStore
// Author: J.Apostolakis, 07.12.2007 - Adapted from G4LogicalVolumeStore
// --------------------------------------------------------------------
#include "G4Types.hh"
@@ -41,7 +36,7 @@
// Static class variables
// ***************************************************************************
//
G4ThreadLocal G4FieldManagerStore* G4FieldManagerStore::fgInstance = 0;
G4ThreadLocal G4FieldManagerStore* G4FieldManagerStore::fgInstance = nullptr;
G4ThreadLocal G4bool G4FieldManagerStore::locked = false;
// ***************************************************************************
@@ -62,7 +57,7 @@ G4FieldManagerStore::G4FieldManagerStore()
G4FieldManagerStore::~G4FieldManagerStore()
{
Clean();
fgInstance = 0;
fgInstance = nullptr;
}
// ***************************************************************************
@@ -79,7 +74,7 @@ void G4FieldManagerStore::Clean()
size_t i=0;
G4FieldManagerStore* store = GetInstance();
for(iterator pos=store->begin(); pos!=store->end(); pos++)
for(auto pos=store->cbegin(); pos!=store->cend(); ++pos)
{
if (*pos) { delete *pos; }
i++;
@@ -87,9 +82,13 @@ void G4FieldManagerStore::Clean()
#ifdef G4GEOMETRY_DEBUG
if (store->size() < i-1)
{ G4cout << "No field managers deleted. Already deleted by user ?" << G4endl; }
{
G4cout << "No field managers deleted. Already deleted by user ?" << G4endl;
}
else
{ G4cout << i-1 << " field managers deleted !" << G4endl; }
{
G4cout << i-1 << " field managers deleted !" << G4endl;
}
#endif
locked = false;
@@ -113,7 +112,7 @@ void G4FieldManagerStore::DeRegister(G4FieldManager* pFieldMgr)
{
if (!locked) // Do not de-register if locked !
{
for (iterator i=GetInstance()->begin(); i!=GetInstance()->end(); i++)
for (auto i=GetInstance()->cbegin(); i!=GetInstance()->cend(); ++i)
{
if (*i==pFieldMgr) // For LogVol was **i == *pLogVolume ... Reason?
{
@@ -130,7 +129,7 @@ void G4FieldManagerStore::DeRegister(G4FieldManager* pFieldMgr)
//
G4FieldManagerStore* G4FieldManagerStore::GetInstance()
{
if (!fgInstance)
if (fgInstance == nullptr)
{
fgInstance = new G4FieldManagerStore;
}
@@ -153,12 +152,12 @@ G4FieldManagerStore* G4FieldManagerStore::GetInstanceIfExist()
void
G4FieldManagerStore::ClearAllChordFindersState()
{
G4ChordFinder *pChordFnd;
G4ChordFinder* pChordFnd;
for (iterator i=GetInstance()->begin(); i!=GetInstance()->end(); i++)
for (auto i=GetInstance()->cbegin(); i!=GetInstance()->cend(); ++i)
{
pChordFnd = (*i)->GetChordFinder();
if( pChordFnd )
if( pChordFnd != nullptr )
{
pChordFnd->ResetStepEstimate();
}
@@ -23,21 +23,22 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4FieldTrack implementation
//
//
// Author: John Apostolakis, CERN - First version, 14.10.1996
// -------------------------------------------------------------------
#include "G4FieldTrack.hh"
std::ostream& operator<<( std::ostream& os, const G4FieldTrack& SixVec)
{
const G4double *SixV = SixVec.SixVector;
const int precPos= 9; // For position
const int precEp= 9; // For Energy / momentum
const int precLen= 12; // For Length along track
const int precSpin= 9; // For polarisation
const int precTime= 6; // For time of flight
const int oldpr= os.precision(precPos);
const G4double* SixV = SixVec.SixVector;
const G4int precPos= 9; // For position
const G4int precEp= 9; // For Energy / momentum
const G4int precLen= 12; // For Length along track
const G4int precSpin= 9; // For polarisation
const G4int precTime= 6; // For time of flight
const G4int oldpr= os.precision(precPos);
os << " ( ";
os << " X= " << SixV[0] << " " << SixV[1] << " "
<< SixV[2] << " "; // Position
@@ -52,15 +53,24 @@ std::ostream& operator<<( std::ostream& os, const G4FieldTrack& SixVec)
os.precision(6);
os << " m0= " << SixVec.fRestMass_c2;
os << " (Pdir-1)= " << SixVec.fMomentumDir.mag()-1.0;
if( SixVec.fLabTimeOfFlight > 0.0 ) os.precision(precTime);
else os.precision(3);
if( SixVec.fLabTimeOfFlight > 0.0 )
{
os.precision(precTime);
}
else
{
os.precision(3);
}
os << " t_lab= " << SixVec.fLabTimeOfFlight;
os << " t_proper= " << SixVec.fProperTimeOfFlight ;
G4ThreeVector pol= SixVec.GetPolarization();
if( pol.mag2() > 0.0 ){
if( pol.mag2() > 0.0 )
{
os.precision(precSpin);
os << " PolV= " << pol; // SixVec.GetPolarization();
}else{
}
else
{
os << " PolV= (0,0,0) ";
}
os << " ) ";
@@ -89,10 +99,9 @@ G4FieldTrack::G4FieldTrack( const G4ThreeVector& pPosition,
// fPDGSpin( pdgSpin )
{
UpdateFourMomentum( kineticEnergy, pMomentumDirection );
// Sets momentum direction as well.
SetPosition( pPosition );
// Sets momentum direction as well.
SetPosition( pPosition );
SetPolarization( vecPolarization );
}
@@ -114,7 +123,7 @@ G4FieldTrack::G4FieldTrack( const G4ThreeVector& pPosition,
fChargeState( DBL_MAX, DBL_MAX, -1.0 ) // charge not set
{
UpdateFourMomentum( kineticEnergy, pMomentumDirection );
// Sets momentum direction as well.
// Sets momentum direction as well.
SetPosition( pPosition );
fChargeState.SetPDGSpin( pdgSpin );
@@ -131,15 +140,15 @@ G4FieldTrack::G4FieldTrack( char ) // Nothing is set !!
G4ThreeVector Zero(0.0, 0.0, 0.0);
SetCurvePnt( Zero, Zero, 0.0 );
SetPolarization( Zero );
// fInitialMomentumMag= 0.00; // Invalid
// fLastMomentumMag= 0.0;
// fInitialMomentumMag = 0.00; // Invalid
// fLastMomentumMag = 0.0;
}
void G4FieldTrack::
SetChargeAndMoments(G4double charge,
G4double magnetic_dipole_moment, // default= DBL_MAX - do not change
G4double electric_dipole_moment, // ditto
G4double magnetic_charge ) // ditto
G4double magnetic_dipole_moment, // default = DBL_MAX
G4double electric_dipole_moment, // ditto
G4double magnetic_charge ) // ditto
{
fChargeState.SetChargesAndMoments( charge,
magnetic_dipole_moment,
@@ -148,7 +157,8 @@ void G4FieldTrack::
// NOTE: Leaves Spin unchanged !
//
// G4double pdgSpin= fChargeState.GetSpin(); // New Property of ChargeState (not well documented! )
// G4double pdgSpin= fChargeState.GetSpin();
// New Property of ChargeState (not well documented! )
// IDEA: Improve the implementation using handles
// -- and handle to the old one (which can be shared by other copies) and
@@ -160,49 +170,49 @@ void G4FieldTrack::
// Load values from array
//
// note that momentum direction must-be/is normalised
// Note that momentum direction must-be/is normalised
//
void G4FieldTrack::LoadFromArray(const G4double valArrIn[ncompSVEC],
G4int noVarsIntegrated)
{
G4int i;
// Fill the variables not integrated with zero -- so it's clear !!
//
G4double valArr[ncompSVEC];
for( i=0; i<noVarsIntegrated; i++){
valArr[i]= valArrIn[i];
for(G4int i=0; i<noVarsIntegrated; ++i)
{
valArr[i] = valArrIn[i];
}
for( i=noVarsIntegrated; i<ncompSVEC; i++) {
valArr[i]= 0.0;
for(G4int i=noVarsIntegrated; i<ncompSVEC; ++i)
{
valArr[i] = 0.0;
}
SixVector[0]=valArr[0];
SixVector[1]=valArr[1];
SixVector[2]=valArr[2];
SixVector[3]=valArr[3];
SixVector[4]=valArr[4];
SixVector[5]=valArr[5];
SixVector[0] = valArr[0];
SixVector[1] = valArr[1];
SixVector[2] = valArr[2];
SixVector[3] = valArr[3];
SixVector[4] = valArr[4];
SixVector[5] = valArr[5];
G4ThreeVector Momentum(valArr[3],valArr[4],valArr[5]);
G4double momentum_square= Momentum.mag2();
fMomentumDir= Momentum.unit();
fKineticEnergy = momentum_square /
(std::sqrt(momentum_square+fRestMass_c2*fRestMass_c2)
+ fRestMass_c2 );
// The above equation is stable for small and large momenta
fKineticEnergy = momentum_square
/ (std::sqrt(momentum_square+fRestMass_c2*fRestMass_c2)
+ fRestMass_c2 );
// The above equation is stable for small and large momenta
// The following components may or may not be
// integrated over -- integration is optional
// fKineticEnergy= valArr[6];
// integrated over -- integration is optional
// fKineticEnergy = valArr[6];
fLabTimeOfFlight=valArr[7];
fProperTimeOfFlight=valArr[8];
G4ThreeVector vecPolarization= G4ThreeVector(valArr[9],valArr[10],valArr[11]);
fLabTimeOfFlight = valArr[7];
fProperTimeOfFlight = valArr[8];
G4ThreeVector vecPolarization= G4ThreeVector(valArr[9],valArr[10],valArr[11]);
SetPolarization( vecPolarization );
// fMomentumDir=G4ThreeVector(valArr[13],valArr[14],valArr[15]);
// fDistanceAlongCurve= valArr[];
}
@@ -22,13 +22,11 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// Helper namespace field_utils implementation
//
//
//
// Implementation by Dmitry Sorokin - GSoC 2017
// Work supported by Google as part of Google Summer of Code 2017.
// Supervision / code review: John Apostolakis
// Author: Dmitry Sorokin, Google Summer of Code 2017
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4FieldUtils.hh"
@@ -39,71 +37,75 @@ namespace field_utils {
G4double absoluteError(const G4double y[],
const G4double yError[],
G4double hstep)
G4double hstep)
{
const G4double momentum2 = getValue2(y, Value3D::Momentum);
const G4double invMomentum2 = 1.0 / momentum2;
const G4double positionError2 = getValue2(yError, Value3D::Position);
const G4double momentumError2 = getValue2(yError, Value3D::Momentum);
const G4double relativeMomentumError2 = momentumError2 * invMomentum2;
const G4double momentum2 = getValue2(y, Value3D::Momentum);
const G4double invMomentum2 = 1.0 / momentum2;
const G4double positionError2 = getValue2(yError, Value3D::Position);
const G4double momentumError2 = getValue2(yError, Value3D::Momentum);
const G4double relativeMomentumError2 = momentumError2 * invMomentum2;
return std::max(std::sqrt(positionError2), std::sqrt(relativeMomentumError2) * hstep);
return std::max(std::sqrt(positionError2),
std::sqrt(relativeMomentumError2) * hstep);
}
G4double relativeError2(const G4double y[],
const G4double yerr[],
G4double h,
G4double eps_rel_max)
G4double h,
G4double eps_rel_max)
{
G4double errmax_sq;
G4double errmax_sq;
G4double inv_eps_vel_sq = 1.0 / (eps_rel_max * eps_rel_max);
G4double errvel_sq = 0.0; // square of momentum vector difference
G4double inv_eps_vel_sq = 1.0 / (eps_rel_max * eps_rel_max);
G4double errvel_sq = 0.0; // square of momentum vector difference
G4double eps_pos = eps_rel_max * h;
G4double inv_eps_pos_sq = 1.0 / (eps_pos * eps_pos);
G4double eps_pos = eps_rel_max * h;
G4double inv_eps_pos_sq = 1.0 / (eps_pos * eps_pos);
// Evaluate accuracy
G4double errpos_sq = getValue2(yerr, Value3D::Position);
errpos_sq *= inv_eps_pos_sq; // Scale relative to required tolerance
// Evaluate accuracy
//
G4double errpos_sq = getValue2(yerr, Value3D::Position);
errpos_sq *= inv_eps_pos_sq; // Scale relative to required tolerance
// Accuracy for momentum
G4double magvel_sq = getValue2(y, Value3D::Momentum);
G4double sumerr_sq = getValue2(yerr, Value3D::Momentum);
if (magvel_sq > 0.0)
{
errvel_sq = sumerr_sq / magvel_sq;
}
else
{
G4Exception("field_utils::relativeError","Field001",
JustWarning, "found case of zero momentum");
errvel_sq = sumerr_sq;
}
errvel_sq *= inv_eps_vel_sq;
errmax_sq = std::max(errpos_sq, errvel_sq);
// Accuracy for momentum
//
G4double magvel_sq = getValue2(y, Value3D::Momentum);
G4double sumerr_sq = getValue2(yerr, Value3D::Momentum);
if (magvel_sq > 0.0)
{
errvel_sq = sumerr_sq / magvel_sq;
}
else
{
G4Exception("field_utils::relativeError","Field001",
JustWarning, "found case of zero momentum");
errvel_sq = sumerr_sq;
}
errvel_sq *= inv_eps_vel_sq;
errmax_sq = std::max(errpos_sq, errvel_sq);
return errmax_sq;
return errmax_sq;
}
G4double relativeError(
const G4double y[],
const G4double yError[],
const G4double h,
const G4double errorTolerance)
G4double relativeError(const G4double y[],
const G4double yError[],
const G4double h,
const G4double errorTolerance)
{
return std::sqrt(relativeError2(y, yError, h, errorTolerance));
return std::sqrt(relativeError2(y, yError, h, errorTolerance));
}
void copy(G4double dst[], const G4double src[], size_t size)
{
memcpy(dst, src, sizeof(G4double) * size);
std::memcpy(dst, src, sizeof(G4double) * size);
}
G4double inverseCurvatureRadius(G4double particleCharge, G4double momentum, G4double BField)
G4double inverseCurvatureRadius(G4double particleCharge,
G4double momentum,
G4double BField)
{
return -c_light * particleCharge * BField / momentum;
return -c_light * particleCharge * BField / momentum;
}
} // field_utils
@@ -23,8 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4HarmonicPolMagField implementation
//
//
// Author: V.Grichine, 03.02.1997
// -------------------------------------------------------------------
#include "G4HarmonicPolMagField.hh"
@@ -36,21 +37,20 @@ G4HarmonicPolMagField::G4HarmonicPolMagField()
G4HarmonicPolMagField* G4HarmonicPolMagField::Clone() const
{
return new G4HarmonicPolMagField;
return new G4HarmonicPolMagField;
}
/////////////////////////////////////////////////////////////////////////
// -------------------------------------------------------------------
G4HarmonicPolMagField::~G4HarmonicPolMagField()
{
}
/////////////////////////////////////////////////////////////////////////
// -------------------------------------------------------------------
void G4HarmonicPolMagField::GetFieldValue(const G4double yTrack[7],
G4double B[3] ) const
{
G4int i ;
G4double a = 1.00 ; // mm -> m
G4double x = a*yTrack[0], y = a*yTrack[1], z = a*yTrack[2] ;
G4double x2 = x*x, y2 = y*y, z2 = z*z ;
@@ -59,13 +59,13 @@ void G4HarmonicPolMagField::GetFieldValue(const G4double yTrack[7],
static G4ThreadLocal G4double
c[24] = {
.010, .010, .010, // 3(0)
.0001, .0001, .0001, .0001, .0001, // 5(1)
.00001, .00001, .00001, .00001, .00001, .00001, .00001, // 7(2)
.000001, .000001, .000001, .000001, .000001, .000001,
.0000001, .0000001, .0000001 // 9(3)
.0001, .0001, .0001, .0001, .0001, // 5(1)
.00001, .00001, .00001, .00001, .00001, .00001, .00001, // 7(2)
.000001, .000001, .000001, .000001, .000001, .000001,
.0000001, .0000001, .0000001 // 9(3)
} ; // total : 24
// for(i=0;i<24;i++)
// for(auto i=0;i<24; ++i)
// {
// c[i] = 1.0*c[i] ;
// }
@@ -80,7 +80,7 @@ void G4HarmonicPolMagField::GetFieldValue(const G4double yTrack[7],
B[1] = c[2]
+c[5]*z + c[6]*x + 2*c[7]*y
+c[10]*(z2-x2) + c[11]*xz +2*c[12]*yz +2*c[13]*xy + 3*c[14]*(y2-x2)
+c[17]*(z3-3*x2*z) + c[18]*(x*z2-x3/3) +2*c[19]*y*(z2-x2)
+c[17]*(z3-3*x2*z) + c[18]*(x*z2-x3/3) +2*c[19]*y*(z2-x2)
+2*c[20]*xyz
+3*c[21]*z*(y2-x2) + c[22]*(3*x*y2-x3) + 4*c[23]*(y3-3*x2*y) ;
@@ -90,7 +90,7 @@ void G4HarmonicPolMagField::GetFieldValue(const G4double yTrack[7],
+4*c[15]*(z3-3*x2*z) + c[16]*(3*x*z2-x3) + 3*c[17]*(y*z2-x2*y)
+2*c[18]*xyz
+2*c[19]*z*(y2-x2) + c[20]*(x*y2-x3/3) + c[21]*(y3-3*x2*y) ;
for(i=0;i<3;i++)
for(auto i=0; i<3 ; ++i)
{
B[i] = 0.1*B[i] ;
}
@@ -23,55 +23,67 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// G4HelixExplicitEuler implementation
//
// Helix Explicit Euler: x_1 = x_0 + helix(h)
// with helix(h) being a helix piece of length h
// most simple approach for solving linear differential equations.
// with helix(h) being a helix piece of length h.
// 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
// Author: W.Wander <wwc@mit.edu>, 12.09.1997
// -------------------------------------------------------------------
#include "G4HelixExplicitEuler.hh"
#include "G4PhysicalConstants.hh"
#include "G4ThreeVector.hh"
void G4HelixExplicitEuler::Stepper( const G4double yInput[7],
const G4double*,
G4double Step,
G4double yOut[7],
G4double yErr[])
G4HelixExplicitEuler::G4HelixExplicitEuler(G4Mag_EqRhs* EqRhs)
: G4MagHelicalStepper(EqRhs)
{
}
G4HelixExplicitEuler::~G4HelixExplicitEuler()
{
}
//Estimation of the Stepping Angle
void G4HelixExplicitEuler::Stepper( const G4double yInput[7],
const G4double*,
G4double Step,
G4double yOut[7],
G4double yErr[] )
{
// Estimation of the Stepping Angle
//
G4ThreeVector Bfld;
MagFieldEvaluate(yInput, Bfld);
const G4int nvar = 6 ;
G4int i;
G4double yTemp[8], yIn[8] ;
G4double yTemp[8], yIn[8] ;
G4ThreeVector Bfld_midpoint;
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<nvar;i++) yIn[i]=yInput[i];
// Saving yInput because yInput and yOut can be aliases for same array
//
for(G4int i=0; i<nvar; ++i)
{
yIn[i] = yInput[i];
}
G4double h = Step * 0.5;
G4double h = Step * 0.5;
// Do full step and two half steps
G4double yTemp2[7];
AdvanceHelix(yIn, Bfld, h, yTemp2,yTemp);
MagFieldEvaluate(yTemp2, Bfld_midpoint) ;
AdvanceHelix(yTemp2, Bfld_midpoint, h, yOut);
// Error estimation
for(i=0;i<nvar;i++) {
yErr[i] = yOut[i] - yTemp[i] ;
}
// Do full step and two half steps
//
G4double yTemp2[7];
AdvanceHelix(yIn, Bfld, h, yTemp2,yTemp);
MagFieldEvaluate(yTemp2, Bfld_midpoint) ;
AdvanceHelix(yTemp2, Bfld_midpoint, h, yOut);
SetAngCurve(GetAngCurve() * 2);
// Error estimation
//
for(G4int i=0; i<nvar; ++i)
{
yErr[i] = yOut[i] - yTemp[i];
}
}
G4double G4HelixExplicitEuler::DistChord() const
@@ -83,28 +95,27 @@ G4double G4HelixExplicitEuler::DistChord() const
G4double distChord;
G4double Ang_curve=GetAngCurve();
if(Ang_curve<=pi){
distChord=GetRadHelix()*(1-std::cos(0.5*Ang_curve));
}
else
if(Ang_curve<twopi){
distChord=GetRadHelix()*(1+std::cos(0.5*(twopi-Ang_curve)));
}
else{
distChord=2.*GetRadHelix();
}
if(Ang_curve<=pi)
{
distChord=GetRadHelix()*(1-std::cos(0.5*Ang_curve));
}
else if(Ang_curve<twopi)
{
distChord=GetRadHelix()*(1+std::cos(0.5*(twopi-Ang_curve)));
}
else
{
distChord=2.*GetRadHelix();
}
return distChord;
}
void
G4HelixExplicitEuler::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[])
void G4HelixExplicitEuler::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[] )
{
AdvanceHelix(yIn, Bfld, h, yOut);
AdvanceHelix(yIn, Bfld, h, yOut);
}
@@ -23,35 +23,41 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4HelixHeum implementation
//
//
//
// Simple Heum:
// 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
// Author: W.Wander <wwc@mit.edu>, 03/11/1998
// -------------------------------------------------------------------
#include "G4HelixHeum.hh"
#include "G4ThreeVector.hh"
G4HelixHeum::G4HelixHeum(G4Mag_EqRhs* EqRhs)
: G4MagHelicalStepper(EqRhs)
{
}
G4HelixHeum::~G4HelixHeum()
{
}
void
G4HelixHeum::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[])
G4ThreeVector Bfld,
G4double h,
G4double yOut[])
{
const G4int nvar = 6 ;
G4ThreeVector Bfield_Temp, Bfield_Temp2;
G4double yTemp[6], yAdd1[6], yAdd2[6] , yTemp2[6];
G4int i;
AdvanceHelix( yIn, Bfld, h, yAdd1 );
AdvanceHelix( yIn, Bfld, h/3.0, yTemp );
@@ -63,7 +69,8 @@ G4HelixHeum::DumbStepper( const G4double yIn[],
AdvanceHelix( yIn, Bfield_Temp2, h, yAdd2 );
for( i = 0; i < nvar; i++ ) {
for( G4int i = 0; i < nvar; ++i )
{
yOut[i] = ( 0.25 * yAdd1[i] + 0.75 * yAdd2[i]);
}
@@ -23,8 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// G4HelixImplicitEuler implementation
//
// Helix Implicit Euler:
// x_1 = x_0 + 1/2 * ( helix(h,t_0,x_0)
@@ -34,37 +33,49 @@
// 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
//
// Author: W.Wander <wwc@mit.edu>, 03/11/1998
// -------------------------------------------------------------------------
#include "G4HelixImplicitEuler.hh"
#include "G4ThreeVector.hh"
G4HelixImplicitEuler::G4HelixImplicitEuler(G4Mag_EqRhs *EqRhs)
: G4MagHelicalStepper(EqRhs)
{
}
G4HelixImplicitEuler::~G4HelixImplicitEuler()
{
}
void
G4HelixImplicitEuler::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[])
G4HelixImplicitEuler::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[])
{
const G4int nvar = 6 ;
G4double yTemp[6], yTemp2[6];
G4ThreeVector Bfld_endpoint;
G4int i;
// Step forward like in the explicit euler case
//
AdvanceHelix( yIn, Bfld, h, yTemp);
// now obtain the new field value at the new point
//
MagFieldEvaluate(yTemp, Bfld_endpoint);
// and also advance along a helix for this field value
//
AdvanceHelix( yIn, Bfld_endpoint, h, yTemp2);
// we take the average
for( i = 0; i < nvar; i++ )
// we take the average
//
for( G4int i = 0; i < nvar; ++i )
{
yOut[i] = 0.5 * ( yTemp[i] + yTemp2[i] );
}
// NormaliseTangentVector( yOut );
}
@@ -33,9 +33,7 @@
// use Stepper for small step(ClassicalRK4 by default)
// Else use HelixExplicitEuler Stepper
//
// History:
// Derived from ExactHelicalStepper 18/05/07
//
// Created: T.Nikitina, CERN - 18.05.2007, derived from G4ExactHelicalStepper
// -------------------------------------------------------------------------
#include "G4HelixMixedStepper.hh"
@@ -52,7 +50,8 @@
#include "G4SimpleHeum.hh"
#include "G4RKG3_Stepper.hh"
#include "G4NystromRK4.hh"
// Additional potential stepper
// Additional potential steppers
#include "G4DormandPrince745.hh"
#include "G4BogackiShampine23.hh"
#include "G4BogackiShampine45.hh"
@@ -61,105 +60,122 @@
#include "G4ThreeVector.hh"
#include "G4LineSection.hh"
// ---------------------------------------------------------------------------
G4HelixMixedStepper::
G4HelixMixedStepper(G4Mag_EqRhs *EqRhs,
G4HelixMixedStepper(G4Mag_EqRhs* EqRhs,
G4int stepperNumber,
G4double angleThreshold)
: G4MagHelicalStepper(EqRhs), fNumCallsRK4(0), fNumCallsHelix(0)
: G4MagHelicalStepper(EqRhs)
{
SetVerbose(1);
if( angleThreshold < 0.0 ){
fAngle_threshold= (1.0/3.0)*pi;
}else{
fAngle_threshold= angleThreshold;
if( angleThreshold < 0.0 )
{
fAngle_threshold = (1.0/3.0)*pi;
}
else
{
fAngle_threshold = angleThreshold;
}
if(stepperNumber<0)
stepperNumber=4; // Default is RK4 (original)
// stepperNumber=745; // Default is DormandPrince745 (ie DoPri5)
// stepperNumber=8; // Default is CashKarp
{
// stepperNumber = 4; // Default is RK4 (original)
stepperNumber = 745; // Default is DormandPrince745 (ie DoPri5)
// stepperNumber = 8; // Default is CashKarp
}
fStepperNumber = stepperNumber; // Store the choice
fRK4Stepper = SetupStepper(EqRhs, fStepperNumber);
}
// ---------------------------------------------------------------------------
G4HelixMixedStepper::~G4HelixMixedStepper()
{
delete(fRK4Stepper);
if (fVerbose>0){ PrintCalls();};
delete fRK4Stepper;
if (fVerbose>0) { PrintCalls(); }
}
void G4HelixMixedStepper::Stepper( const G4double yInput[7],
const G4double dydx[7],
G4double Step,
G4double yOut[7],
G4double yErr[])
// ---------------------------------------------------------------------------
void G4HelixMixedStepper::Stepper( const G4double yInput[7],
const G4double dydx[7],
G4double Step,
G4double yOut[7],
G4double yErr[])
{
//Estimation of the Stepping Angle
// Estimation of the Stepping Angle
//
G4ThreeVector Bfld;
MagFieldEvaluate(yInput, Bfld);
G4double Bmag = Bfld.mag();
const G4double *pIn = yInput+3;
G4ThreeVector initVelocity= G4ThreeVector( pIn[0], pIn[1], pIn[2]);
G4double velocityVal = initVelocity.mag();
const G4double* pIn = yInput+3;
G4ThreeVector initVelocity = G4ThreeVector( pIn[0], pIn[1], pIn[2] );
G4double velocityVal = initVelocity.mag();
const G4double R_1=std::abs(GetInverseCurve(velocityVal,Bmag)); // curv= inverse Radius
G4double Ang_curve= R_1 * Step;
const G4double R_1 = std::abs(GetInverseCurve(velocityVal,Bmag));
// curv = inverse Radius
G4double Ang_curve = R_1 * Step;
// SetAngCurve(Ang_curve);
// SetCurve(std::abs(1/R_1)); // Move below, to avoid un-needed division if RK used
if(Ang_curve< fAngle_threshold)
// SetCurve(std::abs(1/R_1));
if(Ang_curve < fAngle_threshold)
{
fNumCallsRK4++;
++fNumCallsRK4;
fRK4Stepper->Stepper(yInput,dydx,Step,yOut,yErr);
}
else
{
constexpr G4int nvar = 6 ;
constexpr G4int nvarMax = 8 ;
G4double yTemp[nvarMax], yIn[nvarMax], yTemp2[nvarMax];
G4ThreeVector Bfld_midpoint;
constexpr G4int nvar = 6 ;
constexpr G4int nvarMax = 8 ;
G4double yTemp[nvarMax], yIn[nvarMax], yTemp2[nvarMax];
G4ThreeVector Bfld_midpoint;
SetAngCurve(Ang_curve);
SetCurve(std::abs(1.0/R_1));
fNumCallsHelix++;
++fNumCallsHelix;
// Saving yInput because yInput and yOut can be aliases for same array
for(G4int i=0;i<nvar;i++) yIn[i]=yInput[i];
// Saving yInput because yInput and yOut can be aliases for same array
//
for(G4int i=0; i<nvar; ++i)
{
yIn[i]=yInput[i];
}
G4double halfS = Step * 0.5;
// 1. Do first half step and full step
//
AdvanceHelix(yIn, Bfld, halfS, yTemp, yTemp2); // yTemp2 for s=2*h (halfS)
//**********
MagFieldEvaluate(yTemp, Bfld_midpoint) ;
// 2. Do second half step - with revised field
// NOTE: Could avoid this call if 'Bfld_midpoint == Bfld'
// or diff 'almost' zero
//
AdvanceHelix(yTemp, Bfld_midpoint, halfS, yOut);
// Not requesting y at s=2*h (halfS)
//**********
// Not requesting y at s=2*h (halfS)
// 3. Estimate the integration error
// should be (nearly) zero if Bfield= constant
for(G4int i=0;i<nvar;i++) {
yErr[i] = yOut[i] - yTemp2[i] ;
//
for(G4int i=0; i<nvar; ++i)
{
yErr[i] = yOut[i] - yTemp2[i];
}
}
}
void
G4HelixMixedStepper::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[])
// ---------------------------------------------------------------------------
void G4HelixMixedStepper::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[] )
{
AdvanceHelix(yIn, Bfld, h, yOut);
}
G4double G4HelixMixedStepper::DistChord() const
// ---------------------------------------------------------------------------
G4double G4HelixMixedStepper::DistChord() const
{
// Implementation : must check whether h/R > 2 pi !!
// If( h/R < pi) use G4LineSection::DistLine
@@ -168,15 +184,18 @@ G4double G4HelixMixedStepper::DistChord() const
G4double distChord;
G4double Ang_curve=GetAngCurve();
if(Ang_curve<=pi){
if(Ang_curve<=pi)
{
distChord=GetRadHelix()*(1-std::cos(0.5*Ang_curve));
}
else
{
if(Ang_curve<twopi){
if(Ang_curve<twopi)
{
distChord=GetRadHelix()*(1+std::cos(0.5*(twopi-Ang_curve)));
}
else{
else
{
distChord=2.*GetRadHelix();
}
}
@@ -192,13 +211,14 @@ void G4HelixMixedStepper::PrintCalls()
<< " and Number of calls to Helix = " << fNumCallsHelix << G4endl;
}
// ---------------------------------------------------------------------------
G4MagIntegratorStepper*
G4HelixMixedStepper::SetupStepper(G4Mag_EqRhs* pE, G4int StepperNumber)
{
G4MagIntegratorStepper* pStepper;
if (fVerbose>0) G4cout << " G4HelixMixedStepper: ";
switch ( StepperNumber )
{
{
// Robust, classic method
case 4:
pStepper = new G4ClassicalRK4( pE );
@@ -292,10 +312,13 @@ G4HelixMixedStepper::SetupStepper(G4Mag_EqRhs* pE, G4int StepperNumber)
pStepper = new G4DormandPrince745( pE ); // Was G4ClassicalRK4( pE );
if (fVerbose>0) G4cout << "G4DormandPrince745 (Default)";
break;
}
}
if(fVerbose>0)
{
G4cout << " chosen as stepper for small steps in G4HelixMixedStepper."
<< G4endl;
}
return pStepper;
}
@@ -23,8 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// G4HelixSimpleRunge implementation
//
// Simple Runge:
// x_1 = x_0 + h * ( dx( t_0+h/2, x_0 + h/2 * dx( t_0, x_0) ) )
@@ -33,17 +32,26 @@
// 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
// Author: W. Wander <wwc@mit.edu>, 03.12.1998
// -------------------------------------------------------------------------
#include "G4HelixSimpleRunge.hh"
#include "G4ThreeVector.hh"
G4HelixSimpleRunge::G4HelixSimpleRunge(G4Mag_EqRhs* EqRhs)
: G4MagHelicalStepper(EqRhs)
{
}
G4HelixSimpleRunge::~G4HelixSimpleRunge()
{
}
void
G4HelixSimpleRunge::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[])
G4HelixSimpleRunge::DumbStepper( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yOut[] )
{
const G4int nvar = 6 ;
G4double yTemp[nvar]; // , yAdd[nvar];
@@ -52,6 +60,7 @@ G4HelixSimpleRunge::DumbStepper( const G4double yIn[],
AdvanceHelix( yIn, Bfld, 0.5 * h, yTemp);
// now obtain the new field value at the new point
//
MagFieldEvaluate(yTemp, Bfld_midpoint);
AdvanceHelix( yIn, Bfld_midpoint, h, yOut);
@@ -23,8 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// G4ImplicitEuler implementation
//
// Implicit Euler:
//
@@ -35,8 +34,7 @@
// 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
//
// Author: W. Wander <wwc@mit.edu>, 12.09.1997
// --------------------------------------------------------------------
#include "G4ImplicitEuler.hh"
@@ -46,11 +44,11 @@
//
// Constructor
G4ImplicitEuler::G4ImplicitEuler(G4EquationOfMotion *EqRhs,
G4int numberOfVariables):
G4MagErrorStepper(EqRhs, numberOfVariables)
G4ImplicitEuler::G4ImplicitEuler(G4EquationOfMotion* EqRhs,
G4int numberOfVariables)
: G4MagErrorStepper(EqRhs, numberOfVariables)
{
unsigned int noVariables= std::max(numberOfVariables,8); // For Time .. 7+1
unsigned int noVariables = std::max(numberOfVariables,8); // For Time .. 7+1
dydxTemp = new G4double[noVariables] ;
yTemp = new G4double[noVariables] ;
}
@@ -59,40 +57,40 @@ G4MagErrorStepper(EqRhs, numberOfVariables)
////////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4ImplicitEuler::~G4ImplicitEuler()
{
delete[] dydxTemp;
delete[] yTemp;
delete [] dydxTemp;
delete [] yTemp;
}
//////////////////////////////////////////////////////////////////////
//
// DumbStepper
//
void
G4ImplicitEuler::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[])
G4ImplicitEuler::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[] )
{
G4int i;
const G4int numberOfVariables= GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
// Initialise time to t0, needed when it is not updated by the integration.
//
yTemp[7] = yOut[7] = yIn[7]; // Better to set it to NaN; // TODO
for( i = 0; i < numberOfVariables; i++ )
for( G4int i = 0; i < numberOfVariables; ++i )
{
yTemp[i] = yIn[i] + h*dydx[i] ;
}
RightHandSide(yTemp,dydxTemp);
for( i = 0; i < numberOfVariables; i++ )
for( G4int i = 0; i < numberOfVariables; ++i )
{
yOut[i] = yIn[i] + 0.5 * h * ( dydx[i] + dydxTemp[i] );
}
return ;
return;
}
@@ -23,6 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4LineCurrentMagField implementation
//
// Author: V.Grichine, 03.02.1997
// -------------------------------------------------------------------
#include "G4LineCurrentMagField.hh"
@@ -33,19 +36,20 @@ G4LineCurrentMagField::G4LineCurrentMagField(G4double pFieldConstant)
fFieldConstant = pFieldConstant ;
}
// -----------------------------------------------------------------
G4Field* G4LineCurrentMagField::Clone() const
{
return new G4LineCurrentMagField( fFieldConstant );
return new G4LineCurrentMagField( fFieldConstant );
}
////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------
G4LineCurrentMagField::~G4LineCurrentMagField()
{
}
///////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------
void G4LineCurrentMagField::GetFieldValue( const G4double yTrack[7],
G4double B[3] ) const
@@ -58,7 +62,7 @@ void G4LineCurrentMagField::GetFieldValue( const G4double yTrack[7],
G4double Br = fFieldConstant/r;
B[0] = -Br*y/r ;
B[1] = Br*x/r ;
B[2] = 0 ;
B[2] = 0.0 ;
}
// -----------------------------------------------------------------
@@ -23,12 +23,20 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4LineSection implementation
//
//
// Created: J.Apostolakis, 1999
// --------------------------------------------------------------------
#include "G4LineSection.hh"
G4LineSection::G4LineSection( const G4ThreeVector& PntA,
const G4ThreeVector& PntB )
: EndpointA(PntA), VecAtoB(PntB-PntA)
{
fABdistanceSq = VecAtoB.mag2();
}
G4double G4LineSection::Dist( G4ThreeVector OtherPnt ) const
{
G4double dist_sq;
@@ -62,7 +70,7 @@ G4double G4LineSection::Dist( G4ThreeVector OtherPnt ) const
}
else // B is the closest point
{
G4ThreeVector EndpointB = EndpointA + VecAtoB;
G4ThreeVector EndpointB = EndpointA + VecAtoB;
G4ThreeVector VecBZ = OtherPnt - EndpointB;
dist_sq = VecBZ.mag2();
}
@@ -23,8 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4MagErrorStepper implementation
//
//
// Author: W.Wander <wwc@mit.edu>, 09.12.1997
// --------------------------------------------------------------------
#include "G4MagErrorStepper.hh"
@@ -32,88 +33,95 @@
G4MagErrorStepper::~G4MagErrorStepper()
{
delete[] yMiddle;
delete[] dydxMid;
delete[] yInitial;
delete[] yOneStep;
delete [] yMiddle;
delete [] dydxMid;
delete [] yInitial;
delete [] yOneStep;
}
void
G4MagErrorStepper::Stepper( const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError [] )
void G4MagErrorStepper::Stepper( const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError [] )
{
const G4int nvar = this->GetNumberOfVariables() ;
const G4int maxvar= GetNumberOfStateVariables();
const G4int nvar = GetNumberOfVariables();
const G4int maxvar = GetNumberOfStateVariables();
G4int i;
// correction for Richardson Extrapolation.
//
G4double correction = 1. / ( (1 << IntegratorOrder()) -1 );
// Saving yInput because yInput and yOutput can be aliases for same array
for(i=0;i<nvar;i++) yInitial[i]=yInput[i];
yInitial[7]= yInput[7]; // Copy the time in case ... even if not really needed
//
for(G4int i=0; i<nvar; ++i)
{
yInitial[i]=yInput[i];
}
yInitial[7] = yInput[7]; // Copy the time in case...even if not really needed
yMiddle[7] = yInput[7]; // Copy the time from initial value
yOneStep[7] = yInput[7]; // As it contributes to final value of yOutput ?
// yOutput[7] = yInput[7]; // -> dumb stepper does it too for RK4
for(i=nvar;i<maxvar;i++) yOutput[i]=yInput[i];
for(G4int i=nvar; i<maxvar; ++i)
{
yOutput[i]=yInput[i];
}
// yError[7] = 0.0;
G4double halfStep = hstep * 0.5;
// Do two half steps
//
DumbStepper (yInitial, dydx, halfStep, yMiddle);
RightHandSide(yMiddle, dydxMid);
DumbStepper (yMiddle, dydxMid, halfStep, yOutput);
// Store midpoint, chord calculation
//
fMidPoint = G4ThreeVector( yMiddle[0], yMiddle[1], yMiddle[2]);
// Do a full Step
//
DumbStepper(yInitial, dydx, hstep, yOneStep);
for(i=0;i<nvar;i++) {
for(G4int i=0; i<nvar; ++i)
{
yError [i] = yOutput[i] - yOneStep[i] ;
yOutput[i] += yError[i]*correction ; // Provides accuracy increased
// by 1 order via the
// Richardson Extrapolation
yOutput[i] += yError[i]*correction ;
// Provides accuracy increased by 1 order via Richardson Extrapolation
}
fInitialPoint = G4ThreeVector( yInitial[0], yInitial[1], yInitial[2]);
fFinalPoint = G4ThreeVector( yOutput[0], yOutput[1], yOutput[2]);
return ;
return;
}
G4double
G4MagErrorStepper::DistChord() const
G4double G4MagErrorStepper::DistChord() const
{
// Estimate the maximum distance from the curve to the chord
//
// We estimate this using the distance of the midpoint to
// chord (the line between
// We estimate this using the distance of the midpoint to
// chord (the line between
//
// Method below is good only for angle deviations < 2 pi,
// This restriction should not a problem for the Runge cutta methods,
// which generally cannot integrate accurately for large angle deviations.
// Method below is good only for angle deviations < 2 pi,
// This restriction should not a problem for the Runge cutta methods,
// which generally cannot integrate accurately for large angle deviations.
G4double distLine, distChord;
if (fInitialPoint != fFinalPoint) {
distLine= G4LineSection::Distline( fMidPoint, fInitialPoint, fFinalPoint );
// This is a class method that gives distance of Mid
// from the Chord between the Initial and Final points.
if (fInitialPoint != fFinalPoint)
{
distLine = G4LineSection::Distline(fMidPoint, fInitialPoint, fFinalPoint);
// This is a class method that gives distance of Mid
// from the Chord between the Initial and Final points.
distChord = distLine;
}else{
}
else
{
distChord = (fMidPoint-fInitialPoint).mag();
}
return distChord;
}
@@ -23,8 +23,13 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4MagHelicalStepper implementation
//
// 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
//
// Created: J.Apostolakis, CERN - 05.11.1998
// --------------------------------------------------------------------
#include "G4MagHelicalStepper.hh"
@@ -33,20 +38,14 @@
#include "G4LineSection.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
// Constant for determining unit conversion when using normal as integrand.
//
const G4double G4MagHelicalStepper::fUnitConstant = 0.299792458*(GeV/(tesla*m));
G4MagHelicalStepper::G4MagHelicalStepper(G4Mag_EqRhs *EqRhs)
: G4MagIntegratorStepper(EqRhs, 6), // integrate over 6 variables only !!
// position & velocity
fPtrMagEqOfMot(EqRhs), fAngCurve(0.), frCurve(0.), frHelix(0.)
fPtrMagEqOfMot(EqRhs)
{
}
@@ -55,11 +54,11 @@ G4MagHelicalStepper::~G4MagHelicalStepper()
}
void
G4MagHelicalStepper::AdvanceHelix( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yHelix[],
G4double yHelix2[] )
G4MagHelicalStepper::AdvanceHelix( const G4double yIn[],
G4ThreeVector Bfld,
G4double h,
G4double yHelix[],
G4double yHelix2[] )
{
// const G4int nvar = 6;
@@ -79,12 +78,12 @@ G4MagHelicalStepper::AdvanceHelix( const G4double yIn[],
G4ThreeVector positionMove, endTangent;
G4double Bmag = Bfld.mag();
const G4double *pIn = yIn+3;
G4ThreeVector initVelocity= G4ThreeVector( pIn[0], pIn[1], pIn[2]);
const G4double* pIn = yIn+3;
G4ThreeVector initVelocity = G4ThreeVector( pIn[0], pIn[1], pIn[2]);
G4double velocityVal = initVelocity.mag();
G4ThreeVector initTangent = (1.0/velocityVal) * initVelocity;
R_1=GetInverseCurve(velocityVal,Bmag);
R_1 = GetInverseCurve(velocityVal,Bmag);
// for too small magnetic fields there is no curvature
// (include momentum here) FIXME
@@ -182,11 +181,9 @@ G4MagHelicalStepper::AdvanceHelix( const G4double yIn[],
}
}
// Use the midpoint method to get an error estimate and correction
// modified from G4ClassicalRK4: W.Wander <wwc@mit.edu> 12/09/97
//
// 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*,
@@ -196,8 +193,6 @@ G4MagHelicalStepper::Stepper( const G4double yInput[],
{
const G4int nvar = 6;
G4int i;
// correction for Richardson Extrapolation.
// G4double correction = 1. / ( (1 << IntegratorOrder()) -1 );
@@ -205,27 +200,30 @@ G4MagHelicalStepper::Stepper( const G4double yInput[],
G4ThreeVector Bfld_initial, Bfld_midpoint;
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<nvar;i++) { yIn[i]=yInput[i]; }
//
for(G4int i=0; i<nvar; ++i)
{
yIn[i]=yInput[i];
}
G4double h = hstep * 0.5;
MagFieldEvaluate(yIn, Bfld_initial) ;
// Do two half steps
DumbStepper(yIn, Bfld_initial, h, yTemp);
//
DumbStepper(yIn, Bfld_initial, h, yTemp);
MagFieldEvaluate(yTemp, Bfld_midpoint) ;
DumbStepper(yTemp, Bfld_midpoint, h, yOut);
// Do a full Step
//
h = hstep ;
DumbStepper(yIn, Bfld_initial, h, yTemp);
// Error estimation
for(i=0;i<nvar;i++)
//
for(G4int i=0; i<nvar; ++i)
{
yErr[i] = yOut[i] - yTemp[i] ;
}
@@ -23,19 +23,11 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4MagInt_Driver implementation
//
//
//
//
// Implementation for class G4MagInt_Driver
// Tracking in space dependent magnetic field
//
// History of major changes:
// 8 Nov 01 J. Apostolakis: Respect minimum step in AccurateAdvance
// 27 Jul 99 J. Apostolakis: Ensured that AccurateAdvance does not loop
// due to very small eps & step size (precision)
// 28 Jan 98 W. Wander: Added ability for low order integrators
// 7 Oct 96 V. Grichine First version
// V.Grichine, 07.10.1996 - Created
// W.Wander, 28.01.1998 - Added ability for low order integrators
// J.Apostolakis, 08.11.2001 - Respect minimum step in AccurateAdvance
// --------------------------------------------------------------------
#include <iomanip>
@@ -51,31 +43,18 @@
// Constructor
//
G4MagInt_Driver::G4MagInt_Driver( G4double hminimum,
G4MagIntegratorStepper *pStepper,
G4MagIntegratorStepper* pStepper,
G4int numComponents,
G4int statisticsVerbose)
: fSmallestFraction( 1.0e-12 ),
fNoIntegrationVariables(numComponents),
fMinNoVars(12),
: fNoIntegrationVariables(numComponents),
fNoVars( std::max( fNoIntegrationVariables, fMinNoVars )),
fStatisticsVerboseLevel(statisticsVerbose),
fNoTotalSteps(0), fNoBadSteps(0), fNoSmallSteps(0),
fNoInitialSmallSteps(0), fNoCalls(0),
fDyerr_max(0.0), fDyerr_mx2(0.0),
fDyerrPos_smTot(0.0), fDyerrPos_lgTot(0.0), fDyerrVel_lgTot(0.0),
fSumH_sm(0.0), fSumH_lg(0.0),
fVerboseLevel(0)
fStatisticsVerboseLevel(statisticsVerbose)
{
// In order to accomodate "Laboratory Time", which is [7], fMinNoVars=8
// is required. For proper time of flight and spin, fMinNoVars must be 12
RenewStepperAndAdjust( pStepper );
fMinimumStep= hminimum;
// The (default) maximum number of steps is Base
// divided by the order of Stepper
//
fMaxStepBase = 250; // Was 5000
fMinimumStep = hminimum;
fMaxNoSteps = fMaxStepBase / pIntStepper->IntegratorOrder();
#ifdef G4DEBUG_FIELD
@@ -111,9 +90,9 @@ G4MagInt_Driver::~G4MagInt_Driver()
G4bool
G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
G4double hstep,
G4double eps,
G4double hinitial )
G4double hstep,
G4double eps,
G4double hinitial )
{
// Runge-Kutta driver with adaptive stepsize control. Integrate starting
// values at y_current over hstep x2 with accuracy eps.
@@ -121,12 +100,12 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
// interval. RightHandSide is the right-hand side of ODE system.
// The source is similar to odeint routine from NRC p.721-722 .
G4int nstp, i, no_warnings=0;
G4int nstp, i, no_warnings = 0;
G4double x, hnext, hdid, h;
#ifdef G4DEBUG_FIELD
static G4int dbg=1;
static G4int nStpPr=50; // For debug printing of long integrations
static G4int dbg = 1;
static G4int nStpPr = 50; // For debug printing of long integrations
G4double ySubStepStart[G4FieldTrack::ncompSVEC];
G4FieldTrack yFldTrkStart(y_current);
#endif
@@ -138,9 +117,9 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
G4double startCurveLength;
G4int noFullIntegr=0, noSmallIntegr = 0 ;
static G4ThreadLocal G4int noGoodSteps =0 ; // Bad = chord > curve-len
const G4int nvar= fNoVars;
G4int noFullIntegr = 0, noSmallIntegr = 0;
static G4ThreadLocal G4int noGoodSteps = 0; // Bad = chord > curve-len
const G4int nvar = fNoVars;
G4FieldTrack yStartFT(y_current);
@@ -148,7 +127,7 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
//
if( hstep <= 0.0 )
{
if(hstep==0.0)
if( hstep == 0.0 )
{
std::ostringstream message;
message << "Proposed step is zero; hstep = " << hstep << " !";
@@ -186,10 +165,10 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
x = x1;
for (i=0;i<nvar;i++) { y[i] = ystart[i]; }
for ( i=0; i<nvar; ++i) { y[i] = ystart[i]; }
G4bool lastStep= false;
nstp=1;
nstp = 1;
do
{
@@ -197,13 +176,13 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
#ifdef G4DEBUG_FIELD
G4double xSubStepStart= x;
for (i=0;i<nvar;i++) { ySubStepStart[i] = y[i]; }
for (i=0; i<nvar; ++i) { ySubStepStart[i] = y[i]; }
yFldTrkStart.LoadFromArray(y, fNoIntegrationVariables);
yFldTrkStart.SetCurveLength(x);
#endif
pIntStepper->RightHandSide( y, dydx );
fNoTotalSteps++;
++fNoTotalSteps;
// Perform the Integration
//
@@ -211,7 +190,7 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
{
OneGoodStep(y,dydx,x,h,eps,hdid,hnext) ;
//--------------------------------------
lastStepSucceeded= (hdid == h);
lastStepSucceeded = (hdid == h);
#ifdef G4DEBUG_FIELD
if (dbg>2)
{
@@ -227,17 +206,17 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
yFldTrk.LoadFromArray(y, fNoIntegrationVariables);
yFldTrk.SetCurveLength( x );
QuickAdvance( yFldTrk, dydx, h, UNKNOWN_CURVATURE_RADIUS, dchord_step, dyerr_len );
QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len );
//-----------------------------------------------------
yFldTrk.DumpToArray(y);
#ifdef G4FLD_STATS
fNoSmallSteps++;
if ( dyerr_len > fDyerr_max) { fDyerr_max= dyerr_len; }
++fNoSmallSteps;
if ( dyerr_len > fDyerr_max ) { fDyerr_max = dyerr_len; }
fDyerrPos_smTot += dyerr_len;
fSumH_sm += h; // Length total for 'small' steps
if (nstp<=1) { fNoInitialSmallSteps++; }
if (nstp<=1) { ++fNoInitialSmallSteps; }
#endif
#ifdef G4DEBUG_FIELD
if (dbg>1)
@@ -258,18 +237,18 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
"Integration Step became Zero!");
}
dyerr = dyerr_len / h;
hdid= h;
hdid = h;
x += hdid;
// Compute suggested new step
hnext= ComputeNewStepSize( dyerr/eps, h);
hnext = ComputeNewStepSize( dyerr/eps, h);
// .. hnext= ComputeNewStepSize_WithinLimits( dyerr/eps, h);
lastStepSucceeded= (dyerr<= eps);
lastStepSucceeded = (dyerr<= eps);
}
if (lastStepSucceeded) { noFullIntegr++; }
else { noSmallIntegr++; }
if (lastStepSucceeded) { ++noFullIntegr; }
else { ++noSmallIntegr; }
G4ThreeVector EndPos( y[0], y[1], y[2] );
@@ -280,8 +259,8 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
G4cout << "MagIntDrv: " ;
G4cout << "hdid=" << std::setw(12) << hdid << " "
<< "hnext=" << std::setw(12) << hnext << " "
<< "hstep=" << std::setw(12) << hstep << " (requested) "
<< G4endl;
<< "hstep=" << std::setw(12) << hstep << " (requested) "
<< G4endl;
PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp);
}
#endif
@@ -290,7 +269,7 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
G4double endPointDist= (EndPos-StartPos).mag();
if ( endPointDist >= hdid*(1.+perMillion) )
{
fNoBadSteps++;
++fNoBadSteps;
// Issue a warning only for gross differences -
// we understand how small difference occur.
@@ -306,12 +285,12 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
}
#endif
no_warnings++;
++no_warnings;
}
}
else
{
noGoodSteps ++;
++noGoodSteps;
}
// #endif
@@ -336,7 +315,7 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
WarnSmallStepSize( hnext, hstep, h, x-x1, nstp );
PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp);
}
no_warnings++;
++no_warnings;
}
#endif
// Make sure that the next step is at least Hmin.
@@ -365,7 +344,7 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
<< G4endl
<< " Integration step 'h' became "
<< h << " due to roundoff. " << G4endl
<< " Calculated as difference of x2= "<< x2 << " and x=" << x
<< " Calculated as difference of x2= "<< x2 << " and x=" << x
<< " Forcing termination of advance." << G4endl;
G4cout.precision(prec);
}
@@ -378,9 +357,9 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
// Have we reached the end ?
// --> a better test might be x-x2 > an_epsilon
succeeded= (x>=x2); // If it was a "forced" last step
succeeded = (x>=x2); // If it was a "forced" last step
for (i=0;i<nvar;i++) { yEnd[i] = y[i]; }
for (i=0; i<nvar; ++i) { yEnd[i] = y[i]; }
// Put back the values.
y_current.LoadFromArray( yEnd, fNoIntegrationVariables );
@@ -388,7 +367,7 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
if(nstp > fMaxNoSteps)
{
no_warnings++;
++no_warnings;
succeeded = false;
#ifdef G4DEBUG_FIELD
if (dbg)
@@ -417,8 +396,8 @@ G4MagInt_Driver::WarnSmallStepSize( G4double hnext, G4double hstep,
G4double h, G4double xDone,
G4int nstp)
{
static G4ThreadLocal G4int noWarningsIssued =0;
const G4int maxNoWarnings = 10; // Number of verbose warnings
static G4ThreadLocal G4int noWarningsIssued = 0;
const G4int maxNoWarnings = 10; // Number of verbose warnings
std::ostringstream message;
if( (noWarningsIssued < maxNoWarnings) || fVerboseLevel > 10 )
{
@@ -439,7 +418,7 @@ G4MagInt_Driver::WarnSmallStepSize( G4double hnext, G4double hstep,
}
G4Exception("G4MagInt_Driver::WarnSmallStepSize()", "GeomField1001",
JustWarning, message);
noWarningsIssued++;
++noWarningsIssued;
}
// ---------------------------------------------------------
@@ -447,27 +426,27 @@ G4MagInt_Driver::WarnSmallStepSize( G4double hnext, G4double hstep,
void
G4MagInt_Driver::WarnTooManyStep( G4double x1start,
G4double x2end,
G4double xCurrent)
G4double xCurrent )
{
std::ostringstream message;
message << "The number of steps used in the Integration driver"
<< " (Runge-Kutta) is too many." << G4endl
<< "Integration of the interval was not completed !" << G4endl
<< "Only a " << (xCurrent-x1start)*100/(x2end-x1start)
<< " % fraction of it was done.";
G4Exception("G4MagInt_Driver::WarnTooManyStep()", "GeomField1001",
JustWarning, message);
std::ostringstream message;
message << "The number of steps used in the Integration driver"
<< " (Runge-Kutta) is too many." << G4endl
<< "Integration of the interval was not completed !" << G4endl
<< "Only a " << (xCurrent-x1start)*100/(x2end-x1start)
<< " % fraction of it was done.";
G4Exception("G4MagInt_Driver::WarnTooManyStep()", "GeomField1001",
JustWarning, message);
}
// ---------------------------------------------------------
void
G4MagInt_Driver::WarnEndPointTooFar (G4double endPointDist,
G4double h ,
G4double eps,
G4int dbg)
G4double h ,
G4double eps,
G4int dbg)
{
static G4ThreadLocal G4double maxRelError=0.0;
static G4ThreadLocal G4double maxRelError = 0.0;
G4bool isNewMax, prNewMax;
isNewMax = endPointDist > (1.0 + maxRelError) * h;
@@ -479,7 +458,7 @@ G4MagInt_Driver::WarnEndPointTooFar (G4double endPointDist,
{
static G4ThreadLocal G4int noWarnings = 0;
std::ostringstream message;
if( (noWarnings ++ < 10) || (dbg>2) )
if( (noWarnings++ < 10) || (dbg>2) )
{
message << "The integration produced an end-point which " << G4endl
<< "is further from the start-point than the curve length."
@@ -529,22 +508,20 @@ G4MagInt_Driver::OneGoodStep( G4double y[], // InOut
G4double inv_eps_vel_sq = 1.0 / (eps_rel_max*eps_rel_max);
G4double errpos_sq=0.0; // square of displacement error
G4double errvel_sq=0.0; // square of momentum vector difference
G4double errspin_sq=0.0; // square of spin vector difference
G4int iter;
G4double errpos_sq = 0.0; // square of displacement error
G4double errvel_sq = 0.0; // square of momentum vector difference
G4double errspin_sq = 0.0; // square of spin vector difference
static G4ThreadLocal G4int tot_no_trials=0;
const G4int max_trials=100;
G4ThreeVector Spin(y[9],y[10],y[11]);
G4double spin_mag2 =Spin.mag2() ;
G4bool hasSpin= (spin_mag2 > 0.0);
G4double spin_mag2 = Spin.mag2();
G4bool hasSpin = (spin_mag2 > 0.0);
for (iter=0; iter<max_trials ;iter++)
for (G4int iter=0; iter<max_trials; ++iter)
{
tot_no_trials++;
++tot_no_trials;
pIntStepper-> Stepper(y,dydx,h,ytemp,yerr);
// *******
G4double eps_pos = eps_rel_max * std::max(h, fMinimumStep);
@@ -586,7 +563,7 @@ G4MagInt_Driver::OneGoodStep( G4double y[], // InOut
if ( errmax_sq <= 1.0 ) { break; } // Step succeeded.
// Step failed; compute the size of retrial Step.
htemp = GetSafety()*h* std::pow( errmax_sq, 0.5*GetPshrnk() );
htemp = GetSafety() * h * std::pow( errmax_sq, 0.5*GetPshrnk() );
if (htemp >= 0.1*h) { h = htemp; } // Truncation error too large,
else { h = 0.1*h; } // reduce stepsize, but no more
@@ -617,7 +594,7 @@ G4MagInt_Driver::OneGoodStep( G4double y[], // InOut
}
x += (hdid = h);
for(G4int k=0;k<fNoIntegrationVariables;k++) { y[k] = ytemp[k]; }
for(G4int k=0; k<fNoIntegrationVariables; ++k) { y[k] = ytemp[k]; }
return;
}
@@ -626,18 +603,18 @@ G4MagInt_Driver::OneGoodStep( G4double y[], // InOut
// 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_pos_sq,
G4double& dyerr_mom_rel_sq )
G4bool G4MagInt_Driver::QuickAdvance(G4FieldTrack& y_posvel, // INOUT
const G4double dydx[],
G4double hstep, // In
G4double& dchord_step,
G4double& dyerr_pos_sq,
G4double& dyerr_mom_rel_sq )
{
G4Exception("G4MagInt_Driver::QuickAdvance()", "GeomField0001",
FatalException, "Not yet implemented.");
// Use the parameters of this method, to please compiler
//
dchord_step = dyerr_pos_sq = hstep * hstep * dydx[0];
dyerr_mom_rel_sq = y_posvel.GetPosition().mag2();
return true;
@@ -645,13 +622,11 @@ G4bool G4MagInt_Driver::QuickAdvance(
//----------------------------------------------------------------------
G4bool G4MagInt_Driver::QuickAdvance(
G4FieldTrack& y_posvel, // INOUT
const G4double dydx[],
G4double hstep, // In
G4double /*inverseCurvatureRadius*/,
G4double& dchord_step,
G4double& dyerr )
G4bool G4MagInt_Driver::QuickAdvance(G4FieldTrack& y_posvel, // INOUT
const G4double dydx[],
G4double hstep, // In
G4double& dchord_step,
G4double& dyerr )
{
G4double dyerr_pos_sq, dyerr_mom_rel_sq;
G4double yerr_vec[G4FieldTrack::ncompSVEC],
@@ -659,8 +634,8 @@ G4bool G4MagInt_Driver::QuickAdvance(
G4double s_start;
G4double dyerr_mom_sq, vel_mag_sq, inv_vel_mag_sq;
static G4ThreadLocal G4int no_call=0;
no_call ++;
static G4ThreadLocal G4int no_call = 0;
++no_call;
// Move data into array
y_posvel.DumpToArray( yarrin ); // yarrin <== y_posvel
@@ -705,7 +680,7 @@ G4bool G4MagInt_Driver::QuickAdvance(
// sqr(yerr_vec[3])+sqr(yerr_vec[4])+sqr(yerr_vec[5]));
// Set suggested new step
hstep= ComputeNewStepSize( dyerr_len, hstep);
hstep = ComputeNewStepSize( dyerr_len, hstep);
#endif
if( dyerr_pos_sq > ( dyerr_mom_rel_sq * sqr(hstep) ) )
@@ -724,13 +699,12 @@ G4bool G4MagInt_Driver::QuickAdvance(
// --------------------------------------------------------------------------
#ifdef QUICK_ADV_ARRAY_IN_AND_OUT
G4bool G4MagInt_Driver::QuickAdvance(
G4double yarrin[], // In
const G4double dydx[],
G4double hstep, // In
G4double yarrout[],
G4double& dchord_step,
G4double& dyerr ) // In length
G4bool G4MagInt_Driver::QuickAdvance(G4double yarrin[], // In
const G4double dydx[],
G4double hstep, // In
G4double yarrout[],
G4double& dchord_step,
G4double& dyerr ) // In length
{
G4Exception("G4MagInt_Driver::QuickAdvance()", "GeomField0001",
FatalException, "Not yet implemented.");
@@ -741,8 +715,8 @@ G4bool G4MagInt_Driver::QuickAdvance(
// --------------------------------------------------------------------------
// This method computes new step sizes - but does not limit changes to
// within certain factors
// This method computes new step sizes - but does not limit changes to
// within certain factors
//
G4double G4MagInt_Driver::
ComputeNewStepSize(G4double errMaxNorm, // max error (normalised)
@@ -810,12 +784,12 @@ G4MagInt_Driver::ComputeNewStepSize_WithinLimits(
// ---------------------------------------------------------------------------
void G4MagInt_Driver::PrintStatus( const G4double* StartArr,
G4double xstart,
const G4double* CurrentArr,
G4double xcurrent,
G4double requestStep,
G4int subStepNo)
void G4MagInt_Driver::PrintStatus( const G4double* StartArr,
G4double xstart,
const G4double* CurrentArr,
G4double xcurrent,
G4double requestStep,
G4int subStepNo )
// Potentially add as arguments:
// <dydx> - as Initial Force
// stepTaken(hdid) - last step taken
@@ -835,11 +809,10 @@ void G4MagInt_Driver::PrintStatus( const G4double* StartArr,
// ---------------------------------------------------------------------------
void G4MagInt_Driver::PrintStatus(
const G4FieldTrack& StartFT,
const G4FieldTrack& CurrentFT,
G4double requestStep,
G4int subStepNo)
void G4MagInt_Driver::PrintStatus(const G4FieldTrack& StartFT,
const G4FieldTrack& CurrentFT,
G4double requestStep,
G4int subStepNo)
{
G4int verboseLevel= fVerboseLevel;
const G4int noPrecision = 5;
@@ -899,16 +872,15 @@ void G4MagInt_Driver::PrintStatus(
// ---------------------------------------------------------------------------
void G4MagInt_Driver::PrintStat_Aux(
const G4FieldTrack& aFieldTrack,
G4double requestStep,
G4double step_len,
G4int subStepNo,
G4double subStepSize,
G4double dotVeloc_StartCurr)
void G4MagInt_Driver::PrintStat_Aux(const G4FieldTrack& aFieldTrack,
G4double requestStep,
G4double step_len,
G4int subStepNo,
G4double subStepSize,
G4double dotVeloc_StartCurr)
{
const G4ThreeVector Position= aFieldTrack.GetPosition();
const G4ThreeVector UnitVelocity= aFieldTrack.GetMomentumDir();
const G4ThreeVector Position = aFieldTrack.GetPosition();
const G4ThreeVector UnitVelocity = aFieldTrack.GetMomentumDir();
if( subStepNo >= 0)
{
@@ -934,11 +906,11 @@ void G4MagInt_Driver::PrintStat_Aux(
G4cout << std::setw( 7) << aFieldTrack.GetKineticEnergy();
G4cout << std::setw(12) << step_len << " ";
static G4ThreadLocal G4double oldCurveLength= 0.0;
static G4ThreadLocal G4double oldSubStepLength= 0.0;
static G4ThreadLocal G4int oldSubStepNo= -1;
static G4ThreadLocal G4double oldCurveLength = 0.0;
static G4ThreadLocal G4double oldSubStepLength = 0.0;
static G4ThreadLocal G4int oldSubStepNo = -1;
G4double subStep_len=0.0;
G4double subStep_len = 0.0;
if( curveLen > oldCurveLength )
{
subStep_len= curveLen - oldCurveLength;
@@ -967,8 +939,8 @@ void G4MagInt_Driver::PrintStat_Aux(
void G4MagInt_Driver::PrintStatisticsReport()
{
G4int noPrecBig= 6;
G4int oldPrec= G4cout.precision(noPrecBig);
G4int noPrecBig = 6;
G4int oldPrec = G4cout.precision(noPrecBig);
G4cout << "G4MagInt_Driver Statistics of steps undertaken. " << G4endl;
G4cout << "G4MagInt_Driver: Number of Steps: "
@@ -1004,8 +976,9 @@ GetDerivatives(const G4FieldTrack& y_curr, G4double* dydx) const
{
G4double ytemp[G4FieldTrack::ncompSVEC];
y_curr.DumpToArray(ytemp);
pIntStepper->RightHandSide(ytemp, dydx); // Avoid virtual call for GetStepper
// Was: GetStepper()->ComputeRightHandSide(ytemp, dydx);
pIntStepper->RightHandSide(ytemp, dydx);
// Avoid virtual call for GetStepper
// Was: GetStepper()->ComputeRightHandSide(ytemp, dydx);
}
void G4MagInt_Driver::GetDerivatives(const G4FieldTrack& track,
@@ -1038,7 +1011,7 @@ G4MagIntegratorStepper* G4MagInt_Driver::GetStepper()
}
void G4MagInt_Driver::
RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper)
RenewStepperAndAdjust(G4MagIntegratorStepper* pItsStepper)
{
pIntStepper = pItsStepper;
ReSetParameters();
@@ -23,28 +23,24 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4MagIntegratorStepper implementation
//
//
// Author: J.Apostolakis, CERN - 15.01.1997
// --------------------------------------------------------------------
#include "G4MagIntegratorStepper.hh"
// Constructor for stepper abstract base class.
//
G4MagIntegratorStepper::G4MagIntegratorStepper(G4EquationOfMotion* Equation,
G4int num_integration_vars,
G4int num_state_vars,
bool isFSAL
// , G4int methodOrder
)
//
G4MagIntegratorStepper::
G4MagIntegratorStepper( G4EquationOfMotion* Equation,
G4int num_integration_vars,
G4int num_state_vars,
G4bool isFSAL )
: fEquation_Rhs(Equation),
fNoIntegrationVariables(num_integration_vars),
fNoStateVariables(std::max(num_state_vars,8)),
fNoRHSCalls( 0UL ),
fIntegrationOrder( -1 ), // Invalid value -- must be set by stepper !!!
fIsFSAL(isFSAL)
{
}
@@ -23,17 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4Mag_EqRhs implementation
//
//
// 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
//
// Created: J.Apostolakis, CERN - 13.01.1997
// --------------------------------------------------------------------
#include "G4MagneticField.hh"
@@ -44,22 +36,22 @@
const G4double G4Mag_EqRhs::fUnitConstant = 0.299792458 * (GeV/(tesla*m));
// Constructor Implementation
//
G4Mag_EqRhs::G4Mag_EqRhs( G4MagneticField *magField )
: G4EquationOfMotion(magField), fCof_val(0.)
G4Mag_EqRhs::G4Mag_EqRhs( G4MagneticField* magField )
: G4EquationOfMotion(magField)
{
}
G4Mag_EqRhs::~G4Mag_EqRhs()
{
}
void
G4Mag_EqRhs::SetChargeMomentumMass( G4ChargeState particleCharge,
G4double, // MomentumXc
G4double, // MomentumXc
G4double ) // particleMass
{
G4double pcharge = particleCharge.GetCharge();
fCof_val = pcharge*eplus*c_light ; // B must be in Tesla
// fCof_val = fUnitConstant*pcharge/MomentumXc; // B must be in Tesla
// fCof_val = fUnitConstant*pcharge/MomentumXc; // B must be in Tesla
// fMass = particleMass;
}
G4Mag_EqRhs::~G4Mag_EqRhs() { }
@@ -23,16 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4Mag_SpinEqRhs implementation
//
//
// This is the standard right-hand side for equation of motion.
// This version of the right-hand side includes the three components
// of the particle's spin.
//
// J. Apostolakis, February 8th, 1999
// P. Gumplinger, February 8th, 1999
// D. Cote-Ahern, P. Gumplinger, April 11th, 2001
//
// Created: J.Apostolakis, P.Gumplinger - 08.02.1999
// --------------------------------------------------------------------
#include "G4Mag_SpinEqRhs.hh"
@@ -42,8 +35,7 @@
#include "G4ThreeVector.hh"
G4Mag_SpinEqRhs::G4Mag_SpinEqRhs( G4MagneticField* MagField )
: G4Mag_EqRhs( MagField ), charge(0.), mass(0.), magMoment(0.),
spin(0.), omegac(0.), anomaly(0.0011659208), beta(0.), gamma(0.)
: G4Mag_EqRhs( MagField )
{
}
@@ -91,11 +83,14 @@ G4Mag_SpinEqRhs::EvaluateRhsGivenB( const G4double y[],
dydx[1] = y[4] * inv_momentum_magnitude; // (d/ds)y = Vy/V
dydx[2] = y[5] * inv_momentum_magnitude; // (d/ds)z = Vz/V
if (charge == 0.) {
if (charge == 0.)
{
dydx[3] = 0.;
dydx[4] = 0.;
dydx[5] = 0.;
} else {
}
else
{
dydx[3] = cof*(y[4]*B[2] - y[5]*B[1]) ; // Ax = a*(Vy*Bz - Vz*By)
dydx[4] = cof*(y[5]*B[0] - y[3]*B[2]) ; // Ay = a*(Vz*Bx - Vx*Bz)
dydx[5] = cof*(y[3]*B[1] - y[4]*B[0]) ; // Az = a*(Vx*By - Vy*Bx)
@@ -115,17 +110,24 @@ G4Mag_SpinEqRhs::EvaluateRhsGivenB( const G4double y[],
G4ThreeVector Spin(y[9],y[10],y[11]);
G4double pcharge;
if (charge == 0.) pcharge = 1.;
else pcharge = charge;
G4ThreeVector dSpin(0.,0.,0.);
if (Spin.mag2() != 0.) {
dSpin = pcharge*omegac*(ucb*(Spin.cross(BField))-udb*(Spin.cross(u)));
if (charge == 0.)
{
pcharge = 1.;
}
else
{
pcharge = charge;
}
dydx[ 9] = dSpin.x();
G4ThreeVector dSpin(0.,0.,0.);
if (Spin.mag2() != 0.)
{
dSpin = pcharge*omegac*(ucb*(Spin.cross(BField))-udb*(Spin.cross(u)));
}
dydx[9] = dSpin.x();
dydx[10] = dSpin.y();
dydx[11] = dSpin.z();
return ;
return;
}
@@ -23,30 +23,29 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4Mag_UsualEqRhs implementation
//
//
//
// This is the 'standard' right-hand side for the equation of motion
// of a charged particle in a magnetic field.
//
// Initial version: J. Apostolakis, January 13th, 1997
//
// Created: J.Apostolakis, CERN - 13.01.1997
// --------------------------------------------------------------------
#include "G4Mag_UsualEqRhs.hh"
#include "G4MagneticField.hh"
#include "globals.hh" // For DBL_MAX
#include "globals.hh"
G4Mag_UsualEqRhs::G4Mag_UsualEqRhs( G4MagneticField* MagField )
: G4Mag_EqRhs( MagField ) {}
: G4Mag_EqRhs( MagField )
{
}
G4Mag_UsualEqRhs::~G4Mag_UsualEqRhs() {}
G4Mag_UsualEqRhs::~G4Mag_UsualEqRhs()
{
}
void
G4Mag_UsualEqRhs::EvaluateRhsGivenB( const G4double y[],
const G4double B[3],
G4double dydx[] ) const
const G4double B[3],
G4double dydx[] ) const
{
G4double momentum_mag_square = y[3]*y[3] + y[4]*y[4] + y[5]*y[5];
G4double inv_momentum_magnitude = 1.0 / std::sqrt( momentum_mag_square );
@@ -61,14 +60,13 @@ G4Mag_UsualEqRhs::EvaluateRhsGivenB( const G4double y[],
dydx[4] = cof*(y[5]*B[0] - y[3]*B[2]) ; // Ay = a*(Vz*Bx - Vx*Bz)
dydx[5] = cof*(y[3]*B[1] - y[4]*B[0]) ; // Az = a*(Vx*By - Vy*Bx)
return ;
return;
}
void
G4Mag_UsualEqRhs::
SetChargeMomentumMass( G4ChargeState particleCharge,
G4double MomentumXc,
G4double mass)
G4Mag_UsualEqRhs::SetChargeMomentumMass( G4ChargeState particleCharge,
G4double MomentumXc,
G4double mass )
{
G4Mag_EqRhs::SetChargeMomentumMass( particleCharge, MomentumXc, mass);
@@ -23,14 +23,15 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4MagneticField implementation
//
//
// Created: J.Apostolakis, CERN - 13.01.1996
// --------------------------------------------------------------------
#include "G4MagneticField.hh"
G4MagneticField::G4MagneticField()
: G4Field( false ) // No gravitational field (default)
: G4Field( false ) // No gravitational field (default)
{
}
@@ -38,12 +39,12 @@ G4MagneticField::~G4MagneticField()
{
}
G4MagneticField::G4MagneticField(const G4MagneticField & )
: G4Field( false )
G4MagneticField::G4MagneticField(const G4MagneticField& )
: G4Field( false )
{
}
G4MagneticField& G4MagneticField::operator = (const G4MagneticField &p)
G4MagneticField& G4MagneticField::operator = (const G4MagneticField& p)
{
if (&p == this) return *this;
G4Field::operator=(p);
@@ -22,14 +22,11 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ModifiedMidpoint implementation
//
//
// G4ModifiedMidpoint implementation
// Based on modified_midpoint.hpp from boost
//
// Author: Dmitry Sorokin - GSoC 2016
//
///////////////////////////////////////////////////////////////////////////////
// Author: Dmitry Sorokin, Google Summer of Code 2016
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4ModifiedMidpoint.hh"
#include "G4FieldUtils.hh"
@@ -62,6 +59,7 @@ void G4ModifiedMidpoint::DoStep( const G4double yIn[], const G4double dydyIn[],
const G4double h2 = 2 * h;
// y1 = yIn + h * dydx
//
for (G4int i = 0; i < fnvar; ++i)
{
y1[i] = yIn[i] + h * dydyIn[i];
@@ -73,6 +71,7 @@ void G4ModifiedMidpoint::DoStep( const G4double yIn[], const G4double dydyIn[],
// general step
// yTemp = y1; y1 = y0 + h2 * dydx; y0 = yTemp
//
for (G4int i = 1; i < fsteps; ++i)
{
copy(yTemp, y1);
@@ -87,6 +86,7 @@ void G4ModifiedMidpoint::DoStep( const G4double yIn[], const G4double dydyIn[],
// last step
// yOut = 0.5 * (y0 + y1 + h * dydx)
//
for (G4int i = 0; i < fnvar; ++i)
{
yOut[i] = 0.5 * (y0[i] + y1[i] + h * dydx[i]);
@@ -116,6 +116,7 @@ void G4ModifiedMidpoint::DoStep( const G4double yIn[], const G4double dydxIn[],
// result of first step already gives approximation
// at the center of the interval
//
if(fsteps == 2)
{
copy(yMid, y1);
@@ -125,6 +126,7 @@ void G4ModifiedMidpoint::DoStep( const G4double yIn[], const G4double dydxIn[],
// general step
// yTemp = y1; y1 = y0 + h2 * dydx; y0 = yTemp
//
for (G4int i = 1; i < fsteps; ++i)
{
copy(yTemp, y1);
@@ -145,6 +147,7 @@ void G4ModifiedMidpoint::DoStep( const G4double yIn[], const G4double dydxIn[],
// last step
// yOut = 0.5 * (y0 + y1 + h * dydx)
//
for (G4int i = 0; i < fnvar; ++i)
{
yOut[i] = 0.5 * (y0[i] + y1[i] + h * derivs[fsteps-1][i]);
@@ -23,16 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4MonopoleEq implementation
//
//
//
// This is the right-hand side for equation of motion for a
// magnetic charge in a combined Electro-Magnetic field
//
// d(p_c)/ds=g{c-energyB_ - p_c x E}/pc
//
// 17.11.09 V.Grichine
//
// Created: V.Grichine, 17.11.2009
// -------------------------------------------------------------------
#include "G4MonopoleEq.hh"
@@ -40,9 +33,18 @@
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
G4MonopoleEq::G4MonopoleEq(G4ElectroMagneticField* emField )
: G4EquationOfMotion( emField )
{
}
G4MonopoleEq::~G4MonopoleEq()
{
}
void
G4MonopoleEq::SetChargeMomentumMass(G4ChargeState particleCharge, // e+ units
G4double,
G4double,
G4double particleMass)
{
G4double pcharge = particleCharge.GetCharge();
@@ -52,12 +54,10 @@ G4MonopoleEq::SetChargeMomentumMass(G4ChargeState particleCharge, // e+ units
fMassCof = particleMass*particleMass ;
}
void
G4MonopoleEq::EvaluateRhsGivenB(const G4double y[],
const G4double Field[],
G4double dydx[] ) const
const G4double Field[],
G4double dydx[] ) const
{
// Components of y:
@@ -71,13 +71,10 @@ G4MonopoleEq::EvaluateRhsGivenB(const G4double y[],
G4double pModuleInverse = 1.0/std::sqrt(pSquared) ;
// G4double inverse_velocity = Energy * c_light * pModuleInverse;
G4double inverse_velocity = Energy * pModuleInverse / c_light;
G4double cof1 = fElectroMagCof*pModuleInverse ;
// G4double vDotE = y[3]*Field[3] + y[4]*Field[4] + y[5]*Field[5] ;
dydx[0] = y[3]*pModuleInverse ;
dydx[1] = y[4]*pModuleInverse ;
dydx[2] = y[5]*pModuleInverse ;
@@ -88,9 +85,11 @@ G4MonopoleEq::EvaluateRhsGivenB(const G4double y[],
dydx[5] = cof1*(cof2*Field[2] - (y[3]*Field[4] - y[4]*Field[3])) ;
dydx[6] = 0.;//not used
dydx[6] = 0.; //not used
// Lab Time of flight
//
dydx[7] = inverse_velocity;
return ;
return;
}
@@ -23,11 +23,10 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4NystromRK4 implmentation
//
//
// History:
// - Created: I.Gavrilenko 15.05.2009 (as G4AtlasRK4)
// - Adaptations: J.Apostolakis May-Nov 2009
// Created: I.Gavrilenko, 15.05.2009 (as G4AtlasRK4)
// Adaptations: J.Apostolakis, November 2009
// -------------------------------------------------------------------
#include "G4NystromRK4.hh"
@@ -39,22 +38,18 @@
using namespace field_utils;
namespace {
G4bool notEquals(G4double p1, G4double p2)
namespace
{
return std::fabs(p1 - p2) > perMillion * p2;
}
constexpr G4int INTEGRATED_COMPONENTS = 6;
G4bool notEquals(G4double p1, G4double p2)
{
return std::fabs(p1 - p2) > perMillion * p2;
}
constexpr G4int INTEGRATED_COMPONENTS = 6;
} // namespace
G4NystromRK4::G4NystromRK4(G4Mag_EqRhs* equation, G4double distanceConstField)
: G4MagIntegratorStepper(equation, INTEGRATED_COMPONENTS),
fMomentum(0),
fMomentum2(0),
fInverseMomentum(0),
fCoefficient(0)
: G4MagIntegratorStepper(equation, INTEGRATED_COMPONENTS)
{
if (distanceConstField > 0)
{
@@ -192,38 +187,37 @@ G4double G4NystromRK4::DistChord() const
void G4NystromRK4::SetDistanceForConstantField(G4double length)
{
if (!GetField())
{
G4Exception("G4NystromRK4::SetDistanceForConstantField","Nystrom 001",
JustWarning, "Provided field is not G4CachedMagneticField. Changing field type.");
if (GetField() == nullptr)
{
G4Exception("G4NystromRK4::SetDistanceForConstantField",
"Nystrom 001", JustWarning,
"Provided field is not G4CachedMagneticField. Changing field type.");
fCachedField = std::unique_ptr<G4CachedMagneticField>(
new G4CachedMagneticField(
dynamic_cast<G4MagneticField*>(GetEquationOfMotion()->GetFieldObj()),
length));
fCachedField = std::unique_ptr<G4CachedMagneticField>(
new G4CachedMagneticField(
dynamic_cast<G4MagneticField*>(GetEquationOfMotion()->GetFieldObj()),
length));
GetEquationOfMotion()->SetFieldObj(fCachedField.get());
}
GetField()->SetConstDistance(length);
GetEquationOfMotion()->SetFieldObj(fCachedField.get());
}
GetField()->SetConstDistance(length);
}
G4double G4NystromRK4::GetDistanceForConstantField() const
{
if (!GetField())
{
return 0;
}
return GetField()->GetConstDistance();
if (GetField() == nullptr)
{
return 0.0;
}
return GetField()->GetConstDistance();
}
G4CachedMagneticField* G4NystromRK4::GetField()
{
return dynamic_cast<G4CachedMagneticField*>(GetEquationOfMotion()->GetFieldObj());
return dynamic_cast<G4CachedMagneticField*>(GetEquationOfMotion()->GetFieldObj());
}
const G4CachedMagneticField* G4NystromRK4::GetField() const
{
return const_cast<G4NystromRK4*>(this)->GetField();
return const_cast<G4NystromRK4*>(this)->GetField();
}
@@ -23,59 +23,67 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4QuadrupoleMagField implementation
//
//
// 03.02.1997, V.Grichine - Created
// 11.05.2012, B.Riese - Allow displaced origin and rotation
// -------------------------------------------------------------------
#include "G4QuadrupoleMagField.hh"
#include "G4RotationMatrix.hh"
static G4RotationMatrix IdentityMatrix;
namespace
{
G4RotationMatrix IdentityMatrix;
}
G4QuadrupoleMagField::G4QuadrupoleMagField(G4double pGradient)
{
fGradient = pGradient ;
fOrigin = G4ThreeVector( 0.0, 0.0, 0.0) ;
fGradient = pGradient;
fpMatrix = &IdentityMatrix;
}
/////////////////////////////////////////////////////////////////////////
// -------------------------------------------------------------------
G4QuadrupoleMagField::G4QuadrupoleMagField(G4double pGradient,
G4ThreeVector pOrigin,
G4RotationMatrix* pMatrix)
{
fGradient = pGradient ;
fOrigin = pOrigin ;
fpMatrix = pMatrix ;
fGradient = pGradient ;
fOrigin = pOrigin ;
fpMatrix = pMatrix ;
}
// -------------------------------------------------------------------
G4Field* G4QuadrupoleMagField::Clone() const
{
return new G4QuadrupoleMagField(fGradient, fOrigin, fpMatrix);
return new G4QuadrupoleMagField(fGradient, fOrigin, fpMatrix);
}
/////////////////////////////////////////////////////////////////////////
// -------------------------------------------------------------------
G4QuadrupoleMagField::~G4QuadrupoleMagField()
{
}
// -------------------------------------------------------------------
void G4QuadrupoleMagField::GetFieldValue( const G4double y[7],
G4double B[3] ) const
// with displaced origin and rotation
{
G4ThreeVector r_global = G4ThreeVector(
y[0] - fOrigin.x(),
y[1] - fOrigin.y(),
y[2] - fOrigin.z());
// with displaced origin and rotation
G4ThreeVector r_global = G4ThreeVector(y[0] - fOrigin.x(),
y[1] - fOrigin.y(),
y[2] - fOrigin.z());
const G4ThreeVector r_local = (*fpMatrix) * r_global;
const G4ThreeVector B_local( fGradient * r_local.y(),fGradient * r_local.x(),0);
const G4ThreeVector B_local( fGradient * r_local.y(),
fGradient * r_local.x(), 0);
const G4ThreeVector B_global = fpMatrix->inverse() * B_local;
B[0] = B_global.x() ;
B[1] = B_global.y() ;
B[2] = B_global.z() ;
B[0] = B_global.x();
B[1] = B_global.y();
B[2] = B_global.z();
}
@@ -23,11 +23,13 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4RK547FEq1 implementation
//
// The Butcher table of the Higham & Hall 5(4)7 method is:
//
// 0 |
// 2/9 | 2/9
// 1/3 | 1/12 1/4
// 1/3 | 1/12 1/4
// 1/2 | 1/8 0 3/8
// 3/5 | 91/500 -27/100 78/125 8/125
// 1 | -11/20 27/20 12/5 -36/5 5
@@ -35,6 +37,10 @@
//----------------------------------------------------------------------------
// 1/12 0 27/32 -4/3 125/96 5/48 0
// 2/15 0 27/80 -2/15 25/48 1/24 1/10
//
// Author: Dmitry Sorokin, Google Summer of Code 2017
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4RK547FEq1.hh"
#include "G4LineSection.hh"
@@ -42,22 +48,21 @@
using namespace field_utils;
G4RK547FEq1::G4RK547FEq1(G4EquationOfMotion* EqRhs, G4int integrationVariables)
: G4MagIntegratorStepper(EqRhs, integrationVariables)
: G4MagIntegratorStepper(EqRhs, integrationVariables)
{
}
void G4RK547FEq1::makeStep(
const G4double yInput[],
const G4double dydx[],
const G4double hstep,
G4double yOutput[],
G4double* dydxOutput,
G4double* yError) const
void G4RK547FEq1::makeStep( const G4double yInput[],
const G4double dydx[],
const G4double hstep,
G4double yOutput[],
G4double* dydxOutput,
G4double* yError ) const
{
G4double yTemp[G4FieldTrack::ncompSVEC];
for (int i = GetNumberOfVariables(); i < GetNumberOfStateVariables(); ++i){
for (G4int i=GetNumberOfVariables(); i<GetNumberOfStateVariables(); ++i)
{
yOutput[i] = yTemp[i] = yInput[i];
}
@@ -67,70 +72,68 @@ void G4RK547FEq1::makeStep(
ak5[G4FieldTrack::ncompSVEC],
ak6[G4FieldTrack::ncompSVEC];
const G4double
b21 = 2./9.,
b31 = 1./12., b32 = 1./4.,
b41 = 1./8., b42 = 0., b43 = 3./8.,
b51 = 91./500., b52 = -27./100., b53 = 78./125., b54 = 8./125.,
b61 = -11./20., b62 = 27./20., b63 = 12./5.,
b64 = -36./5., b65 = 5.,
b71 = 1./12., b72 = 0., b73 = 27./32.,
b74 = -4./3., b75 = 125./96., b76 = 5./48.;
const G4double b21 = 2./9.,
b31 = 1./12., b32 = 1./4.,
b41 = 1./8., b42 = 0., b43 = 3./8.,
b51 = 91./500., b52 = -27./100.,
b53 = 78./125., b54 = 8./125.,
b61 = -11./20., b62 = 27./20., b63 = 12./5.,
b64 = -36./5., b65 = 5.,
b71 = 1./12., b72 = 0., b73 = 27./32.,
b74 = -4./3., b75 = 125./96., b76 = 5./48.;
const G4double
dc1 = b71 - 2./15.,
dc2 = b72 - 0.,
dc3 = b73 - 27./80.,
dc4 = b74 + 2./15.,
dc5 = b75 - 25./48.,
dc6 = b76 - 1./24.,
dc7 = 0. - 1./10.;
const G4double dc1 = b71 - 2./15.,
dc2 = b72 - 0.,
dc3 = b73 - 27./80.,
dc4 = b74 + 2./15.,
dc5 = b75 - 25./48.,
dc6 = b76 - 1./24.,
dc7 = 0. - 1./10.;
//RightHandSide(yInput, dydx);
for(int i = 0; i < GetNumberOfVariables(); ++i)
// RightHandSide(yInput, dydx);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * b21 * dydx[i];
RightHandSide(yTemp, ak2);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b31 * dydx[i] + b32 * ak2[i]);
RightHandSide(yTemp, ak3);
for(int i = 0;i < GetNumberOfVariables(); ++i)
for(G4int i = 0;i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b41 * dydx[i] + b42 * ak2[i] +
b43 * ak3[i]);
RightHandSide(yTemp, ak4);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b51 * dydx[i] + b52 * ak2[i] +
b53 * ak3[i] + b54 * ak4[i]);
RightHandSide(yTemp, ak5);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b61 * dydx[i] + b62 * ak2[i] +
b63 * ak3[i] + b64 * ak4[i] +
b65 * ak5[i]);
RightHandSide(yTemp, ak6);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yOutput[i] = yInput[i] + hstep * (b71 * dydx[i] + b72 * ak2[i] +
b73 * ak3[i] + b74 * ak4[i] +
b75 * ak5[i] + b76 * ak6[i]);
if (dydxOutput && yError) {
if (dydxOutput && yError)
{
RightHandSide(yOutput, dydxOutput);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yError[i] = hstep * (dc1 * dydx[i] + dc2 * ak2[i] + dc3 * ak3[i] +
dc4 * ak4[i] + dc5 * ak5[i] + dc6 * ak6[i] +
dc7 * dydxOutput[i]);
}
}
void G4RK547FEq1::Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[])
void G4RK547FEq1::Stepper( const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[] )
{
copy(fyIn, yInput);
copy(fdydx, dydx);
@@ -141,13 +144,12 @@ void G4RK547FEq1::Stepper(
copy(yOutput, fyOut);
}
void G4RK547FEq1::Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[])
void G4RK547FEq1::Stepper( const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[] )
{
copy(fyIn, yInput);
copy(fdydx, dydx);
@@ -23,11 +23,13 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4RK547FEq2 implementation
//
// The Butcher table of the Higham & Hall 5(4)7 method is:
//
// 0 |
// 2/13 | 2/13
// 2/13 | 3/52 9/52
// 2/13 | 3/52 9/52
// 5/9 | 12955/26244 -15925/8748 12350/6561
// 3/4 | -10383/52480 13923/10496 -176553/199424 505197/997120
// 1 | 1403/7236 -429/268 733330/309339 -7884/8911 104960/113967
@@ -35,6 +37,10 @@
//----------------------------------------------------------------------------------------------------------------------
// 181/2700 0 656903/1846800 19683/106400 34112/110565 67/800 0
// 11377/154575 0 35378291/105729300 343359/1522850 535952/1947645 134/17175 1/12
//
// Author: Dmitry Sorokin, Google Summer of Code 2017
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4RK547FEq2.hh"
#include "G4LineSection.hh"
@@ -42,22 +48,21 @@
using namespace field_utils;
G4RK547FEq2::G4RK547FEq2(G4EquationOfMotion* EqRhs, G4int integrationVariables)
: G4MagIntegratorStepper(EqRhs, integrationVariables)
: G4MagIntegratorStepper(EqRhs, integrationVariables)
{
}
void G4RK547FEq2::makeStep(
const G4double yInput[],
const G4double dydx[],
const G4double hstep,
G4double yOutput[],
G4double* dydxOutput,
G4double* yError) const
void G4RK547FEq2::makeStep( const G4double yInput[],
const G4double dydx[],
const G4double hstep,
G4double yOutput[],
G4double* dydxOutput,
G4double* yError ) const
{
G4double yTemp[G4FieldTrack::ncompSVEC];
for (int i = GetNumberOfVariables(); i < GetNumberOfStateVariables(); ++i){
for (G4int i=GetNumberOfVariables(); i<GetNumberOfStateVariables(); ++i)
{
yOutput[i] = yTemp[i] = yInput[i];
}
@@ -67,71 +72,70 @@ void G4RK547FEq2::makeStep(
ak5[G4FieldTrack::ncompSVEC],
ak6[G4FieldTrack::ncompSVEC];
const G4double
b21 = 2./13.,
b31 = 3./52., b32 = 9./52.,
b41 = 12955./26244., b42 = -15925./8748., b43 = 12350./6561.,
b51 = -10383./52480., b52 = 13923./10496., b53 = -176553./199424.,
b54 = 505197./997120.,
b61 = 1403./7236., b62 = -429./268., b63 = 733330./309339.,
b64 = -7884./8911., b65 = 104960./113967.,
b71 = 181./2700., b72 = 0., b73 = 656903./1846800.,
b74 = 19683./106400., b75 = 34112./110565., b76 = 67./800.;
const G4double b21 = 2./13.,
b31 = 3./52., b32 = 9./52.,
b41 = 12955./26244., b42 = -15925./8748.,
b43 = 12350./6561.,
b51 = -10383./52480., b52 = 13923./10496.,
b53 = -176553./199424., b54 = 505197./997120.,
b61 = 1403./7236., b62 = -429./268., b63 = 733330./309339.,
b64 = -7884./8911., b65 = 104960./113967.,
b71 = 181./2700., b72 = 0., b73 = 656903./1846800.,
b74 = 19683./106400., b75 = 34112./110565.,
b76 = 67./800.;
const G4double
dc1 = b71 - 11377./154575.,
dc2 = b72 - 0.,
dc3 = b73 - 35378291./105729300.,
dc4 = b74 - 343359./1522850.,
dc5 = b75 - 535952./1947645.,
dc6 = b76 - 134./17175.,
dc7 = 0. - 1./12.;
const G4double dc1 = b71 - 11377./154575.,
dc2 = b72 - 0.,
dc3 = b73 - 35378291./105729300.,
dc4 = b74 - 343359./1522850.,
dc5 = b75 - 535952./1947645.,
dc6 = b76 - 134./17175.,
dc7 = 0. - 1./12.;
//RightHandSide(yInput, dydx);
for(int i = 0; i < GetNumberOfVariables(); ++i)
// RightHandSide(yInput, dydx);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * b21 * dydx[i];
RightHandSide(yTemp, ak2);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b31 * dydx[i] + b32 * ak2[i]);
RightHandSide(yTemp, ak3);
for(int i = 0;i < GetNumberOfVariables(); ++i)
for(G4int i = 0;i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b41 * dydx[i] + b42 * ak2[i] +
b43 * ak3[i]);
RightHandSide(yTemp, ak4);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b51 * dydx[i] + b52 * ak2[i] +
b53 * ak3[i] + b54 * ak4[i]);
RightHandSide(yTemp, ak5);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b61 * dydx[i] + b62 * ak2[i] +
b63 * ak3[i] + b64 * ak4[i] +
b65 * ak5[i]);
RightHandSide(yTemp, ak6);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yOutput[i] = yInput[i] + hstep * (b71 * dydx[i] + b72 * ak2[i] +
b73 * ak3[i] + b74 * ak4[i] +
b75 * ak5[i] + b76 * ak6[i]);
if (dydxOutput && yError) {
if (dydxOutput && yError)
{
RightHandSide(yOutput, dydxOutput);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yError[i] = hstep * (dc1 * dydx[i] + dc2 * ak2[i] + dc3 * ak3[i] +
dc4 * ak4[i] + dc5 * ak5[i] + dc6 * ak6[i] +
dc7 * dydxOutput[i]);
}
}
void G4RK547FEq2::Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[])
void G4RK547FEq2::Stepper( const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[] )
{
copy(fyIn, yInput);
copy(fdydx, dydx);
@@ -142,13 +146,12 @@ void G4RK547FEq2::Stepper(
copy(yOutput, fyOut);
}
void G4RK547FEq2::Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[])
void G4RK547FEq2::Stepper( const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[] )
{
copy(fyIn, yInput);
copy(fdydx, dydx);
@@ -23,6 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4RK547FEq3 implementation
//
// The Butcher table of the Higham & Hall 5(4)7 method is:
//
// 0 |
@@ -35,6 +37,10 @@
//---------------------------------------------------------------------------------------------------------------------
// 1247/10890 0 57375/108053 -1229312/1962015 125/207 43/114 0
// 21487/185130 0 963225/1836901 -39864832/33354255 2575/3519 4472/4845 -1/10
//
// Author: Dmitry Sorokin, Google Summer of Code 2017
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4RK547FEq3.hh"
#include "G4LineSection.hh"
@@ -42,22 +48,21 @@
using namespace field_utils;
G4RK547FEq3::G4RK547FEq3(G4EquationOfMotion* EqRhs, G4int integrationVariables)
: G4MagIntegratorStepper(EqRhs, integrationVariables)
: G4MagIntegratorStepper(EqRhs, integrationVariables)
{
}
void G4RK547FEq3::makeStep(
const G4double yInput[],
const G4double dydx[],
const G4double hstep,
G4double yOutput[],
G4double* dydxOutput,
G4double* yError) const
void G4RK547FEq3::makeStep( const G4double yInput[],
const G4double dydx[],
const G4double hstep,
G4double yOutput[],
G4double* dydxOutput,
G4double* yError ) const
{
G4double yTemp[G4FieldTrack::ncompSVEC];
for (int i = GetNumberOfVariables(); i < GetNumberOfStateVariables(); ++i){
for (G4int i=GetNumberOfVariables(); i<GetNumberOfStateVariables(); ++i)
{
yOutput[i] = yTemp[i] = yInput[i];
}
@@ -67,71 +72,71 @@ void G4RK547FEq3::makeStep(
ak5[G4FieldTrack::ncompSVEC],
ak6[G4FieldTrack::ncompSVEC];
const G4double
b21 = 11./45.,
b31 = 11./120., b32 = 11./40.,
b41 = 106865./87808., b42 = -408375./87808., b43 = 193875./43904.,
b51 = 79503./121000., b52 = -1053./440., b53 = 147753./56870.,
b54 = 27048./710875.,
b61 = 89303./78045., b62 = -2025./473., b63 = 994650./244541.,
b64 = -2547216./28122215., b65 = 475./2967.,
b71 = 1247./10890., b72 = 0., b73 = 57375./108053.,
b74 = -1229312./1962015., b75 = 125./207., b76 = 43./114.;
const G4double b21 = 11./45.,
b31 = 11./120., b32 = 11./40.,
b41 = 106865./87808., b42 = -408375./87808.,
b43 = 193875./43904.,
b51 = 79503./121000., b52 = -1053./440.,
b53 = 147753./56870., b54 = 27048./710875.,
b61 = 89303./78045., b62 = -2025./473.,
b63 = 994650./244541., b64 = -2547216./28122215.,
b65 = 475./2967.,
b71 = 1247./10890., b72 = 0., b73 = 57375./108053.,
b74 = -1229312./1962015., b75 = 125./207.,
b76 = 43./114.;
const G4double
dc1 = b71 - 21487./185130.,
dc2 = b72 - 0.,
dc3 = b73 - 963225./1836901.,
dc4 = b74 + 39864832./33354255.,
dc5 = b75 - 2575./3519.,
dc6 = b76 - 4472./4845.,
dc7 = 0. + 1./10.;
const G4double dc1 = b71 - 21487./185130.,
dc2 = b72 - 0.,
dc3 = b73 - 963225./1836901.,
dc4 = b74 + 39864832./33354255.,
dc5 = b75 - 2575./3519.,
dc6 = b76 - 4472./4845.,
dc7 = 0. + 1./10.;
//RightHandSide(yInput, dydx);
for(int i = 0; i < GetNumberOfVariables(); ++i)
// RightHandSide(yInput, dydx);
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * b21 * dydx[i];
RightHandSide(yTemp, ak2);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b31 * dydx[i] + b32 * ak2[i]);
RightHandSide(yTemp, ak3);
for(int i = 0;i < GetNumberOfVariables(); ++i)
for(G4int i = 0;i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b41 * dydx[i] + b42 * ak2[i] +
b43 * ak3[i]);
RightHandSide(yTemp, ak4);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b51 * dydx[i] + b52 * ak2[i] +
b53 * ak3[i] + b54 * ak4[i]);
RightHandSide(yTemp, ak5);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yTemp[i] = yInput[i] + hstep * (b61 * dydx[i] + b62 * ak2[i] +
b63 * ak3[i] + b64 * ak4[i] +
b65 * ak5[i]);
RightHandSide(yTemp, ak6);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yOutput[i] = yInput[i] + hstep * (b71 * dydx[i] + b72 * ak2[i] +
b73 * ak3[i] + b74 * ak4[i] +
b75 * ak5[i] + b76 * ak6[i]);
if (dydxOutput && yError) {
if (dydxOutput && yError)
{
RightHandSide(yOutput, dydxOutput);
for(int i = 0; i < GetNumberOfVariables(); ++i)
for(G4int i = 0; i < GetNumberOfVariables(); ++i)
yError[i] = hstep * (dc1 * dydx[i] + dc2 * ak2[i] + dc3 * ak3[i] +
dc4 * ak4[i] + dc5 * ak5[i] + dc6 * ak6[i] +
dc7 * dydxOutput[i]);
}
}
void G4RK547FEq3::Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[])
void G4RK547FEq3::Stepper( const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[] )
{
copy(fyIn, yInput);
copy(fdydx, dydx);
@@ -142,13 +147,12 @@ void G4RK547FEq3::Stepper(
copy(yOutput, fyOut);
}
void G4RK547FEq3::Stepper(
const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[])
void G4RK547FEq3::Stepper( const G4double yInput[],
const G4double dydx[],
G4double hstep,
G4double yOutput[],
G4double yError[],
G4double dydxOutput[] )
{
copy(fyIn, yInput);
copy(fdydx, dydx);
@@ -23,16 +23,17 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4RKG3_Stepper implementation
//
//
// Created: J.Apostolakis, V.Grichine - 30.01.1997
// -------------------------------------------------------------------
#include "G4RKG3_Stepper.hh"
#include "G4LineSection.hh"
#include "G4Mag_EqRhs.hh"
G4RKG3_Stepper::G4RKG3_Stepper(G4Mag_EqRhs *EqRhs)
: G4MagIntegratorStepper(EqRhs,6), hStep(0.)
G4RKG3_Stepper::G4RKG3_Stepper(G4Mag_EqRhs* EqRhs)
: G4MagIntegratorStepper(EqRhs,6)
{
}
@@ -40,57 +41,62 @@ G4RKG3_Stepper::~G4RKG3_Stepper()
{
}
void G4RKG3_Stepper::Stepper( const G4double yInput[8],
const G4double dydx[6],
G4double Step,
G4double yOut[8],
G4double yErr[])
void G4RKG3_Stepper::Stepper( const G4double yInput[8],
const G4double dydx[6],
G4double Step,
G4double yOut[8],
G4double yErr[] )
{
G4double B[3];
G4int nvar = 6 ;
G4int i;
G4double by15 = 1. / 15. ; // was 0.066666666 ;
G4double yTemp[8], dydxTemp[6], yIn[8] ;
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<nvar;i++) yIn[i]=yInput[i];
G4double yTemp[8], dydxTemp[6], yIn[8];
// Saving yInput because yInput and yOut can be aliases for same array
//
for(G4int i=0; i<nvar; ++i)
{
yIn[i]=yInput[i];
}
yIn[6] = yInput[6];
yIn[7] = yInput[7];
G4double h = Step * 0.5;
hStep=Step;
// Do two half steps
hStep = Step;
// Do two half steps
StepNoErr(yIn, dydx,h, yTemp,B) ;
//Store Bfld for DistChord Calculation
for(i=0;i<3;i++)BfldIn[i]=B[i];
// RightHandSide(yTemp,dydxTemp) ;
// Store Bfld for DistChord Calculation
//
for(auto i=0; i<3; ++i)
{
BfldIn[i] = B[i];
}
// RightHandSide(yTemp,dydxTemp) ;
GetEquationOfMotion()->EvaluateRhsGivenB(yTemp,B,dydxTemp) ;
StepNoErr(yTemp,dydxTemp,h,yOut,B);
// Store midpoint, chord calculation
fyMidPoint = G4ThreeVector( yTemp[0], yTemp[1], yTemp[2]);
fyMidPoint = G4ThreeVector(yTemp[0], yTemp[1], yTemp[2]);
// Do a full Step
//
h *= 2 ;
StepNoErr(yIn,dydx,h,yTemp,B);
for(i=0;i<nvar;i++)
for(G4int i=0; i<nvar; ++i)
{
yErr[i] = yOut[i] - yTemp[i] ;
yOut[i] += yErr[i]*by15 ; // Provides 5th order of accuracy
}
//Store values for DistChord method
// Store values for DistChord method
//
fyInitial = G4ThreeVector( yIn[0], yIn[1], yIn[2]);
fpInitial = G4ThreeVector( yIn[3], yIn[4], yIn[5]);
fyFinal = G4ThreeVector( yOut[0], yOut[1], yOut[2]);
// NormaliseTangentVector( yOut ); // Deleted
}
// ---------------------------------------------------------------------------
@@ -99,7 +105,7 @@ void G4RKG3_Stepper::Stepper( const G4double yInput[8],
// 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*,
const G4double*,
G4double,
@@ -116,99 +122,93 @@ void G4RKG3_Stepper::StepWithEst( const G4double*,
// -----------------------------------------------------------------
// 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[8],
const G4double dydx[6],
G4double Step,
G4double tOut[8],
G4double B[3] ) // const
G4double B[3] )
{
// Copy and edit the routine above, to delete alpha2, beta2, ...
G4double K1[7],K2[7],K3[7],K4[7] ;
G4double tTemp[8], yderiv[6] ;
// Copy and edit the routine above, to delete alpha2, beta2, ...
//
G4double K1[7], K2[7], K3[7], K4[7];
G4double tTemp[8]={0.0}, yderiv[6]={0.0};
// Need Momentum value to give correct values to the coefficients in equation
// Integration on unit velocity, but tIn[3,4,5] is momentum
G4double mom,inverse_mom;
G4int i ;
const G4double c1=0.5,c2=0.125,c3=1./6.;
// Need Momentum value to give correct values to the coefficients in
// equation. Integration on unit velocity, but tIn[3,4,5] is momentum
G4double mom, inverse_mom;
const G4double c1=0.5, c2=0.125, c3=1./6.;
// GetEquationOfMotion()->EvaluateRhsReturnB(tIn,dydx,B1) ;
// Correction for momentum not a velocity
// Need the protection !!! must be not zero
mom=std::sqrt(tIn[3]*tIn[3]+tIn[4]*tIn[4]+tIn[5]*tIn[5]);
inverse_mom=1./mom;
for(i=0;i<3;i++)
// Need the protection !!! must be not zero
//
mom = std::sqrt(tIn[3]*tIn[3]+tIn[4]*tIn[4]+tIn[5]*tIn[5]);
inverse_mom = 1./mom;
for(auto i=0; i<3; ++i)
{
K1[i] = Step * dydx[i+3]*inverse_mom;
tTemp[i] = tIn[i] + Step*(c1*tIn[i+3]*inverse_mom + c2*K1[i]) ;
tTemp[i+3] = tIn[i+3] + c1*K1[i]*mom ;
}
GetEquationOfMotion()->EvaluateRhsReturnB(tTemp,yderiv,B) ;
for(i=0;i<3;i++)
for(auto i=0; i<3; ++i)
{
K2[i] = Step * yderiv[i+3]*inverse_mom;
tTemp[i+3] = tIn[i+3] + c1*K2[i]*mom ;
}
// Given B, calculate yderiv !
// Given B, calculate yderiv !
//
GetEquationOfMotion()->EvaluateRhsGivenB(tTemp,B,yderiv) ;
for(i=0;i<3;i++)
for(auto i=0; i<3; ++i)
{
K3[i] = Step * yderiv[i+3]*inverse_mom;
tTemp[i] = tIn[i] + Step*(tIn[i+3]*inverse_mom + c1*K3[i]) ;
tTemp[i+3] = tIn[i+3] + K3[i]*mom ;
}
// Calculates y-deriv(atives) & returns B too!
// Calculates y-deriv(atives) & returns B too!
//
GetEquationOfMotion()->EvaluateRhsReturnB(tTemp,yderiv,B) ;
for(i=0;i<3;i++) // Output trajectory vector
for(auto i=0; i<3; ++i) // Output trajectory vector
{
K4[i] = Step * yderiv[i+3]*inverse_mom;
tOut[i] = tIn[i] + Step*(tIn[i+3]*inverse_mom+ (K1[i] + K2[i] + K3[i])*c3) ;
tOut[i] = tIn[i] + Step*(tIn[i+3]*inverse_mom+ (K1[i]+K2[i]+K3[i])*c3) ;
tOut[i+3] = tIn[i+3] + mom*(K1[i] + 2*K2[i] + 2*K3[i] +K4[i])*c3 ;
}
tOut[6] = tIn[6];
tOut[7] = tIn[7];
// NormaliseTangentVector( tOut );
}
// ---------------------------------------------------------------------------
G4double G4RKG3_Stepper::DistChord() const
{
G4double G4RKG3_Stepper::DistChord() const
{
// Soon: must check whether h/R > 2 pi !!
// Method below is good only for < 2 pi
// Method below is good only for < 2 pi
G4double distChord,distLine;
if (fyInitial != fyFinal) {
distLine= G4LineSection::Distline(fyMidPoint,fyInitial,fyFinal );
distChord = distLine;
}else{
if (fyInitial != fyFinal)
{
distLine = G4LineSection::Distline(fyMidPoint,fyInitial,fyFinal);
distChord = distLine;
}
else
{
distChord = (fyMidPoint-fyInitial).mag();
}
return distChord;
}
return distChord;
}
@@ -23,13 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4RepleteEofM implementation
//
//
//
// This is the standard right-hand side for equation of motion.
//
// 08.04.2013 Peter Gumplinger
//
// Created: P.Gumplinger, 08.04.2013
// -------------------------------------------------------------------
#include "G4RepleteEofM.hh"
@@ -42,12 +38,7 @@
G4RepleteEofM::G4RepleteEofM( G4Field* field, G4int nvar )
: G4EquationOfMotion( field ), fNvar(nvar),
fBfield(false), fEfield(false), fGfield(false),
fgradB(false), fSpin(false),
charge(0.), mass(0.), magMoment(0.), spin(0.),
ElectroMagCof(0.), omegac(0.), anomaly(0.),
beta(0.), gamma(0.)
: G4EquationOfMotion( field ), fNvar(nvar)
{
fGfield = field->IsGravityActive();
}
@@ -83,9 +74,9 @@ G4RepleteEofM::SetChargeMomentumMass(G4ChargeState particleCharge, // e+ units
}
void
G4RepleteEofM::EvaluateRhsGivenB(const G4double y[],
const G4double Field[],
G4double dydx[] ) const
G4RepleteEofM::EvaluateRhsGivenB( const G4double y[],
const G4double Field[],
G4double dydx[] ) const
{
// Components of y:
@@ -139,8 +130,10 @@ G4RepleteEofM::EvaluateRhsGivenB(const G4double y[],
// Force due to B field - Field[0,1,2]
if (fBfield) {
if (charge != 0.) {
if (fBfield)
{
if (charge != 0.)
{
dydx[3] += cof1*(y[4]*field[2] - y[5]*field[1]);
dydx[4] += cof1*(y[5]*field[0] - y[3]*field[2]);
dydx[5] += cof1*(y[3]*field[1] - y[4]*field[0]);
@@ -149,18 +142,23 @@ G4RepleteEofM::EvaluateRhsGivenB(const G4double y[],
// add force due to E field - Field[3,4,5]
if (!fBfield) {
if (!fBfield)
{
field[3] = Field[0];
field[4] = Field[1];
field[5] = Field[2];
} else {
}
else
{
field[3] = Field[3];
field[4] = Field[4];
field[5] = Field[5];
}
if (fEfield) {
if (charge != 0.) {
if (fEfield)
{
if (charge != 0.)
{
dydx[3] += cof1*cof2*field[3];
dydx[4] += cof1*cof2*field[4];
dydx[5] += cof1*cof2*field[5];
@@ -169,27 +167,33 @@ G4RepleteEofM::EvaluateRhsGivenB(const G4double y[],
// add force due to gravity field - Field[6,7,8]
if (!fBfield && !fEfield) {
if (!fBfield && !fEfield)
{
field[6] = Field[0];
field[7] = Field[1];
field[8] = Field[2];
} else {
}
else
{
field[6] = Field[6];
field[7] = Field[7];
field[8] = Field[8];
}
if (fGfield) {
if (mass > 0.) {
if (fGfield)
{
if (mass > 0.)
{
dydx[3] += field[6]*cof2*cof3/c_light;
dydx[4] += field[7]*cof2*cof3/c_light;
dydx[5] += field[8]*cof2*cof3/c_light;
}
}
// add force due to ∇(µ⋅B) == (µ⋅∇)B when (∇xB) = 0
// add force
if (!fBfield && !fEfield && !fGfield) {
if (!fBfield && !fEfield && !fGfield)
{
field[9] = Field[0];
field[10] = Field[1];
field[11] = Field[2];
@@ -199,7 +203,9 @@ G4RepleteEofM::EvaluateRhsGivenB(const G4double y[],
field[15] = Field[6];
field[16] = Field[7];
field[17] = Field[8];
} else {
}
else
{
field[9] = Field[9];
field[10] = Field[10];
field[11] = Field[11];
@@ -211,36 +217,27 @@ G4RepleteEofM::EvaluateRhsGivenB(const G4double y[],
field[17] = Field[17];
}
if (fgradB) {
if (magMoment != 0.) {
// field[ 9] == dB_x/dx; field[10] == dB_y/dx; field[11] == dB_z/dx
// field[12] == dB_x/dy; field[13] == dB_y/dy; field[14] == dB_z/dy
// field[15] == dB_x/dz; field[16] == dB_y/dz; field[17] == dB_z/dz
// G4cout << "y[9]: " << y[9] << " y[10]: " << y[10] << " y[11]: " << y[11] << G4endl;
// G4cout << "field[9]: " << field[9] << " field[10]: " << field[10] << " field[11]: " << field[11] << G4endl;
// G4cout << "field[12]: " << field[12] << " field[13]: " << field[13] << " field[14]: " << field[14] << G4endl;
// G4cout << "field[15]: " << field[15] << " field[16]: " << field[16] << " field[17]: " << field[17] << G4endl;
// G4cout << "inv_momentum_magnitdue: " << inv_momentum_magnitude << " Energy: " << Energy << G4endl;
if (fgradB)
{
if (magMoment != 0.)
{
dydx[3] += magMoment*(y[9]*field[ 9]+y[10]*field[10]+y[11]*field[11])
*inv_momentum_magnitude*Energy;
dydx[4] += magMoment*(y[9]*field[12]+y[10]*field[13]+y[11]*field[14])
*inv_momentum_magnitude*Energy;
dydx[5] += magMoment*(y[9]*field[15]+y[10]*field[16]+y[11]*field[17])
*inv_momentum_magnitude*Energy;
// G4cout << "dydx[3,4,5] " << dydx[3] << " " << dydx[4] << " " << dydx[5] << G4endl;
}
}
dydx[6] = 0.; //not used
dydx[6] = 0.; // not used
// Lab Time of flight
//
dydx[7] = inverse_velocity;
if (fNvar == 12) {
if (fNvar == 12)
{
dydx[ 8] = 0.; //not used
dydx[ 9] = 0.;
@@ -248,16 +245,18 @@ G4RepleteEofM::EvaluateRhsGivenB(const G4double y[],
dydx[11] = 0.;
}
if (fSpin) {
// G4cout << "y[9,10,11] " << y[9] << " " << y[10] << " " << y[11] << G4endl;
if (fSpin)
{
G4ThreeVector BField(0.,0.,0.);
if (fBfield) {
if (fBfield)
{
G4ThreeVector F(field[0],field[1],field[2]);
BField = F;
}
G4ThreeVector EField(0.,0.,0.);
if (fEfield) {
if (fEfield)
{
G4ThreeVector F(field[3],field[4],field[5]);
EField = F;
}
@@ -278,26 +277,26 @@ G4RepleteEofM::EvaluateRhsGivenB(const G4double y[],
else pcharge = charge;
G4ThreeVector dSpin(0.,0.,0);
if (Spin.mag2() != 0.) {
if (fBfield) {
if (Spin.mag2() != 0.)
{
if (fBfield)
{
dSpin =
pcharge*omegac*( ucb*(Spin.cross(BField))-udb*(Spin.cross(u)) );
}
if (fEfield) {
dSpin -=
// from Jackson
// -uce*Spin.cross(u.cross(EField)) );
// but this form has one less operation
pcharge*omegac*( uce*(u*(Spin*EField) - EField*(Spin*u)) );
if (fEfield)
{
dSpin -= pcharge*omegac*( uce*(u*(Spin*EField) - EField*(Spin*u)) );
// from Jackson
// -uce*Spin.cross(u.cross(EField)) );
// but this form has one less operation
}
}
dydx[ 9] = dSpin.x();
dydx[10] = dSpin.y();
dydx[11] = dSpin.z();
// G4cout << "dydx[9,10,11] " << dydx[9] << " " << dydx[10] << " " << dydx[11] << G4endl;
}
return ;
return;
}
@@ -0,0 +1,82 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4SextupoleMagField implementation
// by H. Burkhardt 23/10/2019
// -------------------------------------------------------------------
#include "G4SextupoleMagField.hh"
#include "G4RotationMatrix.hh"
// -------------------------------------------------------------------
namespace
{
G4RotationMatrix IdentityMatrix;
}
G4SextupoleMagField::G4SextupoleMagField(G4double pGradient)
{
fGradient = pGradient;
fpMatrix = &IdentityMatrix;
}
G4SextupoleMagField::G4SextupoleMagField(G4double pGradient,
G4ThreeVector pOrigin,
G4RotationMatrix* pMatrix)
{
fGradient = pGradient ;
fOrigin = pOrigin ;
fpMatrix = pMatrix ;
}
G4Field* G4SextupoleMagField::Clone() const
{
return new G4SextupoleMagField(fGradient, fOrigin, fpMatrix);
}
// -------------------------------------------------------------------
G4SextupoleMagField::~G4SextupoleMagField()
{
}
void G4SextupoleMagField::GetFieldValue( const G4double y[4],
G4double B[3] ) const
// with displaced origin and rotation
{
G4ThreeVector r_global = G4ThreeVector(
y[0] - fOrigin.x(),
y[1] - fOrigin.y(),
y[2] - fOrigin.z());
const G4ThreeVector r_local = (*fpMatrix) * r_global;
const G4ThreeVector B_local( fGradient * r_local.x() * r_local.y(),fGradient * ( std::pow(r_local.x(),2) - std::pow(r_local.y(),2) )/2 ,0);
const G4ThreeVector B_global = fpMatrix->inverse() * B_local;
B[0] = B_global.x() ;
B[1] = B_global.y() ;
B[2] = B_global.z() ;
}
@@ -23,16 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4SimpleHeum implementation
//
//
// 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
// Created: W.Wander <wwc@mit.edu>, 12/09/1997
// -------------------------------------------------------------------
#include "G4SimpleHeum.hh"
@@ -41,10 +34,10 @@
///////////////////////////////////////////////////////////////////////////
//
// Constructor
G4SimpleHeum::G4SimpleHeum(G4EquationOfMotion *EqRhs, G4int num_variables):
G4MagErrorStepper(EqRhs, num_variables),
fNumberOfVariables(num_variables)
//
G4SimpleHeum::G4SimpleHeum(G4EquationOfMotion* EqRhs, G4int num_variables)
: G4MagErrorStepper(EqRhs, num_variables),
fNumberOfVariables(num_variables)
{
dydxTemp = new G4double[fNumberOfVariables] ;
dydxTemp2 = new G4double[fNumberOfVariables] ;
@@ -52,46 +45,43 @@ G4SimpleHeum::G4SimpleHeum(G4EquationOfMotion *EqRhs, G4int num_variables):
yTemp2 = new G4double[fNumberOfVariables] ;
}
//////////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4SimpleHeum::~G4SimpleHeum()
{
delete[] dydxTemp;
delete[] dydxTemp2;
delete[] yTemp;
delete[] yTemp2;
delete [] dydxTemp;
delete [] dydxTemp2;
delete [] yTemp;
delete [] yTemp2;
}
//////////////////////////////////////////////////////////////////////
//
// DumbStepper
//
void
G4SimpleHeum::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[])
G4SimpleHeum::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[] )
{
G4int i;
for( i = 0; i < fNumberOfVariables; i++ )
for( G4int 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++ )
for( G4int 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++ )
for( G4int i = 0; i < fNumberOfVariables; ++i )
{
yOut[i] = yIn[i] + h * (0.25 * dydx[i] + 0.75 * dydxTemp2[i]);
}
@@ -23,18 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4SimpleRunge implementation
//
//
// Simple Runge:
//
// x_1 = x_0 + h * ( dx( t_0+h/2, x_0 + h/2 * dx( t_0, x_0) ) )
//
// Second order solver.
// Takes the derivative at a position to be assumed at the middle of the
// Step and adds it to the current position.
//
//
// W.Wander <wwc@mit.edu> 12/09/97
// Created: W.Wander <wwc@mit.edu>, 12/09/1997
// -------------------------------------------------------------------
#include "G4SimpleRunge.hh"
@@ -43,53 +34,51 @@
////////////////////////////////////////////////////////////////
//
// Constructor
//
G4SimpleRunge::G4SimpleRunge(G4EquationOfMotion* EqRhs, G4int numberOfVariables)
: G4MagErrorStepper(EqRhs, numberOfVariables),
fNumberOfVariables(numberOfVariables)
{
unsigned int noVariables= std::max(numberOfVariables,
GetNumberOfStateVariables());
GetNumberOfStateVariables());
// To deal with Time >= 7+1
dydxTemp = new G4double[noVariables] ;
yTemp = new G4double[noVariables] ;
}
/////////////////////////////////////////////////////////////////
//
// Destructor
//
G4SimpleRunge::~G4SimpleRunge()
{
delete[] dydxTemp;
delete[] yTemp;
delete [] dydxTemp;
delete [] yTemp;
}
//////////////////////////////////////////////////////////////////
//
// DumbStepper
//
void
G4SimpleRunge::DumbStepper( const G4double yIn[],
const G4double dydx[],
G4double h,
G4double yOut[])
const G4double dydx[],
G4double h,
G4double yOut[] )
{
// Initialise time to t0, needed when it is not updated by the integration.
yTemp[7] = yOut[7] = yIn[7]; // Better to set it to NaN; // TODO
//
yTemp[7] = yOut[7] = yIn[7];
G4int i;
for( i = 0; i < fNumberOfVariables; i++ )
for( G4int i = 0; i < fNumberOfVariables; ++i )
{
yTemp[i] = yIn[i] + 0.5 * h*dydx[i] ;
}
RightHandSide(yTemp,dydxTemp);
for( i = 0; i < fNumberOfVariables; i++ )
for( G4int i = 0; i < fNumberOfVariables; ++i )
{
yOut[i] = yIn[i] + h * ( dydxTemp[i] );
}
@@ -23,12 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4TrialsCounter implementation
//
// class G4TrialsCounter
//
// Class inline implementation
//
// Author: Dec 8, 2006 John Apostolakis
// Author: John Apostolakis, CERN - 08.12.2006
// -------------------------------------------------------------------
#include "G4TrialsCounter.hh"
@@ -37,8 +34,7 @@
G4TrialsCounter::G4TrialsCounter( const G4String& nameStats,
const G4String& description,
G4bool printOnExit )
: fName(nameStats), fDescription(description),
fStatsVerbose(printOnExit), fPrinted(false)
: fName(nameStats), fDescription(description), fStatsVerbose(printOnExit)
{
ClearCounts();
}
@@ -52,6 +48,7 @@ void
G4TrialsCounter::PrintStatistics()
{
// Print Statistics
//
G4cout << "G4TrialsCounter::PrintStatistics()" << G4endl
<< "Report of counts for " << fDescription << " : " << G4endl;
G4cout << "Stats for '" << fName << "' > "
@@ -60,23 +57,23 @@ G4TrialsCounter::PrintStatistics()
<< " Max-trial= " << fmaxTrials
<< " no-max= " << fNoTimesMaxTrials
<< G4endl;
fPrinted= true;
fPrinted = true;
}
void G4TrialsCounter::ClearCounts()
{
fTotalNoTrials= 0;
fNumberCalls = 0;
fmaxTrials = 0; // Maximum --> so only unsigned ints expected
fNoTimesMaxTrials=0;
fTotalNoTrials = 0;
fNumberCalls = 0;
fmaxTrials = 0; // Maximum --> so only unsigned ints expected
fNoTimesMaxTrials = 0;
}
G4int
G4TrialsCounter::ReturnTotals( G4int& calls, G4int& maxTrials, G4int& numMaxT )
{
calls = fNumberCalls;
maxTrials= fmaxTrials;
numMaxT = fNoTimesMaxTrials;
calls = fNumberCalls;
maxTrials = fmaxTrials;
numMaxT = fNoTimesMaxTrials;
return fTotalNoTrials;
}
@@ -23,22 +23,10 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4TsitourasRK45 implementation
//
// Tsitouras - 5(4) RK steppers ( non-FSAL version )
//
// Implements RK tableau from 'Table 1' of
// C. Tsitouras, “RungeKutta pairs of order 5(4) satisfying only
// the first column simplifying assumption,”
// Computers & Mathematics with Applications,
// vol. 62, no. 2, pp. 770775, 2011.
//
// Adaptation / Geant4 implementation by Somnath Banerjee
// Supervision / code review: John Apostolakis
//
// Sponsored by Google in Google Summer of Code 2015.
//
// First version: 12 June 2015
//
// Author: Somnath Banerjee, Google Summer of Code 2015, 11.06.2015
// Supervision: John Apostolakis, CERN
// -------------------------------------------------------------------
#include "G4TsitourasRK45.hh"
@@ -47,15 +35,13 @@
/////////////////////////////////////////////////////////////////////
//
// Constructor
//
G4TsitourasRK45::G4TsitourasRK45(G4EquationOfMotion *EqRhs,
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables),
fLastStepLength(0.), fAuxStepper(0)
G4int noIntegrationVariables,
G4bool primary)
: G4MagIntegratorStepper(EqRhs, noIntegrationVariables)
{
const G4int numberOfVariables = noIntegrationVariables;
// G4cout << "G4TsitourasRK45 constructor called." << G4endl;
ak2 = new G4double[numberOfVariables] ;
ak3 = new G4double[numberOfVariables] ;
@@ -65,12 +51,11 @@ G4TsitourasRK45::G4TsitourasRK45(G4EquationOfMotion *EqRhs,
ak7 = new G4double[numberOfVariables] ;
ak8 = new G4double[numberOfVariables] ;
// Must ensure space extra 'state' variables exists - i.e. yIn[7]
//
const G4int numStateMax = std::max(GetNumberOfStateVariables(), 8);
const G4int numStateVars = std::max(noIntegrationVariables,
numStateMax );
// GetNumberOfStateVariables() );
yTemp = new G4double[numStateVars] ;
yIn = new G4double[numStateVars] ;
@@ -82,6 +67,7 @@ G4TsitourasRK45::G4TsitourasRK45(G4EquationOfMotion *EqRhs,
fMidVector = new G4double[numberOfVariables];
fMidError = new G4double[numberOfVariables];
if( primary )
{
fAuxStepper = new G4TsitourasRK45(EqRhs, numberOfVariables, !primary);
@@ -91,162 +77,159 @@ G4TsitourasRK45::G4TsitourasRK45(G4EquationOfMotion *EqRhs,
/////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4TsitourasRK45::~G4TsitourasRK45()
{
delete[] ak2;
delete[] ak3;
delete[] ak4;
delete[] ak5;
delete[] ak6;
delete[] ak7;
delete[] ak8;
delete [] ak2;
delete [] ak3;
delete [] ak4;
delete [] ak5;
delete [] ak6;
delete [] ak7;
delete [] ak8;
delete[] yTemp;
delete[] yIn;
delete [] yTemp;
delete [] yIn;
delete[] fLastInitialVector;
delete[] fLastFinalVector;
delete[] fLastDyDx;
delete[] fMidVector;
delete[] fMidError;
delete [] fLastInitialVector;
delete [] fLastFinalVector;
delete [] fLastDyDx;
delete [] fMidVector;
delete [] fMidError;
delete fAuxStepper;
}
//The following coefficients have been obtained from
// The following coefficients have been obtained from
// Table 1: The Coefficients of the new pair
//---Ref---
// C. Tsitouras, RungeKutta pairs of order 5(4) satisfying only
// the first column simplifying assumption,”
// Computers & Mathematics with Applications,
// vol. 62, no. 2, pp. 770775, 2011.
//-----------------------------------
// A corresponding matlab code was also found @ http://users.ntua.gr/tsitoura/new54.m
//
// C. Tsitouras, "RungeKutta pairs of order 5(4) satisfying only
// the first column simplifying assumption"
// Computers & Mathematics with Applications, vol.62, no.2, pp.770-775, 2011.
//
// A corresponding matlab code was also found at:
// http://users.ntua.gr/tsitoura/new54.m
//
// Doing a step
//
void
G4TsitourasRK45::Stepper( const G4double yInput[],
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[])
G4TsitourasRK45::Stepper( const G4double yInput[],
const G4double dydx[],
G4double Step,
G4double yOut[],
G4double yErr[] )
{
G4int i;
const G4double b21 = 0.161 ,
b31 = -0.00848065549235698854 ,
b32 = 0.335480655492356989 ,
b41 = 2.89715305710549343 ,
b42 = -6.35944848997507484 ,
b43 = 4.36229543286958141 ,
const G4double
b21 = 0.161 ,
b31 = -0.00848065549235698854 ,
b32 = 0.335480655492356989 ,
b41 = 2.89715305710549343 ,
b42 = -6.35944848997507484 ,
b43 = 4.36229543286958141 ,
b51 = 5.325864828439257,
b52 = -11.748883564062828,
b53 = 7.49553934288983621 ,
b54 = -0.09249506636175525,
b51 = 5.325864828439257,
b52 = -11.748883564062828,
b53 = 7.49553934288983621 ,
b54 = -0.09249506636175525,
b61 = 5.8614554429464200,
b62 = -12.9209693178471093 ,
b63 = 8.1593678985761586 ,
b64 = -0.071584973281400997,
b65 = -0.0282690503940683829,
b61 = 5.8614554429464200,
b62 = -12.9209693178471093 ,
b63 = 8.1593678985761586 ,
b64 = -0.071584973281400997,
b65 = -0.0282690503940683829,
b71 = 0.0964607668180652295 ,
b72 = 0.01,
b73 = 0.479889650414499575,
b74 = 1.37900857410374189,
b75 = -3.2900695154360807,
b76 = 2.32471052409977398,
// c1 = 0.001780011052226 ,
// c2 = 0.000816434459657 ,
// c3 = -0.007880878010262 ,
// c4 = 0.144711007173263 ,
// c5 = -0.582357165452555 ,
// c6 = 0.458082105929187 ,
// c7 = 1.0/66.0 ;
dc1 = 0.0935237485818927066 - b71 , // - 0.001780011052226,
dc2 = 0.00865288314156636761 - b72, // - 0.000816434459657,
dc3 = 0.492893099131431868 - b73 , // + 0.007880878010262,
dc4 = 1.14023541226785810 - b74 , // 0.144711007173263,
dc5 = - 2.3291801924393646 - b75, // + 0.582357165452555,
dc6 = 1.56887504931661552 - b76 , // - 0.458082105929187,
dc7 = 0.025; //- 1.0/66.0 ;
b71 = 0.0964607668180652295 ,
b72 = 0.01,
b73 = 0.479889650414499575,
b74 = 1.37900857410374189,
b75 = -3.2900695154360807,
b76 = 2.32471052409977398,
// dc1 = -3.0/1280.0,
// dc2 = 0.0,
// dc3 = 6561.0/632320.0,
// dc4 = -343.0/20800.0,
// dc5 = 243.0/12800.0,
// dc6 = -1.0/95.0,
// dc7 = 0.0 ;
// c1 = 0.001780011052226 ,
// c2 = 0.000816434459657 ,
// c3 = -0.007880878010262 ,
// c4 = 0.144711007173263 ,
// c5 = -0.582357165452555 ,
// c6 = 0.458082105929187 ,
// c7 = 1.0/66.0 ;
dc1 = 0.0935237485818927066 - b71 , // - 0.001780011052226,
dc2 = 0.00865288314156636761 - b72, // - 0.000816434459657,
dc3 = 0.492893099131431868 - b73 , // + 0.007880878010262,
dc4 = 1.14023541226785810 - b74 , // 0.144711007173263,
dc5 = - 2.3291801924393646 - b75, // + 0.582357165452555,
dc6 = 1.56887504931661552 - b76 , // - 0.458082105929187,
dc7 = 0.025; //- 1.0/66.0 ;
// dc1 = -3.0/1280.0,
// dc2 = 0.0,
// dc3 = 6561.0/632320.0,
// dc4 = -343.0/20800.0,
// dc5 = 243.0/12800.0,
// dc6 = -1.0/95.0,
// dc7 = 0.0 ;
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
// The number of variables to be integrated over
//
yOut[7] = yTemp[7] = yIn[7] = yInput[7];
// Saving yInput because yInput and yOut can be aliases for same array
for(i=0;i<numberOfVariables;i++)
//
for(G4int i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
}
// RightHandSide(yIn, dydx) ;
// 1st Step - Not doing, getting passed
// RightHandSide(yIn, dydx) ; // 1st Step - Not doing, getting passed
for(i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + b21*Step*dydx[i] ;
}
RightHandSide(yTemp, ak2) ; // 2nd Stage
for(i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b31*dydx[i] + b32*ak2[i]) ;
}
RightHandSide(yTemp, ak3) ; // 3rd Stage
for(i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b41*dydx[i] + b42*ak2[i] + b43*ak3[i]) ;
}
RightHandSide(yTemp, ak4) ; // 4th Stage
for(i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b51*dydx[i] + b52*ak2[i] + b53*ak3[i] +
b54*ak4[i]) ;
}
RightHandSide(yTemp, ak5) ; // 5th Stage
for(i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yTemp[i] = yIn[i] + Step*(b61*dydx[i] + b62*ak2[i] + b63*ak3[i] +
b64*ak4[i] + b65*ak5[i]) ;
}
RightHandSide(yTemp, ak6) ; // 6th Stage
for(i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*(b71*dydx[i] + b72*ak2[i] + b73*ak3[i] +
b74*ak4[i] + b75*ak5[i] + b76*ak6[i]);
}
RightHandSide(yOut, ak7); //7th Stage
RightHandSide(yOut, ak7); // 7th Stage
//Calculate the error in the step:
for(i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yErr[i] = Step*(dc1*dydx[i] + dc2*ak2[i] + dc3*ak3[i] + dc4*ak4[i] +
dc5*ak5[i] + dc6*ak6[i] + dc7*ak7[i] ) ;
// Store Input and Final values, for possible use in calculating chord
//
fLastInitialVector[i] = yIn[i] ;
fLastFinalVector[i] = yOut[i];
fLastDyDx[i] = dydx[i];
@@ -257,68 +240,74 @@ G4TsitourasRK45::Stepper( const G4double yInput[],
return ;
}
void G4TsitourasRK45::SetupInterpolation() // (const G4double *yInput, const G4double *dydx, const G4double Step)
void G4TsitourasRK45::SetupInterpolation()
// (const G4double *yInput, const G4double *dydx, const G4double Step)
{
//Nothing to be done
// Nothing to be done
}
void G4TsitourasRK45::Interpolate(const G4double *yInput, const G4double *dydx, const G4double Step, G4double *yOut, G4double tau){
void G4TsitourasRK45::Interpolate(const G4double* yInput,
const G4double* dydx,
const G4double Step,
G4double* yOut,
G4double tau)
{
G4double bf1, bf2, bf3, bf4, bf5, bf6, bf7;
// Coefficients for all the seven stages.
// Coefficients for all the seven stages.
const G4int numberOfVariables= this->GetNumberOfVariables();
const G4int numberOfVariables = GetNumberOfVariables();
G4double tau0 = tau;
for(int i=0;i<numberOfVariables;i++)
for(G4int i=0; i<numberOfVariables; ++i)
{
yIn[i]=yInput[i];
yIn[i] = yInput[i];
}
G4double
tau_2 = tau0*tau0 ;
// tau_3 = tau0*tau_2,
// tau_4 = tau_2*tau_2;
G4double tau_2 = tau0*tau0 ;
// tau_3 = tau0*tau_2,
// tau_4 = tau_2*tau_2;
bf1 = -1.0530884977290216*tau*(tau - 1.3299890189751412)*(tau_2 -
1.4364028541716351*tau + 0.7139816917074209),
1.4364028541716351*tau + 0.7139816917074209);
bf2 = 0.1017*tau_2*(tau_2 - 2.1966568338249754*tau +
1.2949852507374631),
1.2949852507374631);
bf3 = 2.490627285651252793*tau_2*(tau_2 - 2.38535645472061657*tau
+ 1.57803468208092486) ,
+ 1.57803468208092486);
bf4 = -16.54810288924490272*(tau - 1.21712927295533244)*
(tau - 0.61620406037800089)*tau_2,
(tau - 0.61620406037800089)*tau_2;
bf5 = 47.37952196281928122*(tau - 1.203071208372362603)*
(tau - 0.658047292653547382)*tau_2,
(tau - 0.658047292653547382)*tau_2;
bf6 = -34.87065786149660974*(tau - 1.2)*(tau -
0.666666666666666667)*tau_2,
0.666666666666666667)*tau_2;
bf7 = 2.5*(tau - 1.0)*(tau - 0.6)*tau_2;
//Putting together the coefficients calculated as the respective stage coefficients
for( int i=0; i<numberOfVariables; i++){
yOut[i] = yIn[i] + Step*( bf1*dydx[i] + bf2*ak2[i] + bf3*ak3[i] + bf4*ak4[i]
+ bf5*ak5[i] + bf6*ak6[i] + bf7*ak7[i] ) ;
// Putting together the coefficients calculated as the respective
// stage coefficients
//
for(G4int i=0; i<numberOfVariables; ++i)
{
yOut[i] = yIn[i] + Step*( bf1*dydx[i] + bf2*ak2[i] + bf3*ak3[i]
+ bf4*ak4[i] + bf5*ak5[i] + bf6*ak6[i]
+ bf7*ak7[i] ) ;
}
}
///////////////////////////////////////////////////////////////////////////////
G4double G4TsitourasRK45::DistChord() const
{
G4double distLine, distChord;
G4ThreeVector initialPoint, finalPoint, midPoint;
// Store last initial and final points (they will be overwritten in self-Stepper call!)
// Store last initial and final points (they will be
// overwritten in self-Stepper call!)
//
initialPoint = G4ThreeVector( fLastInitialVector[0],
fLastInitialVector[1], fLastInitialVector[2]);
finalPoint = G4ThreeVector( fLastFinalVector[0],
fLastFinalVector[1], fLastFinalVector[2]);
// Do half a step using StepNoErr
//
fAuxStepper->Stepper( fLastInitialVector, fLastDyDx, 0.5 * fLastStepLength,
fMidVector, fMidError );
@@ -326,8 +315,7 @@ G4double G4TsitourasRK45::DistChord() const
// Use stored values of Initial and Endpoint + new Midpoint to evaluate
// distance of Chord
//
if (initialPoint != finalPoint)
{
distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
@@ -23,32 +23,28 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4UniformElectricField implementation
//
//
//
//
// Class for creation of uniform Electric Field
//
// 30.1.97 V.Grichine
//
// Created: V.Grichine, 30.01.1997
// -------------------------------------------------------------------
#include "G4UniformElectricField.hh"
#include "G4PhysicalConstants.hh"
G4UniformElectricField::G4UniformElectricField(const G4ThreeVector FieldVector )
G4UniformElectricField::
G4UniformElectricField(const G4ThreeVector& FieldVector)
{
fFieldComponents[0] = 0.0;
fFieldComponents[1] = 0.0;
fFieldComponents[2] = 0.0;
fFieldComponents[3] = FieldVector.x();
fFieldComponents[4] = FieldVector.y();
fFieldComponents[5] = FieldVector.z();
fFieldComponents[0] = 0.0;
fFieldComponents[1] = 0.0;
fFieldComponents[2] = 0.0;
fFieldComponents[3] = FieldVector.x();
fFieldComponents[4] = FieldVector.y();
fFieldComponents[5] = FieldVector.z();
}
G4UniformElectricField::G4UniformElectricField(G4double vField,
G4double vTheta,
G4double vPhi )
G4double vPhi)
{
if ( (vField<0) || (vTheta<0) || (vTheta>pi) || (vPhi<0) || (vPhi>twopi) )
{
@@ -64,47 +60,48 @@ G4UniformElectricField::G4UniformElectricField(G4double vField,
fFieldComponents[5] = vField*std::cos(vTheta) ;
}
G4Field* G4UniformElectricField::Clone() const
{
return new G4UniformElectricField( G4ThreeVector(fFieldComponents[3],
fFieldComponents[4],
fFieldComponents[5]) );
}
G4UniformElectricField::~G4UniformElectricField()
{
}
G4UniformElectricField::G4UniformElectricField (const G4UniformElectricField &p)
G4UniformElectricField::
G4UniformElectricField (const G4UniformElectricField& p)
: G4ElectricField(p)
{
for (G4int i=0; i<6; i++)
for (auto i=0; i<6; ++i)
{
fFieldComponents[i] = p.fFieldComponents[i];
}
}
G4UniformElectricField&
G4UniformElectricField::operator = (const G4UniformElectricField &p)
G4UniformElectricField::operator = (const G4UniformElectricField& p)
{
if (&p == this) return *this;
G4ElectricField::operator=(p);
for (G4int i=0; i<6; i++)
for (auto i=0; i<6; ++i)
{
fFieldComponents[i] = p.fFieldComponents[i];
}
return *this;
}
G4Field* G4UniformElectricField::Clone() const
{
return new G4UniformElectricField( G4ThreeVector(fFieldComponents[3],
fFieldComponents[4],
fFieldComponents[5]));
}
// ------------------------------------------------------------------------
void G4UniformElectricField::GetFieldValue (const G4double[4],
G4double *fieldBandE ) const
G4double* fieldBandE) const
{
fieldBandE[0]= 0.0;
fieldBandE[1]= 0.0;
fieldBandE[2]= 0.0;
fieldBandE[3]= fFieldComponents[3] ;
fieldBandE[4]= fFieldComponents[4] ;
fieldBandE[5]= fFieldComponents[5] ;
fieldBandE[0] = 0.0;
fieldBandE[1] = 0.0;
fieldBandE[2] = 0.0;
fieldBandE[3] = fFieldComponents[3];
fieldBandE[4] = fFieldComponents[4];
fieldBandE[5] = fFieldComponents[5];
}
@@ -23,79 +23,73 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4UniformGravityField implementation
//
// Class for creation of Uniform Gravitation Field.
//
// Created: P.Gumplinger, 14.06.2011 - Adapted from G4UniformElectricField
// Thanks to P.Fierlinger (PSI), A.Capra and A.Fontana (INFN Pavia)
// -------------------------------------------------------------------
// History:
// - 14.06.11 P.Gumplinger, Created.
// -------------------------------------------------------------------
// Adopted from G4UniformElectricField.hh
//
// Thanks to Peter Fierlinger (PSI) and
// A. Capra and A. Fontana (INFN Pavia)
// -------------------------------------------------------------------
//
#include "G4UniformGravityField.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
// Construct from a 3-vector
G4UniformGravityField::G4UniformGravityField(const G4ThreeVector FieldVector)
//
G4UniformGravityField::G4UniformGravityField(const G4ThreeVector& FieldVector)
: G4Field ( true ) // Gravity flag *on*
{
fFieldComponents[0] = FieldVector.x();
fFieldComponents[1] = FieldVector.y();
fFieldComponents[2] = FieldVector.z();
fFieldComponents[0] = FieldVector.x();
fFieldComponents[1] = FieldVector.y();
fFieldComponents[2] = FieldVector.z();
}
// Construct from a double > default = -9.81 m*s^-2
G4UniformGravityField::G4UniformGravityField(const G4double gy )
G4UniformGravityField::G4UniformGravityField(const G4double gy)
: G4Field ( true )
{
fFieldComponents[0] = 0.0;
fFieldComponents[1] = gy;
fFieldComponents[2] = 0.0;
}
G4Field* G4UniformGravityField::Clone() const
{
return new G4UniformGravityField( G4ThreeVector(fFieldComponents[0],
fFieldComponents[1],
fFieldComponents[2]) );
fFieldComponents[0] = 0.0;
fFieldComponents[1] = gy;
fFieldComponents[2] = 0.0;
}
G4UniformGravityField::~G4UniformGravityField()
{
}
G4UniformGravityField::G4UniformGravityField (const G4UniformGravityField &p)
: G4Field(p)
G4UniformGravityField::G4UniformGravityField (const G4UniformGravityField& p)
: G4Field(p)
{
for (G4int i=0; i<3; i++)
{
fFieldComponents[i] = p.fFieldComponents[i];
}
for (auto i=0; i<3; ++i)
{
fFieldComponents[i] = p.fFieldComponents[i];
}
}
G4UniformGravityField&
G4UniformGravityField::operator = (const G4UniformGravityField &p)
G4UniformGravityField::operator = (const G4UniformGravityField& p)
{
if (&p == this) return *this;
G4Field::operator=(p);
for (G4int i=0; i<3; i++)
for (auto i=0; i<3; ++i)
{
fFieldComponents[i] = p.fFieldComponents[i];
}
return *this;
}
G4Field* G4UniformGravityField::Clone() const
{
return new G4UniformGravityField( G4ThreeVector(fFieldComponents[0],
fFieldComponents[1],
fFieldComponents[2]) );
}
// -------------------------------------------------------------------
void G4UniformGravityField::GetFieldValue (const G4double [4],
G4double *G ) const
G4double* G ) const
{
G[0]= fFieldComponents[0] ;
G[1]= fFieldComponents[1] ;
G[2]= fFieldComponents[2] ;
G[0]= fFieldComponents[0];
G[1]= fFieldComponents[1];
G[2]= fFieldComponents[2];
}
@@ -23,13 +23,9 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4UniformMagField implementation
//
//
//
// Class for creation of uniform Magnetic Field
//
// 30.1.97 V.Grichine
//
// Created: V.Grichine, 30.01.1997
// -------------------------------------------------------------------
#include "G4UniformMagField.hh"
@@ -37,34 +33,58 @@
G4UniformMagField::G4UniformMagField(const G4ThreeVector& FieldVector )
{
fFieldComponents[0] = FieldVector.x();
fFieldComponents[1] = FieldVector.y();
fFieldComponents[2] = FieldVector.z();
fFieldComponents[0] = FieldVector.x();
fFieldComponents[1] = FieldVector.y();
fFieldComponents[2] = FieldVector.z();
}
G4UniformMagField::~G4UniformMagField()
{
}
G4UniformMagField::G4UniformMagField (const G4UniformMagField& p)
: G4MagneticField(p)
{
for (auto i=0; i<3; ++i)
{
fFieldComponents[i] = p.fFieldComponents[i];
}
}
G4UniformMagField& G4UniformMagField::operator = (const G4UniformMagField& p)
{
if (&p == this) return *this;
G4MagneticField::operator=(p);
for (auto i=0; i<3; ++i)
{
fFieldComponents[i] = p.fFieldComponents[i];
}
return *this;
}
G4Field* G4UniformMagField::Clone() const
{
return new G4UniformMagField( G4ThreeVector(fFieldComponents[0],
fFieldComponents[1],
fFieldComponents[2]) );
return new G4UniformMagField( G4ThreeVector(fFieldComponents[0],
fFieldComponents[1],
fFieldComponents[2]) );
}
void
G4UniformMagField::SetFieldValue(const G4ThreeVector& newFieldVector )
{
fFieldComponents[0] = newFieldVector.x();
fFieldComponents[1] = newFieldVector.y();
fFieldComponents[2] = newFieldVector.z();
fFieldComponents[0] = newFieldVector.x();
fFieldComponents[1] = newFieldVector.y();
fFieldComponents[2] = newFieldVector.z();
}
G4UniformMagField::G4UniformMagField(G4double vField,
G4double vTheta,
G4double vPhi )
G4double vPhi)
{
if ( (vField<0) || (vTheta<0) || (vTheta>pi) || (vPhi<0) || (vPhi>twopi) )
{
std::ostringstream msg;
msg << "ERROR in G4UniformMagField::G4UniformMagField(double, double, double) : "
msg << "ERROR in G4UniformMagField::G4UniformMagField() : "
<< "Invalid parameter(s). " << std::endl;
msg << " Expected " << std::endl;
@@ -83,45 +103,21 @@ G4UniformMagField::G4UniformMagField(G4double vField,
if ( (vPhi<0) || (vPhi>twopi) ) { msg << " <------ Erroneous "; }
G4Exception("G4UniformMagField::G4UniformMagField()",
"GeomField0002", FatalException, msg ); // "Invalid parameters.") ;
"GeomField0002", FatalException, msg );
}
fFieldComponents[0] = vField*std::sin(vTheta)*std::cos(vPhi) ;
fFieldComponents[1] = vField*std::sin(vTheta)*std::sin(vPhi) ;
fFieldComponents[2] = vField*std::cos(vTheta) ;
}
G4UniformMagField::~G4UniformMagField()
{
}
G4UniformMagField::G4UniformMagField (const G4UniformMagField &p)
: G4MagneticField(p)
{
for (G4int i=0; i<3; i++)
{
fFieldComponents[i] = p.fFieldComponents[i];
}
}
G4UniformMagField& G4UniformMagField::operator = (const G4UniformMagField &p)
{
if (&p == this) return *this;
G4MagneticField::operator=(p);
for (G4int i=0; i<3; i++)
{
fFieldComponents[i] = p.fFieldComponents[i];
}
return *this;
}
// ------------------------------------------------------------------------
void G4UniformMagField::GetFieldValue (const G4double [4],
G4double *B ) const
G4double* B) const
{
B[0]= fFieldComponents[0] ;
B[1]= fFieldComponents[1] ;
B[2]= fFieldComponents[2] ;
B[0]= fFieldComponents[0];
B[1]= fFieldComponents[1];
B[2]= fFieldComponents[2];
}
G4ThreeVector G4UniformMagField::GetConstantFieldValue() const
@@ -129,5 +125,5 @@ G4ThreeVector G4UniformMagField::GetConstantFieldValue() const
G4ThreeVector B(fFieldComponents[0],
fFieldComponents[1],
fFieldComponents[2]);
return B;
return B;
}
@@ -23,34 +23,34 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4VFSALIntegrationStepper implementation
//
// Author: Somnath Banerjee, Google Summer of Code 2015
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4VFSALIntegrationStepper.hh"
// Constructor for stepper abstract base class.
//
G4VFSALIntegrationStepper::G4VFSALIntegrationStepper(G4EquationOfMotion* Equation,
G4int num_integration_vars,
G4int num_state_vars)
// Constructor for stepper abstract base class
//
G4VFSALIntegrationStepper::
G4VFSALIntegrationStepper( G4EquationOfMotion* Equation,
G4int num_integration_vars,
G4int num_state_vars )
: fEquation_Rhs(Equation),
fNoIntegrationVariables(num_integration_vars),
fNoStateVariables(num_state_vars),
fNoRHSCalls(0)
// fNumberOfVariables( std::max(num_var,fNoStateVariables) )
fNoStateVariables(num_state_vars)
{
}
void G4VFSALIntegrationStepper::increasefNORHSCalls(){
// std::cout<<"Yeah, I was called!";
fNoRHSCalls++;
}
void G4VFSALIntegrationStepper::RightHandSide( const double y[], double dydx[] )
void G4VFSALIntegrationStepper::increasefNORHSCalls()
{
fEquation_Rhs-> RightHandSide(y, dydx);
increasefNORHSCalls();
++fNoRHSCalls;
}
void G4VFSALIntegrationStepper::RightHandSide( const G4double y[],
G4double dydx[] )
{
fEquation_Rhs->RightHandSide(y, dydx);
increasefNORHSCalls();
}
@@ -23,37 +23,18 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4VIntegrationDriver implementation
//
// class G4VIntegrationDriver
//
// Class description:
//
// Abstract base class for 'driver' classes which are responsible for
// undertaking integration of an state given an equation of motion and
// within acceptable error bound(s).
//
// Different integration methods are meant to be provided via this
// common interface, and can span the original type (explicit Runge Kutta
// methods), enhanced RK methods and alternatives such as the
// Bulirsch-Stoer and multi-step methods.
//
// The drivers' key mission is to insure that the error is below set values.
//
// Implementation by Dmitry Sorokin - GSoC 2017
// Work supported by Google as part of Google Summer of Code 2017.
// Supervision / code review: John Apostolakis
// Author: Dmitry Sorokin, Google Summer of Code 2017
// Supervision: John Apostolakis, CERN
// --------------------------------------------------------------------
#include "G4VIntegrationDriver.hh"
void G4VIntegrationDriver::RenewStepperAndAdjust(G4MagIntegratorStepper *)
{
G4Exception("G4VIntegrationDriver::RenewStepperAndAdjust", "Geometry001", FatalException,
"This method exists only for the original G4MagIntegratorDriver class. "
" Not defined for other classes derived from G4VIntegrationDriver");
}
G4double G4VIntegrationDriver::GetInverseCurvatureRadius(const G4FieldTrack& /*track*/,
G4double /*field*/[]) const
{
return UNKNOWN_CURVATURE_RADIUS;
G4Exception("G4VIntegrationDriver::RenewStepperAndAdjust",
"Geometry001", FatalException,
"This method exists only for the original G4MagIntegratorDriver class. "
"Not defined for other classes derived from G4VIntegrationDriver");
}