File indexing completed on 2025-01-18 09:58:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include "G4FieldUtils.hh"
0032
0033 template <class T>
0034 G4FSALIntegrationDriver<T>::
0035 G4FSALIntegrationDriver ( G4double hminimum, T* pStepper,
0036 G4int numComponents, G4int statisticsVerbose )
0037 : Base(pStepper),
0038 fMinimumStep(hminimum),
0039 fVerboseLevel(statisticsVerbose)
0040 {
0041 if (numComponents != Base::GetStepper()->GetNumberOfVariables())
0042 {
0043 std::ostringstream message;
0044 message << "Driver's number of integrated components "
0045 << numComponents
0046 << " != Stepper's number of components "
0047 << pStepper->GetNumberOfVariables();
0048 G4Exception("G4FSALIntegrationDriver","GeomField0002",
0049 FatalException, message);
0050 }
0051 }
0052
0053 template <class T>
0054 G4FSALIntegrationDriver<T>::~G4FSALIntegrationDriver()
0055 {
0056 #ifdef G4VERBOSE
0057 if( fVerboseLevel > 0 )
0058 {
0059 G4cout << "G4FSALIntegration Driver Stats: "
0060 << "#QuickAdvance " << fNoQuickAvanceCalls
0061 << " - #AccurateAdvance " << fNoAccurateAdvanceCalls << G4endl
0062 << "#good steps " << fNoAccurateAdvanceGoodSteps << " "
0063 << "#bad steps " << fNoAccurateAdvanceBadSteps << G4endl;
0064 }
0065 #endif
0066 }
0067
0068
0069
0070
0071
0072
0073
0074 template <class T>
0075 G4bool G4FSALIntegrationDriver<T>::
0076 AccurateAdvance( G4FieldTrack& track, G4double hstep,
0077 G4double eps, G4double hinitial )
0078 {
0079 ++fNoAccurateAdvanceCalls;
0080
0081 if (hstep < GetMinimumStep())
0082 {
0083 G4double dchord_step = 0.0, dyerr = 0.0;
0084 G4double dydx[G4FieldTrack::ncompSVEC];
0085 Base::GetDerivatives(track, dydx);
0086 return QuickAdvance(track, dydx, hstep, dchord_step, dyerr);
0087 }
0088
0089 G4bool succeeded = false;
0090
0091 G4double hnext, hdid;
0092
0093 G4double y[G4FieldTrack::ncompSVEC], dydx[G4FieldTrack::ncompSVEC];
0094
0095 track.DumpToArray(y);
0096
0097
0098 G4double curveLength = 0.0;
0099 G4double endCurveLength = hstep;
0100
0101
0102 G4double h = hstep;
0103 if (hinitial > CLHEP::perMillion * hstep && hinitial < hstep)
0104 {
0105 h = hinitial;
0106 }
0107
0108 Base::GetStepper()->RightHandSide(y, dydx);
0109
0110 for (G4int iter = 0; iter < Base::GetMaxNoSteps(); ++iter)
0111 {
0112 const G4ThreeVector StartPos =
0113 field_utils::makeVector(y, field_utils::Value3D::Position);
0114
0115 OneGoodStep(y, dydx, curveLength, h, eps, hdid, hnext);
0116
0117 const G4ThreeVector EndPos =
0118 field_utils::makeVector(y, field_utils::Value3D::Position);
0119
0120 CheckStep(EndPos, StartPos, hdid);
0121
0122 G4double restCurveLength = endCurveLength - curveLength;
0123 if (restCurveLength < GetSmallestFraction() * hstep)
0124 {
0125 succeeded = true;
0126 break;
0127 }
0128 h = std::min(hnext, restCurveLength);
0129 }
0130
0131
0132 if (succeeded)
0133 {
0134 track.LoadFromArray(y, Base::GetStepper()->GetNumberOfVariables());
0135 track.SetCurveLength(track.GetCurveLength() + curveLength);
0136 }
0137
0138 return succeeded;
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 template <class T>
0155 void G4FSALIntegrationDriver<T>::
0156 OneGoodStep(G4double y[],
0157 G4double dydx[],
0158 G4double& curveLength,
0159 G4double htry,
0160 G4double eps_rel_max,
0161 G4double& hdid,
0162 G4double& hnext)
0163 {
0164 G4double error2 = DBL_MAX;
0165
0166 G4double yError[G4FieldTrack::ncompSVEC],
0167 yOut[G4FieldTrack::ncompSVEC],
0168 dydxOut[G4FieldTrack::ncompSVEC];
0169
0170
0171 G4double hstep = htry;
0172
0173 const G4int max_trials = 100;
0174
0175 for (G4int iter = 0; iter < max_trials; ++iter)
0176 {
0177 Base::GetStepper()->Stepper(y, dydx, hstep, yOut, yError, dydxOut);
0178 error2 = field_utils::relativeError2(y, yError, hstep, eps_rel_max);
0179
0180
0181 if (error2 <= 1) { break; }
0182
0183 hstep = Base::ShrinkStepSize2(hstep, error2);
0184 }
0185
0186 hnext = Base::GrowStepSize2(hstep, error2);
0187 curveLength += (hdid = hstep);
0188
0189 for(G4int k = 0; k < Base::GetStepper()->GetNumberOfVariables(); ++k)
0190 {
0191 y[k] = yOut[k];
0192 dydx[k] = dydxOut[k];
0193 }
0194 }
0195
0196 template <class T>
0197 G4bool G4FSALIntegrationDriver<T>::
0198 QuickAdvance( G4FieldTrack& fieldTrack, const G4double dydxIn[],
0199 G4double hstep,
0200 G4double& dchord_step, G4double& dyerr )
0201 {
0202 ++fNoQuickAvanceCalls;
0203
0204 if (hstep == 0)
0205 {
0206 std::ostringstream message;
0207 message << "Proposed step is zero; hstep = " << hstep << " !";
0208 G4Exception("G4FSALIntegrationDriver ::QuickAdvance()",
0209 "GeomField1001", JustWarning, message);
0210 return true;
0211 }
0212 if (hstep < 0)
0213 {
0214 std::ostringstream message;
0215 message << "Invalid run condition." << G4endl
0216 << "Proposed step is negative; hstep = "
0217 << hstep << "." << G4endl
0218 << "Requested step cannot be negative! Aborting event.";
0219 G4Exception("G4FSALIntegrationDriver ::QuickAdvance()",
0220 "GeomField0003", EventMustBeAborted, message);
0221 return false;
0222 }
0223
0224 G4double yError[G4FieldTrack::ncompSVEC],
0225 yIn[G4FieldTrack::ncompSVEC],
0226 yOut[G4FieldTrack::ncompSVEC],
0227 dydxOut[G4FieldTrack::ncompSVEC];
0228
0229 fieldTrack.DumpToArray(yIn);
0230
0231 Base::GetStepper()->Stepper(yIn, dydxIn, hstep, yOut, yError, dydxOut);
0232 dchord_step = Base::GetStepper()->DistChord();
0233
0234 fieldTrack.LoadFromArray(yOut, Base::GetStepper()->GetNumberOfVariables());
0235 fieldTrack.SetCurveLength(fieldTrack.GetCurveLength() + hstep);
0236
0237 dyerr = field_utils::absoluteError(yOut, yError, hstep);
0238
0239 return true;
0240 }
0241
0242 template <class T>
0243 void G4FSALIntegrationDriver<T>::SetSmallestFraction(G4double newFraction)
0244 {
0245 if( newFraction > 1.e-16 && newFraction < 1e-8 )
0246 {
0247 fSmallestFraction = newFraction;
0248 }
0249 else
0250 {
0251 std::ostringstream message;
0252 message << "Smallest Fraction not changed. " << G4endl
0253 << " Proposed value was " << newFraction << G4endl
0254 << " Value must be between 1.e-8 and 1.e-16";
0255 G4Exception("G4FSALIntegrationDriver::SetSmallestFraction()",
0256 "GeomField1001", JustWarning, message);
0257 }
0258 }
0259
0260 template <class T>
0261 void G4FSALIntegrationDriver<T>::CheckStep(
0262 const G4ThreeVector& posIn, const G4ThreeVector& posOut, G4double hdid)
0263 {
0264 const G4double endPointDist = (posOut - posIn).mag();
0265 if (endPointDist >= hdid * (1. + CLHEP::perMillion))
0266 {
0267 ++fNoAccurateAdvanceBadSteps;
0268 #ifdef G4DEBUG_FIELD
0269
0270
0271 if (endPointDist >= hdid * (1. + perThousand))
0272 {
0273 G4Exception("G4FSALIntegrationDriver::CheckStep()",
0274 "GeomField1002", JustWarning,
0275 "endPointDist >= hdid!");
0276 }
0277 #endif
0278 }
0279 else
0280 {
0281 ++fNoAccurateAdvanceGoodSteps;
0282 }
0283 }
0284
0285 template <class T>
0286 inline G4double G4FSALIntegrationDriver<T>::GetMinimumStep() const
0287 {
0288 return fMinimumStep;
0289 }
0290
0291 template <class T>
0292 void G4FSALIntegrationDriver<T>::SetMinimumStep(G4double minimumStepLength)
0293 {
0294 fMinimumStep = minimumStepLength;
0295 }
0296
0297 template <class T>
0298 G4int G4FSALIntegrationDriver<T>::GetVerboseLevel() const
0299 {
0300 return fVerboseLevel;
0301 }
0302
0303 template <class T>
0304 void G4FSALIntegrationDriver<T>::SetVerboseLevel(G4int newLevel)
0305 {
0306 fVerboseLevel = newLevel;
0307 }
0308
0309 template <class T>
0310 G4double G4FSALIntegrationDriver<T>::GetSmallestFraction() const
0311 {
0312 return fSmallestFraction;
0313 }
0314
0315 template <class T>
0316 void G4FSALIntegrationDriver<T>::IncrementQuickAdvanceCalls()
0317 {
0318 ++fNoQuickAvanceCalls;
0319 }
0320
0321 template <class T>
0322 G4double
0323 G4FSALIntegrationDriver<T>::AdvanceChordLimited(G4FieldTrack& track,
0324 G4double hstep,
0325 G4double eps,
0326 G4double chordDistance)
0327 {
0328 return ChordFinderDelegate::AdvanceChordLimitedImpl(track, hstep,
0329 eps, chordDistance);
0330 }
0331
0332 template <class T>
0333 void G4FSALIntegrationDriver<T>::StreamInfo( std::ostream& os ) const
0334 {
0335
0336 os << "State of G4IntegrationDriver: " << std::endl;
0337 os << "--Base state (G4RKIntegrationDriver): " << std::endl;
0338 Base::StreamInfo( os );
0339 os << "--Own state (G4IntegrationDriver<>): " << std::endl;
0340 os << " fMinimumStep = " << fMinimumStep << std::endl;
0341 os << " Smallest Fraction = " << fSmallestFraction << std::endl;
0342
0343 os << " verbose level = " << fVerboseLevel << std::endl;
0344 os << " Reintegrates = " << DoesReIntegrate() << std::endl;
0345 os << "--Chord Finder Delegate state: " << std::endl;
0346 ChordFinderDelegate::StreamDelegateInfo( os );
0347 }