Import Geant4 10.5.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2018-06-29 10:58:11 +02:00
parent fe81a77428
commit 6aa23be517
1581 changed files with 124288 additions and 83758 deletions
+74 -13
View File
@@ -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 (Nevilles 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
+10 -1
View File
@@ -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");
}