00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "G4ChordFinderSaf.hh"
00029 #include <iomanip>
00030
00031
00032
00033 G4ChordFinderSaf::G4ChordFinderSaf(G4MagInt_Driver* pIntegrationDriver)
00034 : G4ChordFinder(pIntegrationDriver)
00035 {
00036
00037
00038
00039
00040 }
00041
00042
00043
00044 G4ChordFinderSaf::G4ChordFinderSaf( G4MagneticField* theMagField,
00045 G4double stepMinimum,
00046 G4MagIntegratorStepper* pItsStepper )
00047 : G4ChordFinder( theMagField, stepMinimum, pItsStepper )
00048 {
00049
00050
00051 }
00052
00053
00054
00055
00056
00057 G4ChordFinderSaf::~G4ChordFinderSaf()
00058 {
00059 if( SetVerbose(0) ) { PrintStatistics(); }
00060
00061 }
00062
00063 void
00064 G4ChordFinderSaf::PrintStatistics()
00065 {
00066
00067 G4cout << "G4ChordFinderSaf statistics report: " << G4endl;
00068 G4ChordFinder::PrintStatistics();
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 }
00087
00088
00089
00090
00091 G4double
00092 CalculatePointSafety(G4ThreeVector safetyOrigin,
00093 G4double safetyRadius,
00094 G4ThreeVector point)
00095 {
00096 G4double pointSafety= 0.0;
00097
00098 G4ThreeVector OriginShift = point - safetyOrigin ;
00099 G4double MagSqShift = OriginShift.mag2() ;
00100 if( MagSqShift < sqr(safetyRadius) ){
00101 pointSafety = safetyRadius - std::sqrt(MagSqShift) ;
00102 }
00103
00104 return pointSafety;
00105 }
00106
00107
00108 G4bool
00109 CalculatePointInside(G4ThreeVector safetyOrigin,
00110 G4double safetyRadius,
00111 G4ThreeVector point)
00112 {
00113 G4ThreeVector OriginShift = point - safetyOrigin ;
00114 return ( OriginShift.mag2() < safetyRadius*safetyRadius );
00115 }
00116
00117 G4double
00118 G4ChordFinderSaf::FindNextChord( const G4FieldTrack& yStart,
00119 G4double stepMax,
00120 G4FieldTrack& yEnd,
00121 G4double& dyErrPos,
00122 G4double epsStep,
00123 G4double* pStepForAccuracy,
00124 const G4ThreeVector latestSafetyOrigin,
00125 G4double latestSafetyRadius
00126 )
00127
00128 {
00129
00130 G4FieldTrack yCurrent= yStart;
00131 G4double stepTrial, stepForAccuracy;
00132 G4double dydx[G4FieldTrack::ncompSVEC];
00133
00134
00135
00136
00137
00138 G4bool validEndPoint= false;
00139 G4double dChordStep, lastStepLength;
00140
00141 GetIntegrationDriver()-> GetDerivatives( yCurrent, dydx ) ;
00142
00143 G4int noTrials=0;
00144 const G4double safetyFactor= GetFirstFraction();
00145
00146
00147 G4double startSafety=
00148 CalculatePointSafety( latestSafetyOrigin,
00149 latestSafetyRadius,
00150 yCurrent.GetPosition() );
00151
00152 G4double
00153 likelyGood = std::max( startSafety ,
00154 safetyFactor * GetLastStepEstimateUnc() );
00155
00156 stepTrial = std::min( stepMax, likelyGood );
00157
00158 G4MagInt_Driver *pIntgrDriver= G4ChordFinder::GetIntegrationDriver();
00159 G4double newStepEst_Uncons= 0.0;
00160 do
00161 {
00162 G4double stepForChord;
00163 yCurrent = yStart;
00164
00165
00166 pIntgrDriver->QuickAdvance( yCurrent, dydx, stepTrial,
00167 dChordStep, dyErrPos);
00168
00169
00170 G4ThreeVector EndPointCand= yCurrent.GetPosition();
00171 G4bool endPointInSafetySphere=
00172 CalculatePointInside(latestSafetyOrigin, latestSafetyRadius, EndPointCand);
00173
00174
00175 validEndPoint = AcceptableMissDist(dChordStep)
00176 || endPointInSafetySphere;
00177
00178
00179 lastStepLength = stepTrial;
00180
00181
00182 stepForChord = NewStep(stepTrial, dChordStep, newStepEst_Uncons );
00183
00184 if( ! validEndPoint ) {
00185 if( stepTrial<=0.0 )
00186 stepTrial = stepForChord;
00187 else if (stepForChord <= stepTrial)
00188
00189 stepTrial = std::min( stepForChord,
00190 GetFractionLast() * stepTrial);
00191 else
00192 stepTrial *= 0.1;
00193
00194
00195 }
00196
00197
00198
00199
00200 noTrials++;
00201 }
00202 while( ! validEndPoint );
00203
00204 AccumulateStatistics( noTrials );
00205
00206
00207 if( newStepEst_Uncons > 0.0 ){
00208 SetLastStepEstimateUnc( newStepEst_Uncons );
00209 }
00210
00211
00212
00213 if( pStepForAccuracy ){
00214
00215 G4double dyErr_relative = dyErrPos/(epsStep*lastStepLength);
00216 if( dyErr_relative > 1.0 ) {
00217 stepForAccuracy =
00218 pIntgrDriver->ComputeNewStepSize( dyErr_relative,
00219 lastStepLength );
00220 }else{
00221 stepForAccuracy = 0.0;
00222 }
00223 *pStepForAccuracy = stepForAccuracy;
00224 }
00225
00226 #ifdef TEST_CHORD_PRINT
00227 static int dbg=0;
00228 if( dbg )
00229 G4cout << "ChordF/FindNextChord: NoTrials= " << noTrials
00230 << " StepForGoodChord=" << std::setw(10) << stepTrial << G4endl;
00231 #endif
00232
00233 yEnd= yCurrent;
00234 return stepTrial;
00235 }