Import Geant4 10.5.0.beta source tree
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
$Id: History 107508 2017-11-20 08:23:14Z gcosmo $
|
||||
$Id: History 110833 2018-06-15 15:01:33Z gcosmo $
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=========================================================
|
||||
@@ -17,6 +17,74 @@ committal in the CVS repository !
|
||||
* Reverse chronological order (last date on top), please *
|
||||
----------------------------------------------------------
|
||||
|
||||
June 15, 2018 G.Cosmo - field-V10-04-07
|
||||
---------------------
|
||||
- Fixed minor Coverity defects in G4BurlischStoer and G4ModifiedMidPoint.
|
||||
Code cleanup.
|
||||
|
||||
June 13, 2018 G.Cosmo - field-V10-04-06
|
||||
---------------------
|
||||
- Leave override final only for clone() method in G4UniformMagField,
|
||||
not in destructor...
|
||||
|
||||
June 12, 2018 G.Cosmo - field-V10-04-05
|
||||
---------------------
|
||||
- Use G4Exception warnings instead of streaming to cerr.
|
||||
- Added override final for virtual methods in G4UniformMagField (J.Apostolakis).
|
||||
- Some code cleanup.
|
||||
|
||||
Apr 30, 2018 J. Apostolakis - field-V10-04-04
|
||||
---------------------------
|
||||
- G4VIntegrationDriver and derived classes
|
||||
|
||||
Added new virtual method in G4VIntegrationDriver :
|
||||
void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper)
|
||||
which used to exist in G4MagInt_Driver.
|
||||
( Its absence caused a problem in some existing user code since 10.4. )
|
||||
|
||||
This method must be defined in those derived driver classes which accept
|
||||
a Runge Kutta stepper ( i.e. some or any type of G4MagIntegratorStepper )
|
||||
|
||||
- G4IntegrationDriver, G4FSALIntegrationDriver
|
||||
Defined default implementation (which throws a Fatal G4Exception), and
|
||||
implementations in the templated classes G4IntegrationDriver and
|
||||
G4FSALIntegrationDriver which check the type (via dynamic cast) and
|
||||
change the stepper if it is appropriate.
|
||||
|
||||
Feb 13, 2018 J. Apostolakis - field-V10-04-03
|
||||
---------------------------
|
||||
- Change in G4FieldManager::CreateChordFinder to cope
|
||||
better with case that field argument is null.
|
||||
|
||||
Feb 13, 2018 D. Sorokin - field-V10-04-01
|
||||
----------------------- - field-V10-04-02 (comp. fix)
|
||||
- Introduced Bulirsch-Stoer method of integration, an alternative
|
||||
to Runge-Kutta based on the mid-point method.
|
||||
Separate driver derived G4VIntegrationDriver and implemented
|
||||
using specialisation of G4IntegrationDriver template class.
|
||||
Note: this method does not have a RK 'Stepper' !
|
||||
|
||||
Jan 31, 2018 J. Apostolakis
|
||||
---------------------------
|
||||
- G4MagneticField no longer inherits from G4ElectroMagneticField
|
||||
This was incorrect, and allowed a user to provide a full EM
|
||||
field, but obtain the force only from the B-field when using
|
||||
the equation created in the G4ChordFinder constructor.
|
||||
=> potential interface change.
|
||||
|
||||
Result: It is no longer possible to use the equation of motion for a
|
||||
pure magnetic field for the case of a mixed electromagnetic field.
|
||||
This change is desired, and is a *protection* as that inadvertent
|
||||
use led to incorrect results.
|
||||
Instead the full chain of classes for equation of full EM field,
|
||||
steppers and driver must be used for the case of the 'full' EM field.
|
||||
|
||||
Feb 9, 2017 G.Cosmo - field-V10-04-00
|
||||
-------------------
|
||||
- Removed static data from G4FSALIntegrationDriver, G4IntegrationDriver and
|
||||
G4MagIntegratorDriver and moved to base class as normal data members.
|
||||
Fix required for allowing proper symbol exporting on Windows DLLs.
|
||||
|
||||
Nov 17, 2017 J. Apostolakis - field-V10-03-30
|
||||
---------------------------
|
||||
- G4ChordFinder: Reinstated old driver G4MagInt_Drv, for use
|
||||
@@ -201,20 +269,13 @@ Jul 03, 2017 J.Apostolakis - field-V10-03-08
|
||||
fAuxStepper data members in constructor.
|
||||
Coverity issues: 67393, 67394, 67391, 67390, 67363
|
||||
|
||||
Jul 03, 2017 J.Apostolakis - field-V10-03-07
|
||||
--------------------------
|
||||
- G4FSALBogackiShampline45: fix for memory leak in Stepper()
|
||||
( Coverity issue 67389 )
|
||||
|
||||
Jul 03, 2017 J.Apostolakis - field-V10-03-06
|
||||
Jul 03, 2017 J.Apostolakis - field-V10-03-05, -06, -07
|
||||
--------------------------
|
||||
- fix for memory leak in Stepper() in two steppers:
|
||||
G4FSALBogackiShampline45 ( Coverity issue 67389 )
|
||||
G4FSALDormandPrince745 ( Coverity issue 67397 )
|
||||
- G4BogackiShampline23: fix for memory leak in destructor
|
||||
( Coverity issue 67355 )
|
||||
|
||||
Jun 30, 2017 J.Apostolakis - field-V10-03-05
|
||||
--------------------------
|
||||
- G4FSALDormandPrince745: fix for memory leak in Stepper()
|
||||
( Coverity issue 67397 )
|
||||
( Coverity issue 67355 )
|
||||
|
||||
May 17, 2017 J.Apostolakis - field-V10-03-03, -04 (resubmit)
|
||||
--------------------------
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: $
|
||||
//
|
||||
// Description:
|
||||
// G4BulirschStoer class implementation by Dmitry Sorokin
|
||||
// Implementation is based on bulirsch_stoer.hpp from boost
|
||||
//
|
||||
// The Bulirsch-Stoer is a controlled driver that adjusts both step size
|
||||
// and order of the method. The algorithm uses the modified midpoint and
|
||||
// a polynomial extrapolation compute the solution.
|
||||
|
||||
// Implementation by Dmitry Sorokin - GSoC 2016
|
||||
// Work supported by Google as part of Google Summer of Code 2016.
|
||||
// Supervision / code review: John Apostolakis
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef G4BULIRSCH_STOER_HH
|
||||
#define G4BULIRSCH_STOER_HH
|
||||
|
||||
#include "G4ModifiedMidpoint.hh"
|
||||
|
||||
#include "G4FieldTrack.hh"
|
||||
|
||||
class G4BulirschStoer
|
||||
{
|
||||
public:
|
||||
|
||||
enum class step_result
|
||||
{
|
||||
success,
|
||||
fail
|
||||
};
|
||||
|
||||
G4BulirschStoer( G4EquationOfMotion* equation, G4int nvar,
|
||||
G4double eps_rel, G4double max_dt = DBL_MAX);
|
||||
|
||||
inline void set_max_dt(G4double max_dt);
|
||||
inline void set_max_relative_error(G4double eps_rel);
|
||||
|
||||
// Stepper method
|
||||
//
|
||||
step_result try_step(const G4double in[], const G4double dxdt[],
|
||||
G4double& t, G4double out[], G4double& dt);
|
||||
|
||||
// Reset the internal state of the stepper
|
||||
//
|
||||
void reset();
|
||||
|
||||
inline void SetEquationOfMotion(G4EquationOfMotion* equation);
|
||||
inline G4EquationOfMotion* GetEquationOfMotion();
|
||||
|
||||
inline G4int GetNumberOfVariables() const;
|
||||
|
||||
private:
|
||||
|
||||
const static G4int m_k_max = 8;
|
||||
|
||||
void extrapolate(size_t k, G4double xest[]);
|
||||
G4double calc_h_opt(G4double h, G4double error, size_t k) const;
|
||||
|
||||
G4bool set_k_opt(size_t k, G4double& dt);
|
||||
G4bool in_convergence_window(G4int k) const;
|
||||
G4bool should_reject(G4double error, G4int k) const;
|
||||
|
||||
// Number of vars to be integrated
|
||||
G4int fnvar;
|
||||
|
||||
// Relative tolerance
|
||||
G4double m_eps_rel;
|
||||
|
||||
// Modified midpoint algorithm
|
||||
G4ModifiedMidpoint m_midpoint;
|
||||
|
||||
G4bool m_last_step_rejected;
|
||||
G4bool m_first;
|
||||
|
||||
G4double m_dt_last;
|
||||
// G4double m_t_last;
|
||||
|
||||
// Max allowed time step
|
||||
G4double m_max_dt;
|
||||
|
||||
G4int m_current_k_opt;
|
||||
|
||||
// G4double m_xnew[G4FieldTrack::ncompSVEC];
|
||||
G4double m_err[G4FieldTrack::ncompSVEC];
|
||||
// G4double m_dxdt[G4FieldTrack::ncompSVEC];
|
||||
|
||||
// Stores the successive interval counts
|
||||
G4int m_interval_sequence[m_k_max+1];
|
||||
|
||||
// Extrapolation coeffs (Neville’s algorithm)
|
||||
G4double m_coeff[m_k_max+1][m_k_max];
|
||||
|
||||
// Costs for interval count
|
||||
G4int m_cost[m_k_max+1];
|
||||
|
||||
// Sequence of states for extrapolation
|
||||
G4double m_table[m_k_max][G4FieldTrack::ncompSVEC];
|
||||
|
||||
// Optimal step size
|
||||
G4double h_opt[m_k_max+1];
|
||||
|
||||
// Work per unit step
|
||||
G4double work[m_k_max+1];
|
||||
};
|
||||
|
||||
#include "G4BulirschStoer.icc"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
inline void G4BulirschStoer::set_max_dt(G4double max_dt)
|
||||
{
|
||||
m_max_dt = max_dt;
|
||||
}
|
||||
|
||||
inline void G4BulirschStoer::set_max_relative_error(G4double eps_rel)
|
||||
{
|
||||
m_eps_rel = eps_rel;
|
||||
}
|
||||
|
||||
inline void G4BulirschStoer::SetEquationOfMotion(G4EquationOfMotion* equation)
|
||||
{
|
||||
m_midpoint.SetEquationOfMotion(equation);
|
||||
}
|
||||
|
||||
inline G4EquationOfMotion* G4BulirschStoer::GetEquationOfMotion()
|
||||
{
|
||||
return m_midpoint.GetEquationOfMotion();
|
||||
}
|
||||
|
||||
inline G4int G4BulirschStoer::GetNumberOfVariables() const
|
||||
{
|
||||
return fnvar;
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: $
|
||||
//
|
||||
// Helper namespace 'magneticfield'
|
||||
//
|
||||
// Description:
|
||||
// class G4IntegrationDriver<G4BulirschStoer> implementation by Dmitry Sorokin
|
||||
// This driver class uses Bulirsch-Stoer method to integrate
|
||||
// the equation of motion
|
||||
//
|
||||
// Implementation by Dmitry Sorokin - GSoC 2016
|
||||
// Work supported by Google as part of Google Summer of Code 2016.
|
||||
// Supervision / code review: John Apostolakis
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef G4BULIRSCH_STOER_DRIVER_HH
|
||||
#define G4BULIRSCH_STOER_DRIVER_HH
|
||||
|
||||
#include "G4IntegrationDriver.hh"
|
||||
#include "G4BulirschStoer.hh"
|
||||
|
||||
template <>
|
||||
class G4IntegrationDriver<G4BulirschStoer>: public G4VIntegrationDriver {
|
||||
public:
|
||||
G4IntegrationDriver(
|
||||
G4double hminimum,
|
||||
G4BulirschStoer* stepper,
|
||||
G4int numberOfComponents = 6,
|
||||
G4int statisticsVerbosity = 1);
|
||||
|
||||
~G4IntegrationDriver() = default;
|
||||
|
||||
G4IntegrationDriver(const G4IntegrationDriver&) = delete;
|
||||
G4IntegrationDriver& operator=(const G4IntegrationDriver&) = delete;
|
||||
|
||||
virtual G4bool AccurateAdvance(
|
||||
G4FieldTrack& track,
|
||||
G4double stepLen,
|
||||
G4double eps,
|
||||
G4double beginStep = 0) override;
|
||||
|
||||
virtual G4bool QuickAdvance(
|
||||
G4FieldTrack& y_val,
|
||||
const G4double dydx[],
|
||||
G4double hstep,
|
||||
G4double& missDist,
|
||||
G4double& dyerr) override;
|
||||
|
||||
void OneGoodStep(
|
||||
G4double y[],
|
||||
const G4double dydx[],
|
||||
G4double& curveLength,
|
||||
G4double htry,
|
||||
G4double eps,
|
||||
G4double& hdid,
|
||||
G4double& hnext);
|
||||
|
||||
virtual void GetDerivatives(
|
||||
const G4FieldTrack& track,
|
||||
G4double dydx[]) const override;
|
||||
|
||||
virtual void SetVerboseLevel(G4int level) override;
|
||||
virtual G4int GetVerboseLevel() const override;
|
||||
|
||||
virtual G4double ComputeNewStepSize(
|
||||
G4double errMaxNorm, // normalised error
|
||||
G4double hstepCurrent) override; // current step size
|
||||
|
||||
virtual G4EquationOfMotion* GetEquationOfMotion() override;
|
||||
const G4EquationOfMotion* GetEquationOfMotion() const;
|
||||
virtual void SetEquationOfMotion(G4EquationOfMotion* equation) override;
|
||||
|
||||
virtual const G4MagIntegratorStepper* GetStepper() const override;
|
||||
virtual G4MagIntegratorStepper* GetStepper() override;
|
||||
|
||||
private:
|
||||
G4int GetNumberOfVarialbles() const;
|
||||
|
||||
G4double fMinimumStep;
|
||||
G4double fVerbosity;
|
||||
|
||||
G4ModifiedMidpoint fMidpointMethod;
|
||||
G4BulirschStoer* bulirschStoer;
|
||||
|
||||
G4double yIn[G4FieldTrack::ncompSVEC],
|
||||
yMid[G4FieldTrack::ncompSVEC],
|
||||
yMid2[G4FieldTrack::ncompSVEC],
|
||||
yOut[G4FieldTrack::ncompSVEC],
|
||||
yOut2[G4FieldTrack::ncompSVEC],
|
||||
yError[G4FieldTrack::ncompSVEC];
|
||||
|
||||
|
||||
G4double dydxCurrent[G4FieldTrack::ncompSVEC];
|
||||
G4double yCurrent[G4FieldTrack::ncompSVEC];
|
||||
|
||||
G4double derivs[2][6][G4FieldTrack::ncompSVEC];
|
||||
|
||||
const G4int interval_sequence[2];
|
||||
};
|
||||
|
||||
#include "G4BulirschStoerDriver.icc"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,386 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
#include "G4LineSection.hh"
|
||||
#include "G4FieldUtils.hh"
|
||||
|
||||
G4IntegrationDriver<G4BulirschStoer>::G4IntegrationDriver(
|
||||
G4double hminimum,
|
||||
G4BulirschStoer* stepper,
|
||||
G4int numberOfComponents,
|
||||
G4int statisticsVerbosity)
|
||||
: fMinimumStep(hminimum)
|
||||
, fVerbosity(statisticsVerbosity)
|
||||
, fMidpointMethod(
|
||||
stepper->GetEquationOfMotion(), stepper->GetNumberOfVariables())
|
||||
, bulirschStoer(stepper)
|
||||
, interval_sequence{2,4}
|
||||
{
|
||||
assert(stepper->GetNumberOfVariables() == numberOfComponents);
|
||||
}
|
||||
|
||||
G4bool G4IntegrationDriver<G4BulirschStoer>::AccurateAdvance(
|
||||
G4FieldTrack& track,
|
||||
G4double hstep,
|
||||
G4double eps,
|
||||
G4double hinitial)
|
||||
{
|
||||
G4int fNoTotalSteps = 0;
|
||||
G4int fMaxNoSteps = 10000;
|
||||
G4double fNoBadSteps = 0;
|
||||
G4double fSmallestFraction = 1.0e-12;
|
||||
|
||||
// Driver with adaptive stepsize control. Integrate starting
|
||||
// values at y_current over hstep x2 with accuracy eps.
|
||||
// On output ystart is replaced by values at the end of the integration
|
||||
// interval. RightHandSide is the right-hand side of ODE system.
|
||||
// The source is similar to odeint routine from NRC p.721-722 .
|
||||
|
||||
|
||||
// Ensure that hstep > 0
|
||||
if(hstep == 0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Proposed step is zero; hstep = " << hstep << " !";
|
||||
G4Exception("G4IntegrationDriver<G4BulirschStoer>::AccurateAdvance()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
|
||||
return true;
|
||||
}
|
||||
if(hstep < 0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid run condition." << G4endl
|
||||
<< "Proposed step is negative; hstep = " << hstep << "." << G4endl
|
||||
<< "Requested step cannot be negative! Aborting event.";
|
||||
G4Exception("G4IntegrationDriver<G4BulirschStoer>::AccurateAdvance()",
|
||||
"GeomField0003", EventMustBeAborted, message);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//init first step size
|
||||
G4double h;
|
||||
if ( (hinitial > 0) && (hinitial < hstep)
|
||||
&& (hinitial > perMillion * hstep) )
|
||||
{
|
||||
h = hinitial;
|
||||
}
|
||||
else // Initial Step size "h" defaults to the full interval
|
||||
{
|
||||
h = hstep;
|
||||
}
|
||||
|
||||
//integration variables
|
||||
track.DumpToArray(yCurrent);
|
||||
//copy non-integration variables to out array
|
||||
memcpy(yOut + GetNumberOfVarialbles(),
|
||||
yCurrent + GetNumberOfVarialbles(),
|
||||
sizeof(G4double) * (G4FieldTrack::ncompSVEC - GetNumberOfVarialbles()));
|
||||
|
||||
G4double startCurveLength = track.GetCurveLength();
|
||||
G4double curveLength = startCurveLength;
|
||||
G4double endCurveLength = startCurveLength + hstep;
|
||||
|
||||
//loop variables
|
||||
G4int nstp = 1, no_warnings = 0;
|
||||
G4double hnext, hdid;
|
||||
|
||||
|
||||
G4bool succeeded = true, lastStepSucceeded;
|
||||
|
||||
G4int noFullIntegr = 0, noSmallIntegr = 0 ;
|
||||
static G4ThreadLocal G4int noGoodSteps = 0 ; // Bad = chord > curve-len
|
||||
|
||||
G4bool lastStep = false;
|
||||
|
||||
//BulirschStoer->reset();
|
||||
|
||||
G4FieldTrack yFldTrk(track);
|
||||
|
||||
do
|
||||
{
|
||||
G4ThreeVector StartPos(yCurrent[0], yCurrent[1], yCurrent[2]);
|
||||
GetEquationOfMotion()->RightHandSide(yCurrent, dydxCurrent);
|
||||
fNoTotalSteps++;
|
||||
|
||||
// Perform the Integration
|
||||
if(h == 0){
|
||||
G4Exception("G4IntegrationDriver<G4BulirschStoer>::AccurateAdvance()",
|
||||
"GeomField0003", FatalException,
|
||||
"Integration Step became Zero!");
|
||||
}
|
||||
else if(h > fMinimumStep){
|
||||
//step size if Ok
|
||||
OneGoodStep(yCurrent,dydxCurrent,curveLength,h,eps,hdid,hnext);
|
||||
lastStepSucceeded = (hdid == h);
|
||||
}
|
||||
else{
|
||||
// for small steps call QuickAdvance for speed
|
||||
|
||||
G4double dchord_step, dyerr, dyerr_len; // What to do with these ?
|
||||
yFldTrk.LoadFromArray(yCurrent, G4FieldTrack::ncompSVEC);
|
||||
yFldTrk.SetCurveLength(curveLength);
|
||||
|
||||
QuickAdvance(yFldTrk, dydxCurrent, h, dchord_step, dyerr_len);
|
||||
|
||||
yFldTrk.DumpToArray(yCurrent);
|
||||
|
||||
|
||||
dyerr = dyerr_len / h;
|
||||
hdid = h;
|
||||
curveLength += hdid;
|
||||
|
||||
// Compute suggested new step
|
||||
//hnext = ComputeNewStepSize(dyerr/eps, h);
|
||||
hnext = h;
|
||||
|
||||
//hnext= ComputeNewStepSize_WithinLimits( dyerr/eps, h);
|
||||
lastStepSucceeded = (dyerr <= eps);
|
||||
}
|
||||
|
||||
|
||||
lastStepSucceeded ? ++noFullIntegr : ++noSmallIntegr;
|
||||
|
||||
|
||||
G4ThreeVector EndPos(yCurrent[0], yCurrent[1], yCurrent[2]);
|
||||
|
||||
// Check the endpoint
|
||||
G4double endPointDist = (EndPos - StartPos).mag();
|
||||
if (endPointDist >= hdid*(1. + perMillion))
|
||||
{
|
||||
++fNoBadSteps;
|
||||
|
||||
// Issue a warning only for gross differences -
|
||||
// we understand how small difference occur.
|
||||
if (endPointDist >= hdid*(1.+perThousand))
|
||||
{
|
||||
++no_warnings;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++noGoodSteps;
|
||||
}
|
||||
|
||||
// Avoid numerous small last steps
|
||||
if((h < eps * hstep) || (h < fSmallestFraction * startCurveLength))
|
||||
{
|
||||
// No more integration -- the next step will not happen
|
||||
lastStep = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check the proposed next stepsize
|
||||
if(std::fabs(hnext) < fMinimumStep)
|
||||
{
|
||||
// Make sure that the next step is at least Hmin.
|
||||
h = fMinimumStep;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = hnext;
|
||||
}
|
||||
|
||||
// Ensure that the next step does not overshoot
|
||||
if (curveLength + h > endCurveLength)
|
||||
{
|
||||
h = endCurveLength - curveLength;
|
||||
}
|
||||
|
||||
if (h == 0)
|
||||
{
|
||||
// Cannot progress - accept this as last step - by default
|
||||
lastStep = true;
|
||||
}
|
||||
}
|
||||
} while (((nstp++) <= fMaxNoSteps) && (curveLength < endCurveLength) && (!lastStep));
|
||||
// Have we reached the end ?
|
||||
// --> a better test might be x-x2 > an_epsilon
|
||||
|
||||
succeeded = (curveLength >= endCurveLength); // If it was a "forced" last step
|
||||
|
||||
//copy integrated vars to output array
|
||||
memcpy(yOut, yCurrent, sizeof(G4double) * GetNumberOfVarialbles());
|
||||
|
||||
// upload new state
|
||||
track.LoadFromArray(yOut, G4FieldTrack::ncompSVEC);
|
||||
track.SetCurveLength(curveLength);
|
||||
|
||||
if(nstp > fMaxNoSteps) {
|
||||
++no_warnings;
|
||||
succeeded = false;
|
||||
}
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
G4bool G4IntegrationDriver<G4BulirschStoer>::QuickAdvance(
|
||||
G4FieldTrack& track,
|
||||
const G4double dydx[],
|
||||
G4double hstep,
|
||||
G4double& missDist,
|
||||
G4double& dyerr)
|
||||
{
|
||||
const auto nvar = fMidpointMethod.GetNumberOfVariables();
|
||||
|
||||
track.DumpToArray(yIn);
|
||||
const G4double curveLength = track.GetCurveLength();
|
||||
|
||||
fMidpointMethod.SetSteps(interval_sequence[0]);
|
||||
fMidpointMethod.DoStep(yIn, dydx, yOut, hstep, yMid, derivs[0]);
|
||||
|
||||
fMidpointMethod.SetSteps(interval_sequence[1]);
|
||||
fMidpointMethod.DoStep(yIn, dydx, yOut2, hstep, yMid2, derivs[1]);
|
||||
|
||||
//extrapolation
|
||||
static const G4double coeff =
|
||||
1. / (sqr(static_cast<G4double>(interval_sequence[1]) /
|
||||
static_cast<G4double>(interval_sequence[0])) - 1.);
|
||||
|
||||
for (G4int i = 0; i < nvar; ++i) {
|
||||
yOut[i] = yOut2[i] + (yOut2[i] - yOut[i]) * coeff;
|
||||
yMid[i] = yMid2[i] + (yMid2[i] - yMid[i]) * coeff;
|
||||
}
|
||||
|
||||
//calc chord lenght
|
||||
const auto mid = field_utils::makeVector(yMid, field_utils::Value3D::Position);
|
||||
const auto in = field_utils::makeVector(yIn, field_utils::Value3D::Position);
|
||||
const auto out = field_utils::makeVector(yOut, field_utils::Value3D::Position);
|
||||
|
||||
missDist = G4LineSection::Distline(mid, in, out);
|
||||
|
||||
//calc error
|
||||
for (G4int i = 0; i < nvar; ++i){
|
||||
yError[i] = yOut[i] - yOut2[i];
|
||||
}
|
||||
|
||||
dyerr = hstep * field_utils::relativeError(yOut, yError, hstep);
|
||||
|
||||
|
||||
//copy non-integrated variables to output array
|
||||
memcpy(yOut + nvar,
|
||||
yIn + nvar,
|
||||
sizeof(G4double) * (G4FieldTrack::ncompSVEC - nvar));
|
||||
|
||||
//set new state
|
||||
track.LoadFromArray(yOut, G4FieldTrack::ncompSVEC);
|
||||
track.SetCurveLength(curveLength + hstep);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void G4IntegrationDriver<G4BulirschStoer>::OneGoodStep(
|
||||
G4double y[],
|
||||
const G4double dydx[],
|
||||
G4double& curveLength,
|
||||
G4double htry,
|
||||
G4double eps,
|
||||
G4double& hdid,
|
||||
G4double& hnext)
|
||||
{
|
||||
hnext = htry;
|
||||
G4double curveLengthBegin = curveLength;
|
||||
|
||||
// set maximum allowed error
|
||||
bulirschStoer->set_max_relative_error(eps);
|
||||
|
||||
while (true) {
|
||||
auto res = bulirschStoer->try_step(y, dydx, curveLength, yOut, hnext);
|
||||
if (res == G4BulirschStoer::step_result::success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(y, yOut, sizeof(G4double) * GetNumberOfVarialbles());
|
||||
hdid = curveLength - curveLengthBegin;
|
||||
}
|
||||
|
||||
void G4IntegrationDriver<G4BulirschStoer>::GetDerivatives(
|
||||
const G4FieldTrack& track,
|
||||
G4double dydx[]) const
|
||||
{
|
||||
G4double y[G4FieldTrack::ncompSVEC];
|
||||
track.DumpToArray(y);
|
||||
GetEquationOfMotion()->RightHandSide(y, dydx);
|
||||
}
|
||||
|
||||
void G4IntegrationDriver<G4BulirschStoer>::SetVerboseLevel(G4int level)
|
||||
{
|
||||
fVerbosity = level;
|
||||
}
|
||||
|
||||
G4int G4IntegrationDriver<G4BulirschStoer>::GetVerboseLevel() const
|
||||
{
|
||||
return fVerbosity;
|
||||
}
|
||||
|
||||
G4double G4IntegrationDriver<G4BulirschStoer>::ComputeNewStepSize(
|
||||
G4double /* errMaxNorm*/,
|
||||
G4double hstepCurrent)
|
||||
{
|
||||
return hstepCurrent;
|
||||
}
|
||||
|
||||
G4EquationOfMotion* G4IntegrationDriver<G4BulirschStoer>::GetEquationOfMotion()
|
||||
{
|
||||
assert(bulirschStoer->GetEquationOfMotion() ==
|
||||
fMidpointMethod.GetEquationOfMotion());
|
||||
|
||||
return bulirschStoer->GetEquationOfMotion();
|
||||
}
|
||||
|
||||
const G4EquationOfMotion* G4IntegrationDriver<G4BulirschStoer>::GetEquationOfMotion() const
|
||||
{
|
||||
return const_cast<G4IntegrationDriver<G4BulirschStoer>*>(this)->
|
||||
GetEquationOfMotion();
|
||||
}
|
||||
|
||||
void G4IntegrationDriver<G4BulirschStoer>::SetEquationOfMotion(
|
||||
G4EquationOfMotion* equation)
|
||||
{
|
||||
bulirschStoer->SetEquationOfMotion(equation);
|
||||
fMidpointMethod.SetEquationOfMotion(equation);
|
||||
}
|
||||
|
||||
G4int G4IntegrationDriver<G4BulirschStoer>::GetNumberOfVarialbles() const
|
||||
{
|
||||
assert(bulirschStoer->GetNumberOfVariables() ==
|
||||
fMidpointMethod.GetNumberOfVariables());
|
||||
|
||||
return bulirschStoer->GetNumberOfVariables();
|
||||
}
|
||||
|
||||
const G4MagIntegratorStepper* G4IntegrationDriver<G4BulirschStoer>::GetStepper() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
G4MagIntegratorStepper* G4IntegrationDriver<G4BulirschStoer>::GetStepper()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4FSALIntegrationDriver.hh 107164 2017-11-03 12:11:45Z gcosmo $
|
||||
// $Id: G4FSALIntegrationDriver.hh 109569 2018-05-02 07:08:33Z gcosmo $
|
||||
//
|
||||
//
|
||||
// class G4FSALIntegrationDriver
|
||||
@@ -106,10 +106,12 @@ public:
|
||||
G4double GetPshrnk() const;
|
||||
G4double GetPgrow() const;
|
||||
|
||||
virtual void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper) override;
|
||||
|
||||
// Sets a new stepper pItsStepper for this driver. Then it calls
|
||||
// ReSetParameters to reset its parameters accordingly.
|
||||
void RenewStepperAndAdjust(T *pItsStepper);
|
||||
|
||||
inline void RenewStepperAndAdjustStrict(T *pItsStepper);
|
||||
|
||||
// i) sets the exponents (pgrow & pshrnk),
|
||||
// using the current Stepper's order,
|
||||
// ii) sets the safety
|
||||
@@ -160,7 +162,7 @@ private:
|
||||
|
||||
// The (default) maximum number of steps is Base
|
||||
// divided by the order of Stepper
|
||||
static constexpr G4int fMaxStepBase = 250;
|
||||
G4int fMaxStepBase;
|
||||
|
||||
// Parameters used to grow and shrink trial stepsize.
|
||||
G4double safety;
|
||||
@@ -171,10 +173,6 @@ private:
|
||||
G4double errorConstraintShrink;
|
||||
G4double errorConstraintGrow;
|
||||
|
||||
// Maximum stepsize increase/decrease factors.
|
||||
static constexpr G4double max_stepping_increase = 5;
|
||||
static constexpr G4double max_stepping_decrease = 0.1;
|
||||
|
||||
T* pIntStepper;
|
||||
|
||||
// Step Statistics
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4FSALIntegrationDriver.icc 107495 2017-11-16 13:51:06Z gcosmo $
|
||||
// $Id: G4FSALIntegrationDriver.icc 110753 2018-06-12 15:44:03Z gcosmo $
|
||||
//
|
||||
//
|
||||
// class G4FSALIntegrationDriver
|
||||
@@ -47,11 +47,9 @@
|
||||
|
||||
|
||||
template <class T>
|
||||
G4FSALIntegrationDriver<T>::G4FSALIntegrationDriver (
|
||||
G4double hminimum,
|
||||
T* pStepper,
|
||||
G4int numComponents,
|
||||
G4int statisticsVerbose)
|
||||
G4FSALIntegrationDriver<T>::
|
||||
G4FSALIntegrationDriver ( G4double hminimum, T* pStepper,
|
||||
G4int numComponents, G4int statisticsVerbose )
|
||||
: fSmallestFraction(1e-12),
|
||||
fNoTotalSteps(0),
|
||||
fNoBadSteps(0),
|
||||
@@ -59,24 +57,31 @@ G4FSALIntegrationDriver<T>::G4FSALIntegrationDriver (
|
||||
fVerboseLevel(statisticsVerbose),
|
||||
fNoQuickAvanceCalls(0)
|
||||
{
|
||||
if (numComponents != pStepper->GetNumberOfVariables()) {
|
||||
if (numComponents != pStepper->GetNumberOfVariables())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Driver's number of integrated components " << numComponents
|
||||
<< " != Stepper's number of components " << pStepper->GetNumberOfVariables();
|
||||
G4Exception("G4FSALIntegrationDriver","001", FatalException, message);
|
||||
message << "Driver's number of integrated components "
|
||||
<< numComponents
|
||||
<< " != Stepper's number of components "
|
||||
<< pStepper->GetNumberOfVariables();
|
||||
G4Exception("G4FSALIntegrationDriver","GeomField0002",
|
||||
FatalException, message);
|
||||
}
|
||||
RenewStepperAndAdjust(pStepper);
|
||||
fMinimumStep = hminimum;
|
||||
fMaxStepBase = 250;
|
||||
fMaxNoSteps = fMaxStepBase / pIntStepper->IntegratorOrder();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4FSALIntegrationDriver<T>::~G4FSALIntegrationDriver()
|
||||
{
|
||||
if( fVerboseLevel > 0 )
|
||||
G4cout << "G4FSALIntegration Driver Stats: "
|
||||
<< "#QuickAdvance " << fNoQuickAvanceCalls
|
||||
<< " #AccurateAdvance " << fNoTotalSteps << G4endl;
|
||||
#ifdef G4VERBOSE
|
||||
if( fVerboseLevel > 0 )
|
||||
G4cout << "G4FSALIntegration Driver Stats: "
|
||||
<< "#QuickAdvance " << fNoQuickAvanceCalls
|
||||
<< " - #AccurateAdvance " << fNoTotalSteps << G4endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Runge-Kutta driver with adaptive stepsize control. Integrate starting
|
||||
@@ -85,13 +90,12 @@ G4FSALIntegrationDriver<T>::~G4FSALIntegrationDriver()
|
||||
// interval. RightHandSide is the right-hand side of ODE system.
|
||||
// The source is similar to odeint routine from NRC p.721-722 .
|
||||
template <class T>
|
||||
G4bool G4FSALIntegrationDriver<T>::AccurateAdvance(
|
||||
G4FieldTrack& track,
|
||||
G4double hstep,
|
||||
G4double eps,
|
||||
G4double hinitial)
|
||||
G4bool G4FSALIntegrationDriver<T>::
|
||||
AccurateAdvance( G4FieldTrack& track, G4double hstep,
|
||||
G4double eps, G4double hinitial )
|
||||
{
|
||||
if (hstep < GetMinimumStep()) {
|
||||
if (hstep < GetMinimumStep())
|
||||
{
|
||||
G4double dchord_step = 0, dyerr = 0;
|
||||
G4double dydx[G4FieldTrack::ncompSVEC];
|
||||
GetDerivatives(track, dydx);
|
||||
@@ -113,13 +117,15 @@ G4bool G4FSALIntegrationDriver<T>::AccurateAdvance(
|
||||
|
||||
|
||||
G4double h = hstep;
|
||||
if (hinitial > perMillion * hstep && hinitial < hstep) {
|
||||
if (hinitial > perMillion * hstep && hinitial < hstep)
|
||||
{
|
||||
h = hinitial;
|
||||
}
|
||||
|
||||
pIntStepper->RightHandSide(y, dydx);
|
||||
|
||||
for (G4int iter = 0; iter < fMaxNoSteps; ++iter) {
|
||||
for (G4int iter = 0; iter < fMaxNoSteps; ++iter)
|
||||
{
|
||||
const G4ThreeVector StartPos =
|
||||
field_utils::makeVector(y, field_utils::Value3D::Position);
|
||||
|
||||
@@ -131,16 +137,17 @@ G4bool G4FSALIntegrationDriver<T>::AccurateAdvance(
|
||||
CheckStep(EndPos, StartPos, hdid);
|
||||
|
||||
G4double restCurveLength = endCurveLength - curveLength;
|
||||
if (restCurveLength < GetSmallestFraction() * hstep) {
|
||||
if (restCurveLength < GetSmallestFraction() * hstep)
|
||||
{
|
||||
succeeded = true;
|
||||
break;
|
||||
}
|
||||
|
||||
h = std::min(hnext, restCurveLength);
|
||||
}
|
||||
|
||||
|
||||
if (succeeded) {
|
||||
if (succeeded)
|
||||
{
|
||||
track.LoadFromArray(y, pIntStepper->GetNumberOfVariables());
|
||||
track.SetCurveLength(track.GetCurveLength() + curveLength);
|
||||
}
|
||||
@@ -150,9 +157,11 @@ G4bool G4FSALIntegrationDriver<T>::AccurateAdvance(
|
||||
|
||||
// Step failed; compute the size of retrial Step.
|
||||
template <class T>
|
||||
G4double G4FSALIntegrationDriver<T>::ShrinkStepSize(G4double h, G4double error) const
|
||||
G4double G4FSALIntegrationDriver<T>::
|
||||
ShrinkStepSize(G4double h, G4double error) const
|
||||
{
|
||||
if (error > errorConstraintShrink) {
|
||||
if (error > errorConstraintShrink)
|
||||
{
|
||||
return max_stepping_decrease * h;
|
||||
}
|
||||
return GetSafety() * h * std::pow(error, GetPshrnk());
|
||||
@@ -160,7 +169,8 @@ G4double G4FSALIntegrationDriver<T>::ShrinkStepSize(G4double h, G4double error)
|
||||
|
||||
// Compute size of next Step
|
||||
template<class T>
|
||||
G4double G4FSALIntegrationDriver<T>::GrowStepSize(G4double h, G4double error) const
|
||||
G4double G4FSALIntegrationDriver<T>::
|
||||
GrowStepSize(G4double h, G4double error) const
|
||||
{
|
||||
if (error < errorConstraintGrow) {
|
||||
return max_stepping_increase * h;
|
||||
@@ -180,15 +190,14 @@ G4double G4FSALIntegrationDriver<T>::GrowStepSize(G4double h, G4double error) co
|
||||
// Edition, by William H. Press, Saul A. Teukolsky, William T.
|
||||
// Vetterling, and Brian P. Flannery (Cambridge University Press 1992),
|
||||
// 16.2 Adaptive StepSize Control for Runge-Kutta, p. 719
|
||||
//
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::OneGoodStep(
|
||||
G4double y[],
|
||||
G4double dydx[],
|
||||
G4double& curveLength, // InOut
|
||||
G4double htry,
|
||||
G4double eps_rel_max,
|
||||
G4double& hdid, // Out
|
||||
G4double& hnext) // Out
|
||||
void G4FSALIntegrationDriver<T>::
|
||||
OneGoodStep( G4double y[], G4double dydx[],
|
||||
G4double& curveLength, // InOut
|
||||
G4double htry, G4double eps_rel_max,
|
||||
G4double& hdid, // Out
|
||||
G4double& hnext ) // Out
|
||||
{
|
||||
G4double error = DBL_MAX;
|
||||
|
||||
@@ -202,16 +211,15 @@ void G4FSALIntegrationDriver<T>::OneGoodStep(
|
||||
static G4ThreadLocal G4int tot_no_trials = 0;
|
||||
const G4int max_trials = 100;
|
||||
|
||||
for (G4int iter = 0; iter < max_trials; ++iter) {
|
||||
for (G4int iter = 0; iter < max_trials; ++iter)
|
||||
{
|
||||
++tot_no_trials;
|
||||
|
||||
pIntStepper->Stepper(y, dydx, hstep, yOut, yError, dydxOut);
|
||||
error = field_utils::relativeError(y, yError, hstep, eps_rel_max);
|
||||
|
||||
// Step succeeded.
|
||||
if (error <= 1) {
|
||||
break;
|
||||
}
|
||||
if (error <= 1) break;
|
||||
|
||||
hstep = ShrinkStepSize(hstep, error);
|
||||
}
|
||||
@@ -219,33 +227,34 @@ void G4FSALIntegrationDriver<T>::OneGoodStep(
|
||||
hnext = GrowStepSize(hstep, error);
|
||||
curveLength += (hdid = hstep);
|
||||
|
||||
for(G4int k = 0; k < pIntStepper->GetNumberOfVariables(); ++k) {
|
||||
for(G4int k = 0; k < pIntStepper->GetNumberOfVariables(); ++k)
|
||||
{
|
||||
y[k] = yOut[k];
|
||||
dydx[k] = dydxOut[k];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4bool G4FSALIntegrationDriver<T>::QuickAdvance(
|
||||
G4FieldTrack& fieldTrack,
|
||||
const G4double dydxIn[],
|
||||
G4double hstep,
|
||||
G4double& dchord_step,
|
||||
G4double& dyerr)
|
||||
G4bool G4FSALIntegrationDriver<T>::
|
||||
QuickAdvance( G4FieldTrack& fieldTrack, const G4double dydxIn[],
|
||||
G4double hstep, G4double& dchord_step, G4double& dyerr )
|
||||
{
|
||||
++fNoQuickAvanceCalls;
|
||||
|
||||
if (hstep == 0) {
|
||||
if (hstep == 0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Proposed step is zero; hstep = " << hstep << " !";
|
||||
G4Exception("G4FSALIntegrationDriver ::QuickAdvance()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
return true;
|
||||
}
|
||||
if (hstep < 0) {
|
||||
if (hstep < 0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid run condition." << G4endl
|
||||
<< "Proposed step is negative; hstep = " << hstep << "." << G4endl
|
||||
<< "Proposed step is negative; hstep = "
|
||||
<< hstep << "." << G4endl
|
||||
<< "Requested step cannot be negative! Aborting event.";
|
||||
G4Exception("G4FSALIntegrationDriver ::QuickAdvance()",
|
||||
"GeomField0003", EventMustBeAborted, message);
|
||||
@@ -271,18 +280,21 @@ G4bool G4FSALIntegrationDriver<T>::QuickAdvance(
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4double G4FSALIntegrationDriver<T>::ComputeNewStepSize(
|
||||
G4double errMaxNorm, // max error (normalised)
|
||||
G4double hstepCurrent) // current step size
|
||||
G4double G4FSALIntegrationDriver<T>::
|
||||
ComputeNewStepSize( G4double errMaxNorm, // max error (normalised)
|
||||
G4double hstepCurrent ) // current step size
|
||||
{
|
||||
if (errMaxNorm > 1) {
|
||||
if (errMaxNorm > 1)
|
||||
{
|
||||
return ShrinkStepSize(hstepCurrent, errMaxNorm);
|
||||
} else if(errMaxNorm >= 0) {
|
||||
}
|
||||
else if(errMaxNorm >= 0)
|
||||
{
|
||||
return GrowStepSize(hstepCurrent, errMaxNorm);
|
||||
}
|
||||
|
||||
G4Exception("G4FSALIntegrationDriver::ConputeNewStepSize", "Field002",
|
||||
FatalException, "error is negative");
|
||||
G4Exception("G4FSALIntegrationDriver::ConputeNewStepSize", "GeomField0003",
|
||||
FatalException, "Error is negative!");
|
||||
|
||||
return max_stepping_increase * hstepCurrent;
|
||||
}
|
||||
@@ -290,12 +302,18 @@ G4double G4FSALIntegrationDriver<T>::ComputeNewStepSize(
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::SetSmallestFraction(G4double newFraction)
|
||||
{
|
||||
if( newFraction > 1.e-16 && newFraction < 1e-8 ) {
|
||||
if( newFraction > 1.e-16 && newFraction < 1e-8 )
|
||||
{
|
||||
fSmallestFraction = newFraction;
|
||||
} else {
|
||||
G4cerr << "Warning: SmallestFraction not changed. " << G4endl
|
||||
<< " Proposed value was " << newFraction << G4endl
|
||||
<< " Value must be between 1.e-8 and 1.e-16" << G4endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Smallest Fraction not changed. " << G4endl
|
||||
<< " Proposed value was " << newFraction << G4endl
|
||||
<< " Value must be between 1.e-8 and 1.e-16";
|
||||
G4Exception("G4FSALIntegrationDriver::SetSmallestFraction()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,14 +333,22 @@ void G4FSALIntegrationDriver<T>::CheckStep(
|
||||
++fNoTotalSteps;
|
||||
|
||||
const G4double endPointDist = (posOut - posIn).mag();
|
||||
if (endPointDist >= hdid * (1. + perMillion)) {
|
||||
if (endPointDist >= hdid * (1. + perMillion))
|
||||
{
|
||||
++fNoBadSteps;
|
||||
#ifdef G4DEBUG_FIELD
|
||||
// Issue a warning only for gross differences -
|
||||
// we understand how small difference occur.
|
||||
if (endPointDist >= hdid * (1. + perThousand)){
|
||||
G4cout << "WARNING: endPointDist >= hdid!" << G4endl;
|
||||
if (endPointDist >= hdid * (1. + perThousand))
|
||||
{
|
||||
G4Exception("G4FSALIntegrationDriver::CheckStep()",
|
||||
"GeomField1002", JustWarning,
|
||||
"endPointDist >= hdid!");
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
++fNoGoodSteps;
|
||||
}
|
||||
}
|
||||
@@ -384,10 +410,27 @@ void G4FSALIntegrationDriver<T>::SetSafety(G4double val)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::RenewStepperAndAdjust(T* stepper)
|
||||
void G4FSALIntegrationDriver<T>::
|
||||
RenewStepperAndAdjust(G4MagIntegratorStepper* stepper)
|
||||
{
|
||||
pIntStepper = stepper;
|
||||
ReSetParameters();
|
||||
T* ourStepper= dynamic_cast<T*>(stepper);
|
||||
if ( ourStepper )
|
||||
{
|
||||
RenewStepperAndAdjustStrict( ourStepper );
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Exception("G4FSALIntegrationDriver::RenewStepperAndAdjust()",
|
||||
"GeomField0002", FatalException,
|
||||
"The type of the stepper provided is incorrect for this templated driver");
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::RenewStepperAndAdjustStrict(T* stepper)
|
||||
{
|
||||
pIntStepper = stepper;
|
||||
ReSetParameters();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -454,7 +497,8 @@ G4EquationOfMotion* G4FSALIntegrationDriver<T>::GetEquationOfMotion()
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4FSALIntegrationDriver<T>::SetEquationOfMotion(G4EquationOfMotion* equation)
|
||||
void G4FSALIntegrationDriver<T>::
|
||||
SetEquationOfMotion(G4EquationOfMotion* equation)
|
||||
{
|
||||
pIntStepper->SetEquationOfMotion(equation);
|
||||
}
|
||||
|
||||
@@ -102,9 +102,11 @@ public:
|
||||
G4double GetPshrnk() const;
|
||||
G4double GetPgrow() const;
|
||||
|
||||
virtual void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper) override;
|
||||
|
||||
// Sets a new stepper pItsStepper for this driver. Then it calls
|
||||
// ReSetParameters to reset its parameters accordingly.
|
||||
void RenewStepperAndAdjust(T *pItsStepper);
|
||||
inline void RenewStepperAndAdjustStrict(T *pItsStepper);
|
||||
|
||||
// i) sets the exponents (pgrow & pshrnk),
|
||||
// using the current Stepper's order,
|
||||
@@ -154,7 +156,7 @@ private:
|
||||
|
||||
// The (default) maximum number of steps is Base
|
||||
// divided by the order of Stepper
|
||||
static constexpr G4int fMaxStepBase = 250;
|
||||
G4int fMaxStepBase;
|
||||
|
||||
// Parameters used to grow and shrink trial stepsize.
|
||||
G4double safety;
|
||||
@@ -165,10 +167,6 @@ private:
|
||||
G4double errorConstraintShrink;
|
||||
G4double errorConstraintGrow;
|
||||
|
||||
// Maximum stepsize increase/decrease factors.
|
||||
static constexpr G4double max_stepping_increase = 5;
|
||||
static constexpr G4double max_stepping_decrease = 0.1;
|
||||
|
||||
T* pIntStepper;
|
||||
|
||||
// Step Statistics
|
||||
|
||||
@@ -48,11 +48,9 @@
|
||||
|
||||
|
||||
template <class T>
|
||||
G4IntegrationDriver<T>::G4IntegrationDriver (
|
||||
G4double hminimum,
|
||||
T* pStepper,
|
||||
G4int numComponents,
|
||||
G4int statisticsVerbose)
|
||||
G4IntegrationDriver<T>::
|
||||
G4IntegrationDriver ( G4double hminimum, T* pStepper,
|
||||
G4int numComponents, G4int statisticsVerbose )
|
||||
: fSmallestFraction(1e-12),
|
||||
fNoTotalSteps(0),
|
||||
fNoBadSteps(0),
|
||||
@@ -60,23 +58,32 @@ G4IntegrationDriver<T>::G4IntegrationDriver (
|
||||
fVerboseLevel(statisticsVerbose),
|
||||
fNoQuickAvanceCalls(0)
|
||||
{
|
||||
if (numComponents != pStepper->GetNumberOfVariables()) {
|
||||
if (numComponents != pStepper->GetNumberOfVariables())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Driver's number of integrated components " << numComponents
|
||||
<< " != Stepper's number of components " << pStepper->GetNumberOfVariables();
|
||||
G4Exception("G4IntegrationDriver","001", FatalException, message);
|
||||
message << "Driver's number of integrated components "
|
||||
<< numComponents
|
||||
<< " != Stepper's number of components "
|
||||
<< pStepper->GetNumberOfVariables();
|
||||
G4Exception("G4IntegrationDriver","GeomField0002",
|
||||
FatalException, message);
|
||||
}
|
||||
RenewStepperAndAdjust(pStepper);
|
||||
RenewStepperAndAdjustStrict(pStepper);
|
||||
fMinimumStep = hminimum;
|
||||
fMaxStepBase = 250;
|
||||
fMaxNoSteps = fMaxStepBase / pIntStepper->IntegratorOrder();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4IntegrationDriver<T>::~G4IntegrationDriver()
|
||||
{
|
||||
#ifdef G4VERBOSE
|
||||
if( fVerboseLevel > 0 )
|
||||
G4cout << "G4Integration Driver Stats: #QuickAdvance " << fNoQuickAvanceCalls
|
||||
<< " #AccurateAdvance " << fNoTotalSteps << G4endl;
|
||||
G4cout << "G4Integration Driver Stats: "
|
||||
<< "#QuickAdvance " << fNoQuickAvanceCalls
|
||||
<< " - #AccurateAdvance " << fNoTotalSteps << G4endl;
|
||||
#endif
|
||||
delete pIntStepper;
|
||||
}
|
||||
|
||||
// Runge-Kutta driver with adaptive stepsize control. Integrate starting
|
||||
@@ -84,14 +91,14 @@ G4IntegrationDriver<T>::~G4IntegrationDriver()
|
||||
// On output ystart is replaced by values at the end of the integration
|
||||
// interval. RightHandSide is the right-hand side of ODE system.
|
||||
// The source is similar to odeint routine from NRC p.721-722 .
|
||||
//
|
||||
template <class T>
|
||||
G4bool G4IntegrationDriver<T>::AccurateAdvance(
|
||||
G4FieldTrack& track,
|
||||
G4double hstep,
|
||||
G4double eps,
|
||||
G4double hinitial)
|
||||
G4bool G4IntegrationDriver<T>::
|
||||
AccurateAdvance( G4FieldTrack& track, G4double hstep,
|
||||
G4double eps, G4double hinitial )
|
||||
{
|
||||
if (hstep < GetMinimumStep()) {
|
||||
if (hstep < GetMinimumStep())
|
||||
{
|
||||
G4double dchord_step = 0, dyerr = 0;
|
||||
G4double dydx[G4FieldTrack::ncompSVEC];
|
||||
GetDerivatives(track, dydx);
|
||||
@@ -109,7 +116,8 @@ G4bool G4IntegrationDriver<T>::AccurateAdvance(
|
||||
G4double endCurveLength = hstep;
|
||||
|
||||
G4double h = hstep;
|
||||
if (hinitial > perMillion * hstep && hinitial < hstep) {
|
||||
if (hinitial > perMillion * hstep && hinitial < hstep)
|
||||
{
|
||||
h = hinitial;
|
||||
}
|
||||
|
||||
@@ -127,7 +135,8 @@ G4bool G4IntegrationDriver<T>::AccurateAdvance(
|
||||
CheckStep(EndPos, StartPos, hdid);
|
||||
|
||||
G4double restCurveLength = endCurveLength - curveLength;
|
||||
if (restCurveLength < GetSmallestFraction() * hstep) {
|
||||
if (restCurveLength < GetSmallestFraction() * hstep)
|
||||
{
|
||||
succeeded = true;
|
||||
break;
|
||||
}
|
||||
@@ -135,7 +144,8 @@ G4bool G4IntegrationDriver<T>::AccurateAdvance(
|
||||
h = std::min(hnext, restCurveLength);
|
||||
}
|
||||
|
||||
if (succeeded) {
|
||||
if (succeeded)
|
||||
{
|
||||
track.LoadFromArray(y, pIntStepper->GetNumberOfVariables());
|
||||
track.SetCurveLength(track.GetCurveLength() + curveLength);
|
||||
}
|
||||
@@ -144,20 +154,23 @@ G4bool G4IntegrationDriver<T>::AccurateAdvance(
|
||||
}
|
||||
|
||||
// Step failed; compute the size of retrial Step.
|
||||
template <class T>
|
||||
G4double G4IntegrationDriver<T>::ShrinkStepSize(G4double h, G4double error) const
|
||||
template <class T> G4double G4IntegrationDriver<T>::
|
||||
ShrinkStepSize(G4double h, G4double error) const
|
||||
{
|
||||
if (error > errorConstraintShrink) {
|
||||
if (error > errorConstraintShrink)
|
||||
{
|
||||
return max_stepping_decrease * h;
|
||||
}
|
||||
return GetSafety() * h * std::pow(error, GetPshrnk());
|
||||
}
|
||||
|
||||
// Compute size of next Step
|
||||
template<class T>
|
||||
G4double G4IntegrationDriver<T>::GrowStepSize(G4double h, G4double error) const
|
||||
//
|
||||
template<class T> G4double G4IntegrationDriver<T>::
|
||||
GrowStepSize(G4double h, G4double error) const
|
||||
{
|
||||
if (error < errorConstraintGrow) {
|
||||
if (error < errorConstraintGrow)
|
||||
{
|
||||
return max_stepping_increase * h;
|
||||
}
|
||||
return GetSafety() * h * std::pow(error, GetPgrow());
|
||||
@@ -175,15 +188,14 @@ G4double G4IntegrationDriver<T>::GrowStepSize(G4double h, G4double error) const
|
||||
// Edition, by William H. Press, Saul A. Teukolsky, William T.
|
||||
// Vetterling, and Brian P. Flannery (Cambridge University Press 1992),
|
||||
// 16.2 Adaptive StepSize Control for Runge-Kutta, p. 719
|
||||
//
|
||||
template <class T>
|
||||
void G4IntegrationDriver<T>::OneGoodStep(
|
||||
G4double y[],
|
||||
const G4double dydx[],
|
||||
G4double& curveLength, // InOut
|
||||
G4double htry,
|
||||
G4double eps_rel_max,
|
||||
G4double& hdid, // Out
|
||||
G4double& hnext) // Out
|
||||
void G4IntegrationDriver<T>::
|
||||
OneGoodStep( G4double y[], const G4double dydx[],
|
||||
G4double& curveLength, // InOut
|
||||
G4double htry, G4double eps_rel_max,
|
||||
G4double& hdid, // Out
|
||||
G4double& hnext) // Out
|
||||
{
|
||||
G4double error = DBL_MAX;
|
||||
|
||||
@@ -195,16 +207,15 @@ void G4IntegrationDriver<T>::OneGoodStep(
|
||||
static G4ThreadLocal G4int tot_no_trials = 0;
|
||||
const G4int max_trials = 100;
|
||||
|
||||
for (G4int iter = 0; iter < max_trials; ++iter) {
|
||||
for (G4int iter = 0; iter < max_trials; ++iter)
|
||||
{
|
||||
++tot_no_trials;
|
||||
|
||||
pIntStepper->Stepper(y, dydx, hstep, ytemp, yerror);
|
||||
error = field_utils::relativeError(y, yerror, hstep, eps_rel_max);
|
||||
|
||||
// Step succeeded.
|
||||
if (error <= 1) {
|
||||
break;
|
||||
}
|
||||
if (error <= 1) break;
|
||||
|
||||
hstep = ShrinkStepSize(hstep, error);
|
||||
}
|
||||
@@ -212,32 +223,33 @@ void G4IntegrationDriver<T>::OneGoodStep(
|
||||
hnext = GrowStepSize(hstep, error);
|
||||
curveLength += (hdid = hstep);
|
||||
|
||||
for(G4int k = 0; k < pIntStepper->GetNumberOfVariables(); ++k) {
|
||||
for(G4int k = 0; k < pIntStepper->GetNumberOfVariables(); ++k)
|
||||
{
|
||||
y[k] = ytemp[k];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4bool G4IntegrationDriver<T>::QuickAdvance(
|
||||
G4FieldTrack& fieldTrack,
|
||||
const G4double dydx[],
|
||||
G4double hstep,
|
||||
G4double& dchord_step,
|
||||
G4double& dyerr)
|
||||
G4bool G4IntegrationDriver<T>::
|
||||
QuickAdvance( G4FieldTrack& fieldTrack, const G4double dydx[],
|
||||
G4double hstep, G4double& dchord_step, G4double& dyerr )
|
||||
{
|
||||
++fNoQuickAvanceCalls;
|
||||
|
||||
if (hstep == 0) {
|
||||
if (hstep == 0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Proposed step is zero; hstep = " << hstep << " !";
|
||||
G4Exception("G4IntegrationDriver ::QuickAdvance()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
"GeomField1001", JustWarning, message);
|
||||
return true;
|
||||
}
|
||||
if (hstep < 0) {
|
||||
if (hstep < 0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid run condition." << G4endl
|
||||
<< "Proposed step is negative; hstep = " << hstep << "." << G4endl
|
||||
<< "Proposed step is negative; hstep = "
|
||||
<< hstep << "." << G4endl
|
||||
<< "Requested step cannot be negative! Aborting event.";
|
||||
G4Exception("G4IntegrationDriver ::QuickAdvance()",
|
||||
"GeomField0003", EventMustBeAborted, message);
|
||||
@@ -262,18 +274,21 @@ G4bool G4IntegrationDriver<T>::QuickAdvance(
|
||||
}
|
||||
|
||||
template <class T>
|
||||
G4double G4IntegrationDriver<T>::ComputeNewStepSize(
|
||||
G4double errMaxNorm, // max error (normalised)
|
||||
G4double hstepCurrent) // current step size
|
||||
G4double G4IntegrationDriver<T>::
|
||||
ComputeNewStepSize( G4double errMaxNorm, // max error (normalised)
|
||||
G4double hstepCurrent ) // current step size
|
||||
{
|
||||
if (errMaxNorm > 1) {
|
||||
if (errMaxNorm > 1)
|
||||
{
|
||||
return ShrinkStepSize(hstepCurrent, errMaxNorm);
|
||||
} else if (errMaxNorm >= 0) {
|
||||
}
|
||||
else if (errMaxNorm >= 0)
|
||||
{
|
||||
return GrowStepSize(hstepCurrent, errMaxNorm);
|
||||
}
|
||||
|
||||
G4Exception("G4IntegrationDriver::ConputeNewStepSize", "Field002",
|
||||
FatalException, "error is negative");
|
||||
G4Exception("G4IntegrationDriver::ConputeNewStepSize", "GeomField0003",
|
||||
FatalException, "Error is negative!");
|
||||
|
||||
return max_stepping_increase * hstepCurrent;
|
||||
}
|
||||
@@ -281,18 +296,24 @@ G4double G4IntegrationDriver<T>::ComputeNewStepSize(
|
||||
template <class T>
|
||||
void G4IntegrationDriver<T>::SetSmallestFraction(G4double newFraction)
|
||||
{
|
||||
if( newFraction > 1.e-16 && newFraction < 1e-8 ) {
|
||||
if( newFraction > 1.e-16 && newFraction < 1e-8 )
|
||||
{
|
||||
fSmallestFraction = newFraction;
|
||||
} else {
|
||||
G4cerr << "Warning: SmallestFraction not changed. " << G4endl
|
||||
<< " Proposed value was " << newFraction << G4endl
|
||||
<< " Value must be between 1.e-8 and 1.e-16" << G4endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Smallest Fraction not changed. " << G4endl
|
||||
<< " Proposed value was " << newFraction << G4endl
|
||||
<< " Value must be between 1.e-8 and 1.e-16";
|
||||
G4Exception("G4IntegrationDriver::SetSmallestFraction()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4IntegrationDriver<T>::GetDerivatives(
|
||||
const G4FieldTrack& track, G4double dydx[]) const
|
||||
void G4IntegrationDriver<T>::
|
||||
GetDerivatives( const G4FieldTrack& track, G4double dydx[] ) const
|
||||
{
|
||||
G4double y[G4FieldTrack::ncompSVEC];
|
||||
track.DumpToArray(y);
|
||||
@@ -300,20 +321,29 @@ void G4IntegrationDriver<T>::GetDerivatives(
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4IntegrationDriver<T>::CheckStep(
|
||||
const G4ThreeVector& posIn, const G4ThreeVector& posOut, G4double hdid)
|
||||
void G4IntegrationDriver<T>::
|
||||
CheckStep( const G4ThreeVector& posIn,
|
||||
const G4ThreeVector& posOut, G4double hdid)
|
||||
{
|
||||
++fNoTotalSteps;
|
||||
|
||||
const G4double endPointDist = (posOut - posIn).mag();
|
||||
if (endPointDist >= hdid * (1. + perMillion)) {
|
||||
if (endPointDist >= hdid * (1. + perMillion))
|
||||
{
|
||||
++fNoBadSteps;
|
||||
#ifdef G4DEBUG_FIELD
|
||||
// Issue a warning only for gross differences -
|
||||
// we understand how small difference occur.
|
||||
if (endPointDist >= hdid * (1. + perThousand)){
|
||||
G4cout << "WARNING: endPointDist >= hdid!" << G4endl;
|
||||
if (endPointDist >= hdid * (1. + perThousand))
|
||||
{
|
||||
G4Exception("G4IntegrationDriver::CheckStep()",
|
||||
"GeomField1002", JustWarning,
|
||||
"endPointDist >= hdid!");
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
++fNoGoodSteps;
|
||||
}
|
||||
}
|
||||
@@ -374,11 +404,27 @@ void G4IntegrationDriver<T>::SetSafety(G4double val)
|
||||
UpdateErrorConstraints();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4IntegrationDriver<T>::RenewStepperAndAdjust(T* stepper)
|
||||
template <class T> void G4IntegrationDriver<T>::
|
||||
RenewStepperAndAdjust(G4MagIntegratorStepper* stepper)
|
||||
{
|
||||
pIntStepper = stepper;
|
||||
ReSetParameters();
|
||||
T* ourStepper= dynamic_cast<T*>(stepper);
|
||||
if ( ourStepper )
|
||||
{
|
||||
RenewStepperAndAdjustStrict( ourStepper );
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Exception("G4IntegrationDriver::RenewStepperAndAdjust()",
|
||||
"GeomField0002", FatalException,
|
||||
"The type of the stepper provided is incorrect for this templated driver");
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void G4IntegrationDriver<T>::RenewStepperAndAdjustStrict(T* stepper)
|
||||
{
|
||||
pIntStepper = stepper;
|
||||
ReSetParameters();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4MagIntegratorDriver.hh 107059 2017-11-01 14:58:16Z gcosmo $
|
||||
// $Id: G4MagIntegratorDriver.hh 109569 2018-05-02 07:08:33Z gcosmo $
|
||||
//
|
||||
//
|
||||
// class G4MagInt_Driver
|
||||
@@ -100,7 +100,7 @@ public: // with description
|
||||
virtual G4EquationOfMotion* GetEquationOfMotion() override;
|
||||
virtual void SetEquationOfMotion(G4EquationOfMotion* equation) override;
|
||||
|
||||
inline void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper);
|
||||
virtual void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper) override;
|
||||
// Sets a new stepper pItsStepper for this driver. Then it calls
|
||||
// ReSetParameters to reset its parameters accordingly.
|
||||
|
||||
@@ -218,7 +218,7 @@ private:
|
||||
const G4int fNoVars; // Full number of variable
|
||||
|
||||
G4int fMaxNoSteps;
|
||||
static const G4int fMaxStepBase;
|
||||
G4int fMaxStepBase;
|
||||
|
||||
G4double safety;
|
||||
G4double pshrnk; // exponent for shrinking
|
||||
@@ -226,10 +226,6 @@ private:
|
||||
G4double errcon;
|
||||
// Parameters used to grow and shrink trial stepsize.
|
||||
|
||||
static const G4double max_stepping_increase;
|
||||
static const G4double max_stepping_decrease;
|
||||
// Maximum stepsize increase/decrease factors.
|
||||
|
||||
G4int fStatisticsVerboseLevel;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4MagIntegratorDriver.icc 107059 2017-11-01 14:58:16Z gcosmo $
|
||||
// $Id: G4MagIntegratorDriver.icc 109569 2018-05-02 07:08:33Z gcosmo $
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -106,13 +106,6 @@ void G4MagInt_Driver::SetErrcon(G4double val)
|
||||
errcon=val;
|
||||
}
|
||||
|
||||
inline
|
||||
void G4MagInt_Driver::RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper)
|
||||
{
|
||||
pIntStepper = pItsStepper;
|
||||
ReSetParameters();
|
||||
}
|
||||
|
||||
inline
|
||||
G4int G4MagInt_Driver::GetMaxNoSteps() const
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4MagneticField.hh 66356 2012-12-18 09:02:32Z gcosmo $
|
||||
// $Id: G4MagneticField.hh 108823 2018-03-09 11:03:44Z gcosmo $
|
||||
//
|
||||
//
|
||||
// class G4MagneticField
|
||||
@@ -41,9 +41,9 @@
|
||||
#define G4MAGNETIC_FIELD_DEF
|
||||
|
||||
#include "G4Types.hh"
|
||||
#include "G4ElectroMagneticField.hh"
|
||||
#include "G4Field.hh"
|
||||
|
||||
class G4MagneticField : public G4ElectroMagneticField
|
||||
class G4MagneticField : public G4Field
|
||||
{
|
||||
public: // with description
|
||||
|
||||
|
||||
@@ -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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: $
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
// Modified midpoint method implementation
|
||||
// Implementation is based on modified_midpoint.hpp from boost odeint
|
||||
|
||||
// Implementation by Dmitry Sorokin - GSoC 2016
|
||||
// Work supported by Google as part of Google Summer of Code 2016.
|
||||
// Supervision / code review: John Apostolakis
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef G4MODIFIED_MIDPOINT_HH
|
||||
#define G4MODIFIED_MIDPOINT_HH
|
||||
|
||||
#include "G4Types.hh"
|
||||
#include "G4EquationOfMotion.hh"
|
||||
#include "G4FieldTrack.hh"
|
||||
|
||||
class G4ModifiedMidpoint
|
||||
{
|
||||
public:
|
||||
|
||||
G4ModifiedMidpoint( G4EquationOfMotion* equation,
|
||||
G4int nvar = 6, G4int steps = 2 );
|
||||
~G4ModifiedMidpoint() = default;
|
||||
|
||||
void DoStep( const G4double yIn[], const G4double dydxIn[],
|
||||
G4double yOut[], G4double hstep) const;
|
||||
|
||||
void DoStep( const G4double yIn[], const G4double dydxIn[],
|
||||
G4double yOut[], G4double hstep, G4double yMid[],
|
||||
G4double derivs[][G4FieldTrack::ncompSVEC]) const;
|
||||
|
||||
inline void SetSteps(G4int steps);
|
||||
inline G4int GetSteps() const;
|
||||
|
||||
inline void SetEquationOfMotion(G4EquationOfMotion* equation);
|
||||
inline G4EquationOfMotion* GetEquationOfMotion();
|
||||
|
||||
inline G4int GetNumberOfVariables() const;
|
||||
|
||||
private:
|
||||
|
||||
void copy(G4double dst[], const G4double src[]) const;
|
||||
|
||||
private:
|
||||
|
||||
G4EquationOfMotion* fEquation;
|
||||
G4int fnvar;
|
||||
G4int fsteps;
|
||||
};
|
||||
|
||||
#include "G4ModifiedMidpoint.icc"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
inline void G4ModifiedMidpoint::SetSteps(G4int steps)
|
||||
{
|
||||
fsteps = steps;
|
||||
}
|
||||
|
||||
inline G4int G4ModifiedMidpoint::GetSteps() const
|
||||
{
|
||||
return fsteps;
|
||||
}
|
||||
|
||||
inline void G4ModifiedMidpoint::SetEquationOfMotion(G4EquationOfMotion* equation)
|
||||
{
|
||||
fEquation = equation;
|
||||
}
|
||||
|
||||
inline G4EquationOfMotion* G4ModifiedMidpoint::GetEquationOfMotion()
|
||||
{
|
||||
return fEquation;
|
||||
}
|
||||
|
||||
inline G4int G4ModifiedMidpoint::GetNumberOfVariables() const
|
||||
{
|
||||
return fnvar;
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4UniformMagField.hh 96751 2016-05-04 09:39:38Z gcosmo $
|
||||
// $Id: G4UniformMagField.hh 110759 2018-06-13 06:23:20Z gcosmo $
|
||||
//
|
||||
//
|
||||
// class G4UniformMagField
|
||||
@@ -57,21 +57,21 @@ class G4UniformMagField : public G4MagneticField
|
||||
G4double vTheta,
|
||||
G4double vPhi ) ;
|
||||
|
||||
virtual ~G4UniformMagField() ;
|
||||
virtual ~G4UniformMagField() override;
|
||||
|
||||
G4UniformMagField(const G4UniformMagField &p);
|
||||
G4UniformMagField& operator = (const G4UniformMagField &p);
|
||||
// Copy constructor and assignment operator.
|
||||
|
||||
virtual void GetFieldValue(const G4double yTrack[4],
|
||||
G4double *MagField) const ;
|
||||
void GetFieldValue(const G4double yTrack[4],
|
||||
G4double *MagField) const override final;
|
||||
|
||||
void SetFieldValue(const G4ThreeVector& newFieldValue);
|
||||
|
||||
G4ThreeVector GetConstantFieldValue() const;
|
||||
// Return the field value
|
||||
|
||||
virtual G4Field* Clone() const;
|
||||
G4Field* Clone() const override final;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
|
||||
class G4VIntegrationDriver {
|
||||
public:
|
||||
G4VIntegrationDriver() = default;
|
||||
G4VIntegrationDriver()
|
||||
: max_stepping_increase(5), max_stepping_decrease(0.1) {};
|
||||
virtual ~G4VIntegrationDriver() = default;
|
||||
|
||||
G4VIntegrationDriver(const G4VIntegrationDriver&) = delete;
|
||||
@@ -80,6 +81,9 @@ public:
|
||||
virtual const G4MagIntegratorStepper* GetStepper() const = 0;
|
||||
virtual G4MagIntegratorStepper* GetStepper() = 0;
|
||||
|
||||
// Method for compatibility -- relevant only for G4MagIntegratorDriver
|
||||
virtual void RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper);
|
||||
|
||||
// Taking the last step's normalised error, calculate
|
||||
// a step size for the next step.
|
||||
// Do not limit the next step's size within a factor of the
|
||||
@@ -89,6 +93,12 @@ public:
|
||||
|
||||
virtual void SetVerboseLevel(G4int level) = 0;
|
||||
virtual G4int GetVerboseLevel() const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
G4double max_stepping_increase;
|
||||
G4double max_stepping_decrease;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# Generated on : 29/9/2010
|
||||
#
|
||||
# $Id: sources.cmake 107113 2017-11-02 14:47:33Z gcosmo $
|
||||
# $Id: sources.cmake 109569 2018-05-02 07:08:33Z gcosmo $
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@@ -31,6 +31,10 @@ GEANT4_DEFINE_MODULE(NAME G4magneticfield
|
||||
HEADERS
|
||||
G4BogackiShampine23.hh
|
||||
G4BogackiShampine45.hh
|
||||
G4BulirschStoer.hh
|
||||
G4BulirschStoer.icc
|
||||
G4BulirschStoerDriver.hh
|
||||
G4BulirschStoerDriver.icc
|
||||
G4CachedMagneticField.hh
|
||||
G4CashKarpRKF45.hh
|
||||
G4ChargeState.hh
|
||||
@@ -91,6 +95,8 @@ GEANT4_DEFINE_MODULE(NAME G4magneticfield
|
||||
G4Mag_EqRhs.hh
|
||||
G4Mag_SpinEqRhs.hh
|
||||
G4Mag_UsualEqRhs.hh
|
||||
G4ModifiedMidpoint.hh
|
||||
G4ModifiedMidpoint.icc
|
||||
G4MonopoleEq.hh
|
||||
G4MagneticField.hh
|
||||
G4NystromRK4.hh
|
||||
@@ -112,6 +118,7 @@ GEANT4_DEFINE_MODULE(NAME G4magneticfield
|
||||
SOURCES
|
||||
G4BogackiShampine23.cc
|
||||
G4BogackiShampine45.cc
|
||||
G4BulirschStoer.cc
|
||||
G4CachedMagneticField.cc
|
||||
G4CashKarpRKF45.cc
|
||||
G4ChargeState.cc
|
||||
@@ -159,6 +166,7 @@ GEANT4_DEFINE_MODULE(NAME G4magneticfield
|
||||
G4Mag_SpinEqRhs.cc
|
||||
G4Mag_UsualEqRhs.cc
|
||||
G4MagneticField.cc
|
||||
G4ModifiedMidpoint.cc
|
||||
G4MonopoleEq.cc
|
||||
G4NystromRK4.cc
|
||||
G4QuadrupoleMagField.cc
|
||||
@@ -174,6 +182,7 @@ GEANT4_DEFINE_MODULE(NAME G4magneticfield
|
||||
G4UniformElectricField.cc
|
||||
G4UniformGravityField.cc
|
||||
G4UniformMagField.cc
|
||||
G4VIntegrationDriver.cc
|
||||
GRANULAR_DEPENDENCIES
|
||||
G4globman
|
||||
GLOBAL_DEPENDENCIES
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: $
|
||||
//
|
||||
// G4BulirschStoer class implementation
|
||||
// Based on bulirsch_stoer.hpp from boost
|
||||
//
|
||||
// Author: Dmitry Sorokin - GSoC 2016
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "G4BulirschStoer.hh"
|
||||
|
||||
#include "G4FieldUtils.hh"
|
||||
|
||||
namespace
|
||||
{
|
||||
const G4double STEPFAC1 = 0.65;
|
||||
const G4double STEPFAC2 = 0.94;
|
||||
const G4double STEPFAC3 = 0.02;
|
||||
const G4double STEPFAC4 = 4.0;
|
||||
const G4double KFAC1 = 0.8;
|
||||
const G4double KFAC2 = 0.9;
|
||||
} // namespace
|
||||
|
||||
G4BulirschStoer::G4BulirschStoer(G4EquationOfMotion* equation,
|
||||
G4int nvar, G4double eps_rel, G4double max_dt)
|
||||
: fnvar(nvar), m_eps_rel(eps_rel), m_midpoint(equation,nvar),
|
||||
m_last_step_rejected(false), m_first(true), m_dt_last(0.0), m_max_dt(max_dt)
|
||||
{
|
||||
/* initialize sequence of stage numbers and work */
|
||||
|
||||
for(G4int i = 0; i < m_k_max + 1; ++i)
|
||||
{
|
||||
m_interval_sequence[i] = 2 * (i + 1);
|
||||
if (i == 0)
|
||||
{
|
||||
m_cost[i] = m_interval_sequence[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cost[i] = m_cost[i-1] + m_interval_sequence[i];
|
||||
}
|
||||
for(G4int k = 0; k < i; ++k)
|
||||
{
|
||||
const G4double r = static_cast<G4double>(m_interval_sequence[i])
|
||||
/ static_cast<G4double>(m_interval_sequence[k]);
|
||||
m_coeff[i][k] = 1.0 / (r * r - 1.0); // coefficients for extrapolation
|
||||
}
|
||||
|
||||
// crude estimate of optimal order
|
||||
m_current_k_opt = 4;
|
||||
|
||||
// no calculation because log10 might not exist for value_type!
|
||||
|
||||
//const G4double logfact = -log10(std::max(eps_rel, 1.0e-12)) * 0.6 + 0.5;
|
||||
//m_current_k_opt = std::max(1.,
|
||||
// std::min(static_cast<G4double>(m_k_max-1), logfact));
|
||||
}
|
||||
}
|
||||
|
||||
G4BulirschStoer::step_result
|
||||
G4BulirschStoer::try_step( const G4double in[], const G4double dxdt[],
|
||||
G4double& t, G4double out[], G4double& dt)
|
||||
{
|
||||
if(m_max_dt < dt)
|
||||
{
|
||||
// given step size is bigger then max_dt set limit and return fail
|
||||
//
|
||||
dt = m_max_dt;
|
||||
return step_result::fail;
|
||||
}
|
||||
|
||||
if (dt != m_dt_last)
|
||||
{
|
||||
reset(); // step size changed from outside -> reset
|
||||
}
|
||||
|
||||
G4bool reject = true;
|
||||
|
||||
G4double new_h = dt;
|
||||
|
||||
/* m_current_k_opt is the estimated current optimal stage number */
|
||||
|
||||
for(G4int k = 0; k <= m_current_k_opt+1; ++k)
|
||||
{
|
||||
// the stage counts are stored in m_interval_sequence
|
||||
//
|
||||
m_midpoint.SetSteps(m_interval_sequence[k]);
|
||||
if(k == 0)
|
||||
{
|
||||
m_midpoint.DoStep(in, dxdt, out, dt);
|
||||
/* the first step, nothing more to do */
|
||||
}
|
||||
else
|
||||
{
|
||||
m_midpoint.DoStep(in, dxdt, m_table[k-1], dt);
|
||||
extrapolate(k, out);
|
||||
// get error estimate
|
||||
for (G4int i = 0; i < fnvar; ++i)
|
||||
{
|
||||
m_err[i] = out[i] - m_table[0][i];
|
||||
}
|
||||
const G4double error =
|
||||
field_utils::relativeError(out, m_err, dt, m_eps_rel);
|
||||
h_opt[k] = calc_h_opt(dt, error, k);
|
||||
work[k] = static_cast<G4double>(m_cost[k]) / h_opt[k];
|
||||
|
||||
if( (k == m_current_k_opt-1) || m_first) // convergence before k_opt ?
|
||||
{
|
||||
if(error < 1.0)
|
||||
{
|
||||
// convergence
|
||||
reject = false;
|
||||
if( (work[k] < KFAC2 * work[k-1]) || (m_current_k_opt <= 2) )
|
||||
{
|
||||
// leave order as is (except we were in first round)
|
||||
m_current_k_opt = std::min(m_k_max - 1 , std::max(2 , k + 1));
|
||||
new_h = h_opt[k];
|
||||
new_h *= static_cast<G4double>(m_cost[k + 1])
|
||||
/ static_cast<G4double>(m_cost[k]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_current_k_opt = std::min(m_k_max - 1, std::max(2, k));
|
||||
new_h = h_opt[k];
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(should_reject(error , k) && !m_first)
|
||||
{
|
||||
reject = true;
|
||||
new_h = h_opt[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(k == m_current_k_opt) // convergence at k_opt ?
|
||||
{
|
||||
if(error < 1.0)
|
||||
{
|
||||
// convergence
|
||||
reject = false;
|
||||
if(work[k-1] < KFAC2 * work[k])
|
||||
{
|
||||
m_current_k_opt = std::max( 2 , m_current_k_opt-1 );
|
||||
new_h = h_opt[m_current_k_opt];
|
||||
}
|
||||
else if( (work[k] < KFAC2 * work[k-1]) && !m_last_step_rejected )
|
||||
{
|
||||
m_current_k_opt = std::min(m_k_max - 1, m_current_k_opt + 1);
|
||||
new_h = h_opt[k];
|
||||
new_h *= static_cast<G4double>(m_cost[m_current_k_opt])
|
||||
/ static_cast<G4double>(m_cost[k]);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_h = h_opt[m_current_k_opt];
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(should_reject(error, k))
|
||||
{
|
||||
reject = true;
|
||||
new_h = h_opt[m_current_k_opt];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(k == m_current_k_opt + 1) // convergence at k_opt+1 ?
|
||||
{
|
||||
if(error < 1.0) // convergence
|
||||
{
|
||||
reject = false;
|
||||
if(work[k-2] < KFAC2 * work[k-1])
|
||||
{
|
||||
m_current_k_opt = std::max(2, m_current_k_opt - 1);
|
||||
}
|
||||
if((work[k] < KFAC2 * work[m_current_k_opt]) && !m_last_step_rejected)
|
||||
{
|
||||
m_current_k_opt = std::min(m_k_max - 1 , k);
|
||||
}
|
||||
new_h = h_opt[m_current_k_opt];
|
||||
}
|
||||
else
|
||||
{
|
||||
reject = true;
|
||||
new_h = h_opt[m_current_k_opt];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!reject)
|
||||
{
|
||||
t += dt;
|
||||
}
|
||||
|
||||
if(!m_last_step_rejected || new_h < dt)
|
||||
{
|
||||
// limit step size
|
||||
new_h = std::min(m_max_dt, new_h);
|
||||
m_dt_last = new_h;
|
||||
dt = new_h;
|
||||
}
|
||||
|
||||
m_last_step_rejected = reject;
|
||||
m_first = false;
|
||||
|
||||
return reject ? step_result::fail : step_result::success;
|
||||
}
|
||||
|
||||
void G4BulirschStoer::reset()
|
||||
{
|
||||
m_first = true;
|
||||
m_last_step_rejected = false;
|
||||
}
|
||||
|
||||
void G4BulirschStoer::extrapolate(size_t k , G4double xest[])
|
||||
{
|
||||
/* polynomial extrapolation, see http://www.nr.com/webnotes/nr3web21.pdf
|
||||
* uses the obtained intermediate results to extrapolate to dt->0 */
|
||||
|
||||
for(G4int j = k - 1 ; j > 0; --j)
|
||||
{
|
||||
for (G4int i = 0; i < fnvar; ++i)
|
||||
{
|
||||
m_table[j-1][i] = m_table[j][i] * (1. + m_coeff[k][j])
|
||||
- m_table[j-1][i] * m_coeff[k][j];
|
||||
}
|
||||
}
|
||||
for (G4int i = 0; i < fnvar; ++i)
|
||||
{
|
||||
xest[i] = m_table[0][i] * (1. + m_coeff[k][0]) - xest[i] * m_coeff[k][0];
|
||||
}
|
||||
}
|
||||
|
||||
G4double
|
||||
G4BulirschStoer::calc_h_opt(G4double h , G4double error , size_t k) const
|
||||
{
|
||||
/* calculates the optimal step size for a given error and stage number */
|
||||
|
||||
G4double expo = 1.0 / (2 * k + 1);
|
||||
G4double facmin = std::pow(STEPFAC3, expo);
|
||||
G4double fac;
|
||||
|
||||
if (error == 0.0)
|
||||
{
|
||||
fac = 1.0 / facmin;
|
||||
}
|
||||
else
|
||||
{
|
||||
fac = STEPFAC2 / std::pow(error / STEPFAC1 , expo);
|
||||
fac = std::max(facmin / STEPFAC4, std::min(1.0 / facmin, fac));
|
||||
}
|
||||
|
||||
return h * fac;
|
||||
}
|
||||
|
||||
//why is not used!!??
|
||||
G4bool G4BulirschStoer::set_k_opt(size_t k, G4double& dt)
|
||||
{
|
||||
/* calculates the optimal stage number */
|
||||
|
||||
if(k == 1)
|
||||
{
|
||||
m_current_k_opt = 2;
|
||||
return true;
|
||||
}
|
||||
if( (work[k-1] < KFAC1 * work[k]) || (k == m_k_max) ) // order decrease
|
||||
{
|
||||
m_current_k_opt = k - 1;
|
||||
dt = h_opt[ m_current_k_opt ];
|
||||
return true;
|
||||
}
|
||||
else if( (work[k] < KFAC2 * work[k-1])
|
||||
|| m_last_step_rejected || (k == m_k_max-1) )
|
||||
{ // same order - also do this if last step got rejected
|
||||
m_current_k_opt = k;
|
||||
dt = h_opt[m_current_k_opt];
|
||||
return true;
|
||||
}
|
||||
else { // order increase - only if last step was not rejected
|
||||
m_current_k_opt = k + 1;
|
||||
dt = h_opt[m_current_k_opt - 1] * m_cost[m_current_k_opt]
|
||||
/ m_cost[m_current_k_opt - 1];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
G4bool G4BulirschStoer::in_convergence_window(G4int k) const
|
||||
{
|
||||
if( (k == m_current_k_opt - 1) && !m_last_step_rejected )
|
||||
{
|
||||
return true; // decrease stepsize only if last step was not rejected
|
||||
}
|
||||
return (k == m_current_k_opt) || (k == m_current_k_opt + 1);
|
||||
}
|
||||
|
||||
|
||||
G4bool G4BulirschStoer::should_reject(G4double error, G4int k) const
|
||||
{
|
||||
if(k == m_current_k_opt - 1)
|
||||
{
|
||||
const G4double d = G4double(m_interval_sequence[m_current_k_opt]
|
||||
* m_interval_sequence[m_current_k_opt+1])
|
||||
/ G4double(m_interval_sequence[0]
|
||||
* m_interval_sequence[0]);
|
||||
// step will fail, criterion 17.3.17 in NR
|
||||
return error > d * d;
|
||||
}
|
||||
else if(k == m_current_k_opt)
|
||||
{
|
||||
const G4double d = G4double(m_interval_sequence[m_current_k_opt])
|
||||
/ G4double(m_interval_sequence[0]);
|
||||
return error > d * d;
|
||||
}
|
||||
else
|
||||
{
|
||||
return error > 1.0;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4ChordFinder.cc 107508 2017-11-20 08:23:14Z gcosmo $
|
||||
// $Id: G4ChordFinder.cc 110753 2018-06-12 15:44:03Z gcosmo $
|
||||
//
|
||||
//
|
||||
// 25.02.97 - John Apostolakis - Design and implementation
|
||||
@@ -76,8 +76,6 @@ G4ChordFinder::G4ChordFinder(G4VIntegrationDriver* pIntegrationDriver)
|
||||
|
||||
SetFractions_Last_Next( fFractionLast, fFractionNextEstimate);
|
||||
// check the values and set the other parameters
|
||||
|
||||
// G4cout << "G4ChordFinder 1st Constructor called - (driver given). " << G4endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +84,6 @@ G4ChordFinder::G4ChordFinder(G4VIntegrationDriver* pIntegrationDriver)
|
||||
G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
G4double stepMinimum,
|
||||
G4MagIntegratorStepper* pItsStepper, // nullptr is default
|
||||
// G4bool useHigherEfficiencyStepper, // false by default
|
||||
G4bool useFSALstepper ) // false by default
|
||||
: fDefaultDeltaChord( 0.25 * mm ), // Constants
|
||||
fDeltaChord( fDefaultDeltaChord ), // Parameters
|
||||
@@ -102,9 +99,6 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
|
||||
using NewFsalStepperType = G4RK547FEq1; // or 2 or 3
|
||||
const char* NewFSALStepperName = "G4RK574FEq1> FSAL 4th/5th order 7-stage 'Equilibrium-type' #1.";
|
||||
// using OldFsalStepperType = G4FSALBogackiShampine45;
|
||||
// const char* OldFSALStepperName = "FSAL BogackiShampine 45 (Embedded 5th/4th Order, 7-stage)";
|
||||
// = G4FSALDormandPrince745; // = "FSAL Dormand Prince 745 stepper";
|
||||
using RegularStepperType =
|
||||
G4DormandPrince745; // Famous DOPRI5 (MatLab) 5th order embedded method. High efficiency.
|
||||
// G4ClassicalRK4; // The old default
|
||||
@@ -117,20 +111,16 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
|
||||
// Configurable
|
||||
G4bool forceFSALstepper= false; // Choice - true to enable !!
|
||||
// G4bool useNewFSALtype= true;
|
||||
// G4bool forceHigherEffiencyStepper = false;
|
||||
G4bool report = false; // Report type of stepper used
|
||||
|
||||
bool recallFSALflag = useFSALstepper;
|
||||
G4bool recallFSALflag = useFSALstepper;
|
||||
useFSALstepper = forceFSALstepper || useFSALstepper;
|
||||
|
||||
if( report ) {
|
||||
#ifdef G4DEBUG_FIELD
|
||||
G4cout << "G4ChordFinder 2nd Constructor called. " << G4endl;
|
||||
G4cout << " Parameters: " << G4endl;
|
||||
G4cout << " useFSAL stepper= " << useFSALstepper
|
||||
<< " (request = " << recallFSALflag
|
||||
<< " force FSAL = " << forceFSALstepper << " )" << G4endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// useHigherStepper = forceHigherEffiencyStepper || useHigherStepper;
|
||||
|
||||
@@ -149,7 +139,6 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
G4bool errorInStepperCreation = false;
|
||||
|
||||
std::ostringstream message; // In case of failure, load with description !
|
||||
message << "G4ChordFinder 2nd Constructor called. " << G4endl;
|
||||
|
||||
if( pItsStepper != nullptr )
|
||||
{
|
||||
@@ -169,9 +158,11 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
|
||||
if( regularStepper == nullptr )
|
||||
{
|
||||
message << " ERROR> 'Regular' RK Stepper instantiation FAILED." << G4endl;
|
||||
message << "Stepper instantiation FAILED." << G4endl;
|
||||
message << "G4ChordFinder: Attempted to instantiate "
|
||||
<< RegularStepperName << " type stepper " << G4endl;
|
||||
G4Exception("G4ChordFinder::G4ChordFinder()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
errorInStepperCreation = true;
|
||||
}
|
||||
else
|
||||
@@ -186,12 +177,13 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
// new G4IntegrationDriver<RegularStepperType>(stepMinimum,
|
||||
// ==== Create the driver which knows the class type
|
||||
|
||||
if( (fIntgrDriver==nullptr) || report ) {
|
||||
message << "G4ChordFinder: Using G4IntegrationDriver with "
|
||||
if( fIntgrDriver==nullptr)
|
||||
{
|
||||
message << "Using G4IntegrationDriver with "
|
||||
<< RegularStepperName << " type stepper " << G4endl;
|
||||
}
|
||||
if(fIntgrDriver==nullptr) {
|
||||
message << " ERROR> 'Regular' RK Driver instantiation FAILED." << G4endl;
|
||||
message << "Driver instantiation FAILED." << G4endl;
|
||||
G4Exception("G4ChordFinder::G4ChordFinder()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,14 +192,14 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
auto fsalStepper= new NewFsalStepperType(pEquation);
|
||||
// ******************
|
||||
fNewFSALStepperOwned = fsalStepper;
|
||||
// delete fsalStepper;
|
||||
// /*NewFsalStepperType* */ fsalStepper =nullptr; // To check the exception
|
||||
|
||||
if( fsalStepper == nullptr )
|
||||
{
|
||||
message << " ERROR> 'FSAL' RK Stepper instantiation FAILED." << G4endl;
|
||||
message << "G4ChordFinder: Attempted to instantiate "
|
||||
message << "Stepper instantiation FAILED." << G4endl;
|
||||
message << "Attempted to instantiate "
|
||||
<< NewFSALStepperName << " type stepper " << G4endl;
|
||||
G4Exception("G4ChordFinder::G4ChordFinder()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
errorInStepperCreation = true;
|
||||
}
|
||||
else
|
||||
@@ -218,12 +210,13 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
fsalStepper->GetNumberOfVariables() );
|
||||
// ==== Create the driver which knows the class type
|
||||
|
||||
if( (fIntgrDriver==nullptr) || report ) {
|
||||
message << "G4ChordFinder: Using G4FSALIntegrationDriver with stepper type: " << G4endl
|
||||
<< NewFSALStepperName << " (new-FSAL type stepper.) " << G4endl;
|
||||
}
|
||||
if(fIntgrDriver==nullptr) {
|
||||
message << " ERROR> FSAL Integration Driver instantiation FAILED." << G4endl;
|
||||
if( fIntgrDriver==nullptr )
|
||||
{
|
||||
message << "Using G4FSALIntegrationDriver with stepper type: "
|
||||
<< NewFSALStepperName << G4endl;
|
||||
message << "Integration Driver instantiation FAILED." << G4endl;
|
||||
G4Exception("G4ChordFinder::G4ChordFinder()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,27 +248,19 @@ G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField,
|
||||
errmsg << " Configuration: (constructor arguments) " << G4endl
|
||||
<< " provided Stepper = " << pItsStepper << G4endl
|
||||
<< " use FSAL stepper = " << BoolName[useFSALstepper]
|
||||
// ( useFSALstepper ? "True" : "False" )
|
||||
<< " (request = " << BoolName[recallFSALflag]
|
||||
<< " force FSAL = " << BoolName[forceFSALstepper] << " )" << G4endl;
|
||||
// << " use new FSAL stp = " << ( useNewFSALstepper ? "True" : "False" ) << G4endl;
|
||||
<< " force FSAL = " << BoolName[forceFSALstepper] << " )" << G4endl;
|
||||
errmsg << message.str();
|
||||
errmsg << "Aborting.";
|
||||
G4Exception("G4ChordFinder::G4ChordFinder() - constructor 2", "GeomField0003",
|
||||
FatalException, errmsg);
|
||||
}
|
||||
else if ( report )
|
||||
{
|
||||
G4cout << message.str();
|
||||
G4Exception("G4ChordFinder::G4ChordFinder() - constructor 2",
|
||||
"GeomField0003", FatalException, errmsg);
|
||||
}
|
||||
|
||||
assert( ( pItsStepper != nullptr )
|
||||
|| ( fRegularStepperOwned != nullptr )
|
||||
|| ( fNewFSALStepperOwned != nullptr )
|
||||
// || ( fOldFSALStepperOwned != nullptr )
|
||||
);
|
||||
assert( fIntgrDriver != nullptr );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -286,7 +271,6 @@ G4ChordFinder::~G4ChordFinder()
|
||||
delete fEquation; // fIntgrDriver->pIntStepper->theEquation_Rhs;
|
||||
delete fRegularStepperOwned;
|
||||
delete fNewFSALStepperOwned;
|
||||
// delete fOldFSALStepperOwned;
|
||||
delete fIntgrDriver;
|
||||
|
||||
if( fStatsVerbose ) { PrintStatistics(); }
|
||||
@@ -321,9 +305,11 @@ G4ChordFinder::SetFractions_Last_Next( G4double fractLast, G4double fractNext )
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cerr << "G4ChordFinder::SetFractions_Last_Next: Invalid "
|
||||
<< " fraction Last = " << fractLast
|
||||
<< " must be 0 < fractionLast <= 1 " << G4endl;
|
||||
std::ostringstream message;
|
||||
message << "Invalid fraction Last = " << fractLast
|
||||
<< "; must be 0 < fractionLast <= 1 ";
|
||||
G4Exception("G4ChordFinder::SetFractions_Last_Next()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
}
|
||||
if( (fractNext > 0.0) && (fractNext <1.0) )
|
||||
{
|
||||
@@ -331,9 +317,11 @@ G4ChordFinder::SetFractions_Last_Next( G4double fractLast, G4double fractNext )
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cerr << "G4ChordFinder:: SetFractions_Last_Next: Invalid "
|
||||
<< " fraction Next = " << fractNext
|
||||
<< " must be 0 < fractionNext < 1 " << G4endl;
|
||||
std::ostringstream message;
|
||||
message << "Invalid fraction Next = " << fractNext
|
||||
<< "; must be 0 < fractionNext < 1 ";
|
||||
G4Exception("G4ChordFinder::SetFractions_Last_Next()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,11 +340,9 @@ G4ChordFinder::AdvanceChordLimited( G4FieldTrack& yCurrent,
|
||||
G4FieldTrack yEnd( yCurrent);
|
||||
G4double startCurveLen= yCurrent.GetCurveLength();
|
||||
G4double nextStep;
|
||||
// *************
|
||||
|
||||
stepPossible= FindNextChord(yCurrent, stepMax, yEnd, dyErr, epsStep,
|
||||
&nextStep, latestSafetyOrigin, latestSafetyRadius
|
||||
);
|
||||
// *************
|
||||
&nextStep, latestSafetyOrigin, latestSafetyRadius);
|
||||
|
||||
G4bool good_advance;
|
||||
|
||||
@@ -398,8 +384,6 @@ G4ChordFinder::FindNextChord( const G4FieldTrack& yStart,
|
||||
{
|
||||
// Returns Length of Step taken
|
||||
|
||||
// G4cout << ">G4ChordFinder::FindNextChord called." << G4endl;
|
||||
|
||||
G4FieldTrack yCurrent= yStart;
|
||||
G4double stepTrial, stepForAccuracy;
|
||||
G4double dydx[G4FieldTrack::ncompSVEC];
|
||||
@@ -497,14 +481,6 @@ G4ChordFinder::FindNextChord( const G4FieldTrack& yStart,
|
||||
*pStepForAccuracy = stepForAccuracy;
|
||||
}
|
||||
|
||||
#ifdef TEST_CHORD_PRINT
|
||||
static int dbg=0;
|
||||
if( dbg )
|
||||
{
|
||||
G4cout << "ChordF/FindNextChord: NoTrials= " << noTrials
|
||||
<< " StepForGoodChord=" << std::setw(10) << stepTrial << G4endl;
|
||||
}
|
||||
#endif
|
||||
yEnd= yCurrent;
|
||||
return stepTrial;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4FieldManager.cc 107059 2017-11-01 14:58:16Z gcosmo $
|
||||
// $Id: G4FieldManager.cc 108823 2018-03-09 11:03:44Z gcosmo $
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@@ -140,10 +140,16 @@ G4FieldManager::~G4FieldManager()
|
||||
void
|
||||
G4FieldManager::CreateChordFinder(G4MagneticField *detectorMagField)
|
||||
{
|
||||
if ( fAllocatedChordFinder )
|
||||
if ( fAllocatedChordFinder )
|
||||
delete fChordFinder;
|
||||
fChordFinder= new G4ChordFinder( detectorMagField );
|
||||
fAllocatedChordFinder= true;
|
||||
fAllocatedChordFinder= false;
|
||||
|
||||
if( detectorMagField ) {
|
||||
fChordFinder= new G4ChordFinder( detectorMagField );
|
||||
fAllocatedChordFinder= true;
|
||||
} else {
|
||||
fChordFinder = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void G4FieldManager::InitialiseFieldChangesEnergy()
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4MagIntegratorDriver.cc 107059 2017-11-01 14:58:16Z gcosmo $
|
||||
// $Id: G4MagIntegratorDriver.cc 110753 2018-06-12 15:44:03Z gcosmo $
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -47,21 +47,6 @@
|
||||
#include "G4MagIntegratorDriver.hh"
|
||||
#include "G4FieldTrack.hh"
|
||||
|
||||
// Stepsize can increase by no more than 5.0
|
||||
// and decrease by no more than 1/10. = 0.1
|
||||
//
|
||||
const G4double G4MagInt_Driver::max_stepping_increase = 5.0;
|
||||
const G4double G4MagInt_Driver::max_stepping_decrease = 0.1;
|
||||
|
||||
// The (default) maximum number of steps is Base
|
||||
// divided by the order of Stepper
|
||||
//
|
||||
const G4int G4MagInt_Driver::fMaxStepBase = 250; // Was 5000
|
||||
|
||||
#ifndef G4NO_FIELD_STATISTICS
|
||||
#define G4FLD_STATS 1
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
@@ -87,6 +72,12 @@ G4MagInt_Driver::G4MagInt_Driver( G4double hminimum,
|
||||
|
||||
RenewStepperAndAdjust( pStepper );
|
||||
fMinimumStep= hminimum;
|
||||
|
||||
// The (default) maximum number of steps is Base
|
||||
// divided by the order of Stepper
|
||||
//
|
||||
fMaxStepBase = 250; // Was 5000
|
||||
|
||||
fMaxNoSteps = fMaxStepBase / pIntStepper->IntegratorOrder();
|
||||
#ifdef G4DEBUG_FIELD
|
||||
fVerboseLevel=2;
|
||||
@@ -117,10 +108,6 @@ G4MagInt_Driver::~G4MagInt_Driver()
|
||||
}
|
||||
}
|
||||
|
||||
// To add much printing for debugging purposes, uncomment the following
|
||||
// and set verbose level to 1 or higher value !
|
||||
// #define G4DEBUG_FIELD 1
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
G4bool
|
||||
@@ -230,7 +217,8 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
|
||||
//--------------------------------------
|
||||
lastStepSucceeded= (hdid == h);
|
||||
#ifdef G4DEBUG_FIELD
|
||||
if (dbg>2) {
|
||||
if (dbg>2)
|
||||
{
|
||||
PrintStatus( ySubStepStart, xSubStepStart, y, x, h, nstp); // Only
|
||||
}
|
||||
#endif
|
||||
@@ -418,7 +406,7 @@ G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current,
|
||||
#ifdef G4DEBUG_FIELD
|
||||
if( dbg && no_warnings )
|
||||
{
|
||||
G4cerr << "G4MagIntegratorDriver exit status: no-steps " << nstp <<G4endl;
|
||||
G4cerr << "G4MagIntegratorDriver exit status: no-steps " << nstp << G4endl;
|
||||
PrintStatus( yEnd, x1, y, x, hstep, nstp);
|
||||
}
|
||||
#endif
|
||||
@@ -574,11 +562,17 @@ G4MagInt_Driver::OneGoodStep( G4double y[], // InOut
|
||||
// Accuracy for momentum
|
||||
G4double magvel_sq= sqr(y[3]) + sqr(y[4]) + sqr(y[5]) ;
|
||||
G4double sumerr_sq = sqr(yerr[3]) + sqr(yerr[4]) + sqr(yerr[5]) ;
|
||||
if( magvel_sq > 0.0 ) {
|
||||
if( magvel_sq > 0.0 )
|
||||
{
|
||||
errvel_sq = sumerr_sq / magvel_sq;
|
||||
}else{
|
||||
G4cerr << "** G4MagIntegrationDriver: found case of zero momentum."
|
||||
<< " iteration= " << iter << " h= " << h << G4endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Found case of zero momentum." << G4endl
|
||||
<< "- iteration= " << iter << "; h= " << h;
|
||||
G4Exception("G4MagInt_Driver::OneGoodStep()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
errvel_sq = sumerr_sq;
|
||||
}
|
||||
errvel_sq *= inv_eps_vel_sq;
|
||||
@@ -604,23 +598,18 @@ G4MagInt_Driver::OneGoodStep( G4double y[], // InOut
|
||||
xnew = x + h;
|
||||
if(xnew == x)
|
||||
{
|
||||
G4cerr << "G4MagIntegratorDriver::OneGoodStep:" << G4endl
|
||||
<< " Stepsize underflow in Stepper " << G4endl ;
|
||||
G4cerr << " Step's start x=" << x << " and end x= " << xnew
|
||||
<< " are equal !! " << G4endl
|
||||
<<" Due to step-size= " << h
|
||||
<< " . Note that input step was " << htry << G4endl;
|
||||
std::ostringstream message;
|
||||
message << "Stepsize underflow in Stepper !" << G4endl
|
||||
<< "- Step's start x=" << x << " and end x= " << xnew
|
||||
<< " are equal !! " << G4endl
|
||||
<< " Due to step-size= " << h
|
||||
<< ". Note that input step was " << htry;
|
||||
G4Exception("G4MagInt_Driver::OneGoodStep()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef G4FLD_STATS
|
||||
// Sum of squares of position error // and momentum dir (underestimated)
|
||||
fSumH_lg += h;
|
||||
fDyerrPos_lgTot += errpos_sq;
|
||||
fDyerrVel_lgTot += errvel_sq * h * h;
|
||||
#endif
|
||||
|
||||
// Compute size of next Step
|
||||
if (errmax_sq > errcon*errcon)
|
||||
{
|
||||
@@ -635,7 +624,7 @@ G4MagInt_Driver::OneGoodStep( G4double y[], // InOut
|
||||
for(G4int k=0;k<fNoIntegrationVariables;k++) { y[k] = ytemp[k]; }
|
||||
|
||||
return;
|
||||
} // end of OneGoodStep .............................
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
@@ -682,11 +671,9 @@ G4bool G4MagInt_Driver::QuickAdvance(
|
||||
|
||||
// Do an Integration Step
|
||||
pIntStepper-> Stepper(yarrin, dydx, hstep, yarrout, yerr_vec) ;
|
||||
// *******
|
||||
|
||||
// Estimate curve-chord distance
|
||||
dchord_step= pIntStepper-> DistChord();
|
||||
// *********
|
||||
|
||||
// Put back the values. yarrout ==> y_posvel
|
||||
y_posvel.LoadFromArray( yarrout, fNoIntegrationVariables );
|
||||
@@ -760,10 +747,9 @@ G4bool G4MagInt_Driver::QuickAdvance(
|
||||
// This method computes new step sizes - but does not limit changes to
|
||||
// within certain factors
|
||||
//
|
||||
G4double
|
||||
G4MagInt_Driver::ComputeNewStepSize(
|
||||
G4double errMaxNorm, // max error (normalised)
|
||||
G4double hstepCurrent) // current step size
|
||||
G4double G4MagInt_Driver::
|
||||
ComputeNewStepSize(G4double errMaxNorm, // max error (normalised)
|
||||
G4double hstepCurrent) // current step size
|
||||
{
|
||||
G4double hnew;
|
||||
|
||||
@@ -772,10 +758,14 @@ G4MagInt_Driver::ComputeNewStepSize(
|
||||
{
|
||||
// Step failed; compute the size of retrial Step.
|
||||
hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPshrnk()) ;
|
||||
} else if(errMaxNorm > 0.0 ) {
|
||||
}
|
||||
else if(errMaxNorm > 0.0 )
|
||||
{
|
||||
// Compute size of next Step for a successful step
|
||||
hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPgrow()) ;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// if error estimate is zero (possible) or negative (dubious)
|
||||
hnew = max_stepping_increase * hstepCurrent;
|
||||
}
|
||||
@@ -855,7 +845,7 @@ void G4MagInt_Driver::PrintStatus(
|
||||
G4int subStepNo)
|
||||
{
|
||||
G4int verboseLevel= fVerboseLevel;
|
||||
static G4ThreadLocal G4int noPrecision= 5;
|
||||
const G4int noPrecision = 5;
|
||||
G4int oldPrec= G4cout.precision(noPrecision);
|
||||
// G4cout.setf(ios_base::fixed,ios_base::floatfield);
|
||||
|
||||
@@ -898,7 +888,6 @@ void G4MagInt_Driver::PrintStatus(
|
||||
{
|
||||
PrintStat_Aux( StartFT, requestStep, 0.,
|
||||
0, 0.0, 1.0);
|
||||
//*************
|
||||
}
|
||||
|
||||
if( verboseLevel <= 3 )
|
||||
@@ -906,21 +895,8 @@ void G4MagInt_Driver::PrintStatus(
|
||||
G4cout.precision(noPrecision);
|
||||
PrintStat_Aux( CurrentFT, requestStep, step_len,
|
||||
subStepNo, subStepSize, DotStartCurrentVeloc );
|
||||
//*************
|
||||
}
|
||||
|
||||
else // if( verboseLevel > 3 )
|
||||
{
|
||||
// Multi-line output
|
||||
|
||||
// G4cout << "Current Position is " << CurrentPosition << G4endl
|
||||
// << " and UnitVelocity is " << CurrentUnitVelocity << G4endl;
|
||||
// G4cout << "Step taken was " << step_len
|
||||
// << " out of PhysicalStep= " << requestStep << G4endl;
|
||||
// G4cout << "Final safety is: " << safety << G4endl;
|
||||
// G4cout << "Chord length = " << (CurrentPosition-StartPosition).mag()
|
||||
// << G4endl << G4endl;
|
||||
}
|
||||
G4cout.precision(oldPrec);
|
||||
}
|
||||
|
||||
@@ -1004,37 +980,6 @@ void G4MagInt_Driver::PrintStatisticsReport()
|
||||
<< " Small= " << fNoSmallSteps
|
||||
<< " Non-initial small= " << (fNoSmallSteps-fNoInitialSmallSteps)
|
||||
<< G4endl;
|
||||
|
||||
#ifdef G4FLD_STATS
|
||||
G4cout << "MID dyerr: "
|
||||
<< " maximum= " << fDyerr_max
|
||||
<< " Sum small= " << fDyerrPos_smTot
|
||||
<< " std::sqrt(Sum large^2): pos= " << std::sqrt(fDyerrPos_lgTot)
|
||||
<< " vel= " << std::sqrt( fDyerrVel_lgTot )
|
||||
<< " Total h-distance: small= " << fSumH_sm
|
||||
<< " large= " << fSumH_lg
|
||||
<< G4endl;
|
||||
|
||||
#if 0
|
||||
G4int noPrecSmall=4;
|
||||
// Single line precis of statistics ... optional
|
||||
G4cout.precision(noPrecSmall);
|
||||
G4cout << "MIDnums: " << fMinimumStep
|
||||
<< " " << fNoTotalSteps
|
||||
<< " " << fNoSmallSteps
|
||||
<< " " << fNoSmallSteps-fNoInitialSmallSteps
|
||||
<< " " << fNoBadSteps
|
||||
<< " " << fDyerr_max
|
||||
<< " " << fDyerr_mx2
|
||||
<< " " << fDyerrPos_smTot
|
||||
<< " " << fSumH_sm
|
||||
<< " " << fDyerrPos_lgTot
|
||||
<< " " << fDyerrVel_lgTot
|
||||
<< " " << fSumH_lg
|
||||
<< G4endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
G4cout.precision(oldPrec);
|
||||
}
|
||||
|
||||
@@ -1048,13 +993,17 @@ void G4MagInt_Driver::SetSmallestFraction(G4double newFraction)
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cerr << "Warning: SmallestFraction not changed. " << G4endl
|
||||
<< " Proposed value was " << newFraction << G4endl
|
||||
<< " Value must be between 1.e-8 and 1.e-16" << G4endl;
|
||||
std::ostringstream message;
|
||||
message << "Smallest Fraction not changed. " << G4endl
|
||||
<< " Proposed value was " << newFraction << G4endl
|
||||
<< " Value must be between 1.e-8 and 1.e-16";
|
||||
G4Exception("G4MagInt_Driver::SetSmallestFraction()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
}
|
||||
}
|
||||
|
||||
void G4MagInt_Driver::GetDerivatives(const G4FieldTrack& y_curr, G4double* dydx) const
|
||||
void G4MagInt_Driver::
|
||||
GetDerivatives(const G4FieldTrack& y_curr, G4double* dydx) const
|
||||
{
|
||||
G4double ytemp[G4FieldTrack::ncompSVEC];
|
||||
y_curr.DumpToArray(ytemp);
|
||||
@@ -1081,3 +1030,9 @@ G4MagIntegratorStepper* G4MagInt_Driver::GetStepper()
|
||||
return pIntStepper;
|
||||
}
|
||||
|
||||
void G4MagInt_Driver::
|
||||
RenewStepperAndAdjust(G4MagIntegratorStepper *pItsStepper)
|
||||
{
|
||||
pIntStepper = pItsStepper;
|
||||
ReSetParameters();
|
||||
}
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4MagneticField.cc 96678 2016-04-29 16:21:01Z gcosmo $
|
||||
// $Id: G4MagneticField.cc 108823 2018-03-09 11:03:44Z gcosmo $
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "G4MagneticField.hh"
|
||||
|
||||
G4MagneticField::G4MagneticField()
|
||||
: G4ElectroMagneticField()
|
||||
: G4Field( false ) // No gravitational field (default)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -39,14 +39,14 @@ G4MagneticField::~G4MagneticField()
|
||||
{
|
||||
}
|
||||
|
||||
G4MagneticField::G4MagneticField(const G4MagneticField &MagField)
|
||||
: G4ElectroMagneticField( MagField )
|
||||
G4MagneticField::G4MagneticField(const G4MagneticField & )
|
||||
: G4Field( false )
|
||||
{
|
||||
}
|
||||
|
||||
G4MagneticField& G4MagneticField::operator = (const G4MagneticField &p)
|
||||
{
|
||||
if (&p == this) return *this;
|
||||
G4ElectroMagneticField::operator=(p);
|
||||
G4Field::operator=(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: $
|
||||
//
|
||||
// G4ModifiedMidpoint implementation
|
||||
// Based on modified_midpoint.hpp from boost
|
||||
//
|
||||
// Author: Dmitry Sorokin - GSoC 2016
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "G4ModifiedMidpoint.hh"
|
||||
|
||||
G4ModifiedMidpoint::G4ModifiedMidpoint( G4EquationOfMotion* equation,
|
||||
G4int nvar, G4int steps )
|
||||
: fEquation(equation), fnvar(nvar), fsteps(steps)
|
||||
{
|
||||
if (nvar <= 0)
|
||||
{
|
||||
G4Exception("G4ModifiedMidpoint::G4ModifiedMidpoint()",
|
||||
"GeomField0002", FatalException,
|
||||
"Invalid number of variables; must be greater than zero!");
|
||||
}
|
||||
}
|
||||
|
||||
void G4ModifiedMidpoint::DoStep( const G4double yIn[], const G4double dydyIn[],
|
||||
G4double yOut[], G4double hstep) const
|
||||
{
|
||||
G4double y0[G4FieldTrack::ncompSVEC];
|
||||
G4double y1[G4FieldTrack::ncompSVEC];
|
||||
G4double dydx[G4FieldTrack::ncompSVEC];
|
||||
G4double yTemp[G4FieldTrack::ncompSVEC];
|
||||
|
||||
const G4double h = hstep / fsteps;
|
||||
const G4double h2 = 2 * h;
|
||||
|
||||
// y1 = yIn + h * dydx
|
||||
for (G4int i = 0; i < fnvar; ++i)
|
||||
{
|
||||
y1[i] = yIn[i] + h * dydyIn[i];
|
||||
}
|
||||
|
||||
fEquation->RightHandSide(y1, dydx);
|
||||
|
||||
copy(y0, yIn);
|
||||
|
||||
// general step
|
||||
// yTemp = y1; y1 = y0 + h2 * dydx; y0 = yTemp
|
||||
for (G4int i = 1; i < fsteps; ++i)
|
||||
{
|
||||
copy(yTemp, y1);
|
||||
for (G4int j = 0; j < fnvar; ++j)
|
||||
{
|
||||
y1[j] = y0[j] + h2 * dydx[j];
|
||||
}
|
||||
copy(y0, yTemp);
|
||||
|
||||
fEquation->RightHandSide(y1, dydx);
|
||||
}
|
||||
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
|
||||
void G4ModifiedMidpoint::DoStep( const G4double yIn[], const G4double dydxIn[],
|
||||
G4double yOut[], G4double hstep, G4double yMid[],
|
||||
G4double derivs[][G4FieldTrack::ncompSVEC]) const
|
||||
{
|
||||
G4double y0[G4FieldTrack::ncompSVEC];
|
||||
G4double y1[G4FieldTrack::ncompSVEC];
|
||||
G4double yTemp[G4FieldTrack::ncompSVEC];
|
||||
|
||||
const G4double h = hstep / fsteps;
|
||||
const G4double h2 = 2 * h;
|
||||
|
||||
// y0 = yIn
|
||||
copy(y0, yIn);
|
||||
|
||||
// y1 = y0 + h * dydx
|
||||
for (G4int i = 0; i < fnvar; ++i)
|
||||
{
|
||||
y1[i] = y0[i] + h * dydxIn[i];
|
||||
}
|
||||
|
||||
// result of first step already gives approximation
|
||||
// at the center of the interval
|
||||
if(fsteps == 2)
|
||||
{
|
||||
copy(yMid, y1);
|
||||
}
|
||||
|
||||
fEquation->RightHandSide(y1, derivs[0]);
|
||||
|
||||
// general step
|
||||
// yTemp = y1; y1 = y0 + h2 * dydx; y0 = yTemp
|
||||
for (G4int i = 1; i < fsteps; ++i)
|
||||
{
|
||||
copy(yTemp, y1);
|
||||
for (G4int j = 0; j < fnvar; ++j)
|
||||
{
|
||||
y1[j] = y0[j] + h2 * derivs[i-1][j];
|
||||
}
|
||||
copy(y0, yTemp);
|
||||
|
||||
// save approximation at the center of the interval
|
||||
if(i == fsteps / 2 - 1 )
|
||||
{
|
||||
copy(yMid, y1);
|
||||
}
|
||||
|
||||
fEquation->RightHandSide(y1, derivs[i]);
|
||||
}
|
||||
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
|
||||
void G4ModifiedMidpoint::copy(G4double dst[], const G4double src[]) const
|
||||
{
|
||||
std::memcpy(dst, src, sizeof(G4double) * fnvar);
|
||||
}
|
||||
@@ -24,11 +24,11 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: G4NystromRK4.cc 107821 2017-12-05 14:14:47Z gunter $
|
||||
// $Id: G4NystromRK4.cc 110753 2018-06-12 15:44:03Z gcosmo $
|
||||
//
|
||||
// History:
|
||||
// - Created: I.Gavrilenko 15.05.2009 (as G4AtlasRK4)
|
||||
// - Adaptations: J. Apostolakis May-Nov 2009
|
||||
// - Adaptations: J.Apostolakis May-Nov 2009
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
#include <iostream>
|
||||
@@ -64,13 +64,14 @@ G4NystromRK4::~G4NystromRK4()
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Integration in one step
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
G4NystromRK4::Stepper
|
||||
(const G4double P[],const G4double dPdS[],G4double Step,G4double Po[],G4double Err[])
|
||||
G4NystromRK4::Stepper (const G4double P[],
|
||||
const G4double dPdS[],
|
||||
G4double Step, G4double Po[], G4double Err[])
|
||||
{
|
||||
const G4double perMillion = 1.0e-6;
|
||||
G4double R[4] = { P[0], P[1] , P[2], P[7] }; // x, y, z, t
|
||||
@@ -92,7 +93,8 @@ G4NystromRK4::Stepper
|
||||
// - Quick check momentum magnitude (squared) against previous value
|
||||
G4double newmom2 = (P[3]*P[3]+P[4]*P[4]+P[5]*P[5]);
|
||||
G4double oldmom2 = m_mom * m_mom;
|
||||
if( std::fabs(newmom2 - oldmom2) > perMillion * oldmom2 ) {
|
||||
if( std::fabs(newmom2 - oldmom2) > perMillion * oldmom2 )
|
||||
{
|
||||
m_mom = std::sqrt(newmom2) ;
|
||||
m_imom = 1./m_mom;
|
||||
m_cof = m_fEq->FCof()*m_imom;
|
||||
@@ -178,9 +180,9 @@ G4NystromRK4::Stepper
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Estimate the maximum distance from the curve to the chord
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4double
|
||||
G4NystromRK4::DistChord() const
|
||||
@@ -193,7 +195,8 @@ G4NystromRK4::DistChord() const
|
||||
G4double dz = m_mPoint[2]-m_iPoint[2];
|
||||
G4double d2 = (ax*ax+ay*ay+az*az) ;
|
||||
|
||||
if(d2!=0.) {
|
||||
if(d2!=0.)
|
||||
{
|
||||
G4double ds = (ax*dx+ay*dy+az*dz)/d2;
|
||||
dx -= (ds*ax) ;
|
||||
dy -= (ds*ay) ;
|
||||
@@ -202,9 +205,9 @@ G4NystromRK4::DistChord() const
|
||||
return std::sqrt(dx*dx+dy*dy+dz*dz);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Derivatives calculation - caching the momentum value
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
G4NystromRK4::ComputeRightHandSide(const G4double P[],G4double dPdS[])
|
||||
@@ -236,12 +239,15 @@ G4NystromRK4::CheckFieldPosition( const G4double Position[3],
|
||||
G4double dy = Position[1] - lastPosition[1];
|
||||
G4double dz = Position[2] - lastPosition[2];
|
||||
G4double distMag2 = dx*dx+dy*dy+dz*dz;
|
||||
if( distMag2 > m_magdistance2) {
|
||||
if( distMag2 > m_magdistance2)
|
||||
{
|
||||
const G4double allowedDist = std::sqrt( m_magdistance2 );
|
||||
G4double dist= std::sqrt( distMag2 );
|
||||
G4cerr << " NystromRK4::Stepper> ERROR> Moved from correct field position by "
|
||||
<< dist << "( larger than allowed = " << allowedDist << " ) "
|
||||
<< G4endl;
|
||||
std::ostringstream message;
|
||||
message << "Moved from correct field position by " << dist
|
||||
<< "( larger than allowed = " << allowedDist << " ) ";
|
||||
G4Exception("G4NystromRK4::CheckFieldPosition()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
ok= false;
|
||||
}
|
||||
return ok;
|
||||
@@ -256,16 +262,22 @@ G4bool G4NystromRK4::CheckCachedMomemtum( const G4double PosMom[6],
|
||||
{
|
||||
constexpr G4double perThousand = 1.0e-3;
|
||||
G4bool ok= true;
|
||||
G4double new_mom2= (PosMom[3]*PosMom[3]+PosMom[4]*PosMom[4]+PosMom[5]*PosMom[5]);
|
||||
G4double new_mom2= (PosMom[3]*PosMom[3]
|
||||
+PosMom[4]*PosMom[4]
|
||||
+PosMom[5]*PosMom[5]);
|
||||
G4double new_mom= std::sqrt(new_mom2);
|
||||
if( std::fabs(new_mom - savedMom ) > perThousand * savedMom ) {
|
||||
G4cerr << " Nystrom::Stepper WARNING: momentum magnitude is invalid / has changed "
|
||||
<< G4endl
|
||||
<< " new value (p-mag) = " << new_mom << G4endl
|
||||
<< " cached value (p-mag) = " << savedMom << G4endl;
|
||||
if( savedMom > 0.0 ) {
|
||||
G4cerr << " ratio (new/old) = " << new_mom / savedMom << G4endl;
|
||||
if( std::fabs(new_mom - savedMom ) > perThousand * savedMom )
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Momentum magnitude is invalid / has changed !" << G4endl
|
||||
<< " new value (p-mag) = " << new_mom << G4endl
|
||||
<< " cached value (p-mag) = " << savedMom;
|
||||
if( savedMom > 0.0 )
|
||||
{
|
||||
message << "; ratio (new/old) = " << new_mom / savedMom;
|
||||
}
|
||||
G4Exception("G4NystromRK4::CheckCachedMomemtum()",
|
||||
"GeomField1001", JustWarning, message);
|
||||
ok= false;
|
||||
}
|
||||
return ok;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4VIntegrationDriver.cc 109569 2018-05-02 07:08:33Z gcosmo $
|
||||
//
|
||||
// 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
|
||||
|
||||
#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");
|
||||
}
|
||||
Reference in New Issue
Block a user