Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4ParallelGeometriesLimiterProcess << 26 // 27 // ------------------------------------------- << 27 // >> 28 // 28 29 29 #include "G4ios.hh" 30 #include "G4ios.hh" 30 #include "G4ParallelGeometriesLimiterProcess.h 31 #include "G4ParallelGeometriesLimiterProcess.hh" 31 #include "G4BiasingProcessSharedData.hh" 32 #include "G4BiasingProcessSharedData.hh" 32 #include "G4ProcessManager.hh" 33 #include "G4ProcessManager.hh" 33 #include "G4TransportationManager.hh" 34 #include "G4TransportationManager.hh" 34 #include "G4PathFinder.hh" 35 #include "G4PathFinder.hh" 35 #include "G4FieldTrackUpdator.hh" 36 #include "G4FieldTrackUpdator.hh" 36 37 37 #include "G4SystemOfUnits.hh" 38 #include "G4SystemOfUnits.hh" 38 39 39 G4ParallelGeometriesLimiterProcess:: << 40 G4ParallelGeometriesLimiterProcess::G4ParallelGeometriesLimiterProcess(const G4String& processName) : 40 G4ParallelGeometriesLimiterProcess(const G4Str << 41 G4VProcess(processName, fParallel), 41 : G4VProcess(processName, fParallel) << 42 fParallelWorldSafety( 0.0 ), >> 43 fIsTrackingTime ( false ), >> 44 fFieldTrack ( '0' ) 42 { 45 { 43 // -- Process Sub Type ? << 46 // -- Process Sub Type ? ยงยง 44 47 45 fPathFinder = G4PathFinder::GetInstance(); << 48 fPathFinder = G4PathFinder::GetInstance(); 46 fTransportationManager = G4TransportationMan 49 fTransportationManager = G4TransportationManager::GetTransportationManager(); 47 } 50 } 48 51 >> 52 49 // ---------------------------- 53 // ---------------------------- 50 // -- Add/Remove world volumes: 54 // -- Add/Remove world volumes: 51 // ---------------------------- 55 // ---------------------------- 52 void G4ParallelGeometriesLimiterProcess:: << 56 void G4ParallelGeometriesLimiterProcess::AddParallelWorld(const G4String& parallelWorldName) 53 AddParallelWorld(const G4String& parallelWorld << 54 { 57 { >> 58 55 // -- Refuse adding parallel geometry during 59 // -- Refuse adding parallel geometry during tracking time: 56 if (fIsTrackingTime) 60 if (fIsTrackingTime) 57 { << 58 G4ExceptionDescription ed; << 59 ed << "G4ParallelGeometriesLimiterProcess << 60 << "': adding a parallel world volume a << 61 << G4endl; << 62 G4Exception("G4ParallelGeometriesLimiterPr << 63 "BIAS.GEN.21", JustWarning, ed << 64 return; << 65 } << 66 else << 67 { << 68 G4VPhysicalVolume* newWorld = fTransportat << 69 << 70 // -- Fatal exception if requested world d << 71 if (newWorld == nullptr) << 72 { << 73 G4ExceptionDescription tellWhatIsWrong; << 74 tellWhatIsWrong << "Volume `" << parall << 75 << "' is not a parallel << 76 << G4endl; << 77 G4Exception("G4ParallelGeometriesLimiter << 78 "BIAS.GEN.22", FatalExceptio << 79 } << 80 << 81 // -- Protection against adding the mass g << 82 if ( newWorld == fTransportationManager-> << 83 { 61 { 84 G4ExceptionDescription ed; 62 G4ExceptionDescription ed; 85 ed << "G4ParallelGeometriesLimiterProces 63 ed << "G4ParallelGeometriesLimiterProcess `" << GetProcessName() 86 << "': trying to add the world volume << 64 << "': adding a parallel world volume at tracking time is not allowed." << G4endl; 87 << G4endl; << 65 G4Exception("G4ParallelGeometriesLimiterProcess::AddParallelWorld(const G4String& parallelWorldName)", 88 G4Exception("G4ParallelGeometriesLimiter << 66 "BIAS.GEN.21", 89 "BIAS.GEN.23", JustWarning, << 67 JustWarning, ed, >> 68 "Call ignored."); 90 return; 69 return; 91 } 70 } 92 << 71 93 // -- Add parallel world, taking care it i << 72 else 94 G4bool isNew = true; << 73 95 for ( auto knownWorld : fParallelWorlds ) << 96 { << 97 if ( knownWorld == newWorld ) { isNew = << 98 } << 99 if ( isNew ) << 100 { << 101 fParallelWorlds.push_back( newWorld ); << 102 } << 103 else << 104 { 74 { 105 G4ExceptionDescription ed; << 75 G4VPhysicalVolume* newWorld = fTransportationManager->IsWorldExisting( parallelWorldName ); 106 ed << "G4ParallelGeometriesLimiterProces << 76 107 << "': trying to re-add the parallel << 77 // -- Fatal exception if requested world does not exist: 108 << parallelWorldName << "'." << G4end << 78 if (newWorld == 0) 109 G4Exception("G4ParallelGeometriesLimiter << 79 { 110 "BIAS.GEN.24", JustWarning, << 80 G4ExceptionDescription tellWhatIsWrong; 111 return; << 81 tellWhatIsWrong << "Volume `" << parallelWorldName >> 82 << "' is not a parallel world nor the mass world volume." >> 83 << G4endl; >> 84 G4Exception("G4ParallelGeometriesLimiterProcess::SetWorldVolume(const G4String)", >> 85 "BIAS.GEN.22", >> 86 FatalException, >> 87 tellWhatIsWrong); >> 88 } >> 89 >> 90 // -- Protection against adding the mass geometry world as parallel world: >> 91 if ( newWorld == fTransportationManager->GetNavigatorForTracking()->GetWorldVolume() ) >> 92 { >> 93 G4ExceptionDescription ed; >> 94 ed << "G4ParallelGeometriesLimiterProcess `" << GetProcessName() >> 95 << "': trying to add the world volume for tracking as a parallel world." << G4endl; >> 96 G4Exception("G4ParallelGeometriesLimiterProcess::AddParallelWorld(const G4String& parallelWorldName)", >> 97 "BIAS.GEN.23", >> 98 JustWarning, ed, >> 99 "Call ignored."); >> 100 return; >> 101 } >> 102 >> 103 // -- Add parallel world, taking care it is not in the list yet: >> 104 G4bool isNew = true; >> 105 for ( auto knownWorld : fParallelWorlds ) >> 106 { >> 107 if ( knownWorld == newWorld ) isNew = false; >> 108 } >> 109 if ( isNew ) fParallelWorlds.push_back( newWorld ); >> 110 else >> 111 { >> 112 G4ExceptionDescription ed; >> 113 ed << "G4ParallelGeometriesLimiterProcess `" << GetProcessName() >> 114 << "': trying to re-add the parallel world volume `" << parallelWorldName << "'." << G4endl; >> 115 G4Exception("G4ParallelGeometriesLimiterProcess::AddParallelWorld(const G4String& parallelWorldName)", >> 116 "BIAS.GEN.24", >> 117 JustWarning, ed, >> 118 "Call ignored."); >> 119 return; >> 120 } 112 } 121 } 113 } << 122 114 } 123 } 115 124 116 void G4ParallelGeometriesLimiterProcess:: << 125 117 RemoveParallelWorld(const G4String& parallelWo << 126 void G4ParallelGeometriesLimiterProcess::RemoveParallelWorld(const G4String& parallelWorldName) 118 { 127 { >> 128 119 // -- Refuse refuse removing parallel geomet 129 // -- Refuse refuse removing parallel geometry during tracking time: 120 if (fIsTrackingTime) 130 if (fIsTrackingTime) 121 { << 122 G4ExceptionDescription ed; << 123 ed << "G4ParallelGeometriesLimiterProcess << 124 << "': removing a parallel world volume << 125 << G4endl; << 126 G4Exception("G4ParallelGeometriesLimiterPr << 127 "BIAS.GEN.25", JustWarning, ed << 128 return; << 129 } << 130 else << 131 { << 132 G4VPhysicalVolume* newWorld = fTransportat << 133 if (newWorld == nullptr) << 134 { 131 { 135 G4ExceptionDescription ed; 132 G4ExceptionDescription ed; 136 ed << "G4ParallelGeometriesLimiterProces 133 ed << "G4ParallelGeometriesLimiterProcess `" << GetProcessName() 137 << "': trying to remove an inexisting << 134 << "': removing a parallel world volume at tracking time is not allowed." << G4endl; 138 << parallelWorldName << "'." << G4end << 135 G4Exception("G4ParallelGeometriesLimiterProcess::RemoveParallelWorld(const G4String& parallelWorldName)", 139 G4Exception("G4ParallelGeometriesLimiter << 136 "BIAS.GEN.25", 140 "BIAS.GEN.26", JustWarning, << 137 JustWarning, ed, >> 138 "Call ignored."); 141 return; 139 return; 142 } 140 } 143 << 141 144 // -- get position of world volume in list << 142 else 145 std::size_t iWorld = 0; << 143 146 for ( auto knownWorld : fParallelWorlds ) << 147 { << 148 if ( knownWorld == newWorld ) break; << 149 ++iWorld; << 150 } << 151 << 152 if ( iWorld == fParallelWorlds.size() ) << 153 { 144 { 154 G4ExceptionDescription ed; << 145 G4VPhysicalVolume* newWorld = fTransportationManager->IsWorldExisting( parallelWorldName ); 155 ed << "G4ParallelGeometriesLimiterProces << 146 156 << "': trying to remove an non-regist << 147 if (newWorld == 0) 157 << parallelWorldName << "'." << G4end << 148 { 158 G4Exception("G4ParallelGeometriesLimiter << 149 159 "BIAS.GEN.27", JustWarning, << 150 G4ExceptionDescription ed; 160 return; << 151 ed << "G4ParallelGeometriesLimiterProcess `" << GetProcessName() >> 152 << "': trying to remove an inexisting parallel world '" << parallelWorldName << "'." << G4endl; >> 153 G4Exception("G4ParallelGeometriesLimiterProcess::RemoveParallelWorld(const G4String& parallelWorldName)", >> 154 "BIAS.GEN.26", >> 155 JustWarning, ed, >> 156 "Call ignored."); >> 157 return; >> 158 } >> 159 >> 160 // -- get position of world volume in list: >> 161 size_t iWorld = 0; >> 162 for ( auto knownWorld : fParallelWorlds ) >> 163 { >> 164 if ( knownWorld == newWorld ) break; >> 165 iWorld++; >> 166 } >> 167 >> 168 if ( iWorld == fParallelWorlds.size() ) >> 169 { >> 170 G4ExceptionDescription ed; >> 171 ed << "G4ParallelGeometriesLimiterProcess `" << GetProcessName() >> 172 << "': trying to remove an non-registerered parallel world '" << parallelWorldName << "'." << G4endl; >> 173 G4Exception("G4ParallelGeometriesLimiterProcess::RemoveParallelWorld(const G4String& parallelWorldName)", >> 174 "BIAS.GEN.27", >> 175 JustWarning, ed, >> 176 "Call ignored."); >> 177 return; >> 178 } >> 179 >> 180 // -- remove from vector: >> 181 fParallelWorlds.erase( fParallelWorlds.begin() + iWorld ); >> 182 161 } 183 } 162 // -- remove from vector: << 184 163 fParallelWorlds.erase( fParallelWorlds.beg << 185 164 } << 186 165 } 187 } 166 188 >> 189 167 // -------------------- 190 // -------------------- 168 // Start/End tracking: 191 // Start/End tracking: 169 // -------------------- 192 // -------------------- 170 void G4ParallelGeometriesLimiterProcess::Start 193 void G4ParallelGeometriesLimiterProcess::StartTracking(G4Track* track) 171 { 194 { 172 fIsTrackingTime = true; 195 fIsTrackingTime = true; 173 196 174 // -- fetch the navigators, their indeces, a 197 // -- fetch the navigators, their indeces, and activate: 175 fParallelWorldNavigators.clear(); << 198 fParallelWorldNavigators .clear(); 176 fParallelWorldNavigatorIndeces.clear(); 199 fParallelWorldNavigatorIndeces.clear(); 177 fParallelWorldSafeties.clear(); << 200 fParallelWorldSafeties .clear(); 178 fParallelWorldIsLimiting.clear(); << 201 fParallelWorldIsLimiting .clear(); 179 fParallelWorldWasLimiting.clear(); << 202 fParallelWorldWasLimiting .clear(); 180 fCurrentVolumes.clear(); << 203 fCurrentVolumes .clear(); 181 fPreviousVolumes.clear(); << 204 fPreviousVolumes .clear(); 182 for ( auto parallelWorld : fParallelWorlds ) 205 for ( auto parallelWorld : fParallelWorlds ) 183 { << 206 { 184 fParallelWorldNavigators.push_back( fTrans << 207 fParallelWorldNavigators .push_back( fTransportationManager-> GetNavigator( parallelWorld ) ); 185 fParallelWorldNavigatorIndeces.push_back( << 208 fParallelWorldNavigatorIndeces.push_back( fTransportationManager->ActivateNavigator( fParallelWorldNavigators.back() ) ); 186 fParallelWorldSafeties.push_back( 0.0 ); << 209 fParallelWorldSafeties .push_back( 0.0 ); 187 fParallelWorldIsLimiting.push_back( false << 210 fParallelWorldIsLimiting .push_back( false ); 188 fParallelWorldWasLimiting.push_back( false << 211 fParallelWorldWasLimiting .push_back( false ); 189 } << 212 } 190 213 191 fPathFinder->PrepareNewTrack( track->GetPosi 214 fPathFinder->PrepareNewTrack( track->GetPosition(), track->GetMomentumDirection() ); 192 // -- Does it work at this level, after "Pre << 215 // -- ยงยง does it work at this level, after "PrepareNewTrack" above ? 193 for ( auto navigatorIndex : fParallelWorldNa 216 for ( auto navigatorIndex : fParallelWorldNavigatorIndeces ) 194 { << 217 { 195 fPreviousVolumes.push_back( nullptr ); << 218 fPreviousVolumes.push_back( nullptr ); 196 fCurrentVolumes .push_back( fPathFinder->G << 219 fCurrentVolumes .push_back( fPathFinder->GetLocatedVolume( navigatorIndex ) ); 197 } 220 } 198 221 199 // -- will force updating safety: 222 // -- will force updating safety: 200 fParallelWorldSafety = 0.0; 223 fParallelWorldSafety = 0.0; 201 for ( std::size_t i = 0 ; i < fParallelWorld << 224 for ( size_t i = 0 ; i < fParallelWorldNavigatorIndeces.size() ; i++ ) fParallelWorldSafeties[i] = 0.0; 202 { << 203 fParallelWorldSafeties[i] = 0.0; << 204 } << 205 } 225 } 206 226 >> 227 207 void G4ParallelGeometriesLimiterProcess::EndTr 228 void G4ParallelGeometriesLimiterProcess::EndTracking() 208 { 229 { 209 fIsTrackingTime = false; 230 fIsTrackingTime = false; 210 for ( auto parallelWorldNavigator : fParalle 231 for ( auto parallelWorldNavigator : fParallelWorldNavigators ) 211 { << 212 fTransportationManager->DeActivateNavigato 232 fTransportationManager->DeActivateNavigator( parallelWorldNavigator ); 213 } << 214 } 233 } 215 234 216 G4double G4ParallelGeometriesLimiterProcess:: << 235 217 PostStepGetPhysicalInteractionLength(const G4T << 236 G4double G4ParallelGeometriesLimiterProcess::PostStepGetPhysicalInteractionLength(const G4Track&, G4double, G4ForceCondition* condition) 218 G4ForceCo << 219 { 237 { >> 238 220 // -- push previous step limitation flags an 239 // -- push previous step limitation flags and volumes: 221 // -- consider switching pointers insteads o << 240 // -- ยงยง consider switching pointers insteads of making copies of std::vector's: 222 fParallelWorldWasLimiting = fParallelWorldIs 241 fParallelWorldWasLimiting = fParallelWorldIsLimiting; 223 fPreviousVolumes = fCurrentVolumes; << 242 fPreviousVolumes = fCurrentVolumes; 224 243 225 // -- update volumes: 244 // -- update volumes: 226 std::size_t i = 0; << 245 size_t i = 0; 227 for ( auto navigatorIndex : fParallelWorldNa << 246 for ( auto navigatorIndex : fParallelWorldNavigatorIndeces ) fCurrentVolumes[i++] = fPathFinder->GetLocatedVolume( navigatorIndex ); 228 { << 229 fCurrentVolumes[i++] = fPathFinder->GetLoc << 230 } << 231 247 232 *condition = NotForced; 248 *condition = NotForced; 233 return DBL_MAX; 249 return DBL_MAX; 234 } 250 } 235 251 236 G4double G4ParallelGeometriesLimiterProcess:: << 252 237 AlongStepGetPhysicalInteractionLength(const G4 << 253 G4double G4ParallelGeometriesLimiterProcess::AlongStepGetPhysicalInteractionLength(const G4Track& track, 238 G4double << 254 G4double previousStepSize, 239 G4double << 255 G4double currentMinimumStep, 240 G4double << 256 G4double& proposedSafety, 241 G4GPILSe << 257 G4GPILSelection* selection) 242 { 258 { >> 259 243 // -- Init: 260 // -- Init: 244 // -- Note that the returnedStep must be phy << 261 // -- Note that the returnedStep must be physically meaningful, even if we return NotCandidateForSelection as condition; 245 // -- even if we return NotCandidateForSelec << 262 // -- the reason is that the stepping manager always takes the smallest alongstep among the returned ones (point related 246 // -- the reason is that the stepping manage << 247 // -- alongstep among the returned ones (poi << 248 // -- to geometry step length wrt to true pa 263 // -- to geometry step length wrt to true path length). 249 *selection = NotCandidateForSelection; << 264 *selection = NotCandidateForSelection; 250 G4double returnedStep = DBL_MAX; 265 G4double returnedStep = DBL_MAX; 251 266 252 // -- G4FieldTrack and ELimited: 267 // -- G4FieldTrack and ELimited: 253 static G4ThreadLocal G4FieldTrack* endTrack_ << 268 static G4ThreadLocal G4FieldTrack *endTrack_G4MT_TLS_ = 0 ; 254 if (!endTrack_MT) endTrack_MT = new G4FieldT << 269 if (!endTrack_G4MT_TLS_) endTrack_G4MT_TLS_ = new G4FieldTrack ('0') ; 255 G4FieldTrack& endTrack = *endTrack_MT; << 270 G4FieldTrack &endTrack = *endTrack_G4MT_TLS_; 256 << 271 257 static G4ThreadLocal ELimited* eLimited_MT = << 272 static G4ThreadLocal ELimited *eLimited_G4MT_TLS_ = 0 ; 258 if (!eLimited_MT) eLimited_MT = new ELimited << 273 if (!eLimited_G4MT_TLS_) eLimited_G4MT_TLS_ = new ELimited ; 259 ELimited &eLimited = *eLimited_MT; << 274 ELimited &eLimited = *eLimited_G4MT_TLS_; >> 275 260 276 261 // ------------------- 277 // ------------------- 262 // -- Update safeties: 278 // -- Update safeties: 263 // ------------------- 279 // ------------------- 264 if ( previousStepSize > 0.0 ) 280 if ( previousStepSize > 0.0 ) 265 { << 266 for ( auto& parallelWorldSafety : fParalle << 267 { 281 { 268 parallelWorldSafety -= previousStepSize; << 282 for ( auto& parallelWorldSafety : fParallelWorldSafeties ) 269 if ( parallelWorldSafety < 0. ) { paral << 283 { 270 fParallelWorldSafety = parallelWorldSafe << 284 parallelWorldSafety -= previousStepSize; 271 ? parallelWorldSafe << 285 if ( parallelWorldSafety < 0. ) parallelWorldSafety = 0.0; >> 286 fParallelWorldSafety = parallelWorldSafety < fParallelWorldSafety ? parallelWorldSafety : fParallelWorldSafety ; >> 287 } 272 } 288 } 273 } << 274 289 >> 290 275 // ----------------------------------------- 291 // ------------------------------------------ 276 // Determination of the proposed step length 292 // Determination of the proposed step length: 277 // ----------------------------------------- 293 // ------------------------------------------ 278 if ( ( currentMinimumStep <= fParallelWorldS << 294 if ( ( currentMinimumStep <= fParallelWorldSafety ) && ( currentMinimumStep > 0. ) ) 279 && ( currentMinimumStep > 0. ) ) << 295 { 280 { << 296 // -- No chance to limit the step, as proposed move inside safety 281 // -- No chance to limit the step, as prop << 297 282 << 298 returnedStep = currentMinimumStep; 283 returnedStep = currentMinimumStep; << 299 proposedSafety = fParallelWorldSafety - currentMinimumStep; 284 proposedSafety = fParallelWorldSafety - cu << 300 } 285 } << 286 else 301 else 287 { << 302 { 288 // -- Proposed move exceeds common safety, << 303 // -- Proposed move exceeds common safety, need to state 289 G4double smallestReturnedStep = -1.0; << 304 G4double smallestReturnedStep = -1.0; 290 ELimited eLimitedForSmallestStep = kDoNot; << 305 ELimited eLimitedForSmallestStep = kDoNot; 291 for ( std::size_t i = 0 ; i < fParallelWor << 306 for ( size_t i = 0 ; i < fParallelWorldNavigatorIndeces.size() ; i++ ) 292 { << 307 { 293 // -- Update safety of geometries having << 308 // -- Update safety of geometries having safety smaller than current minimum step 294 if ( currentMinimumStep >= fParallelWor << 309 if ( currentMinimumStep >= fParallelWorldSafeties[i] ) 295 { << 310 { 296 G4FieldTrackUpdator::Update(&fFieldTra << 311 G4FieldTrackUpdator::Update(&fFieldTrack, &track); 297 G4double tmpReturnedStep = fPathFinder << 312 G4double tmpReturnedStep = fPathFinder->ComputeStep(fFieldTrack, 298 currentMi << 313 currentMinimumStep, 299 fParallel << 314 fParallelWorldNavigatorIndeces[i], 300 track.Get << 315 track.GetCurrentStepNumber(), 301 fParallel << 316 fParallelWorldSafeties[i], 302 eLimited, << 317 eLimited, 303 << 318 endTrack, 304 if ( ( smallestReturnedStep < 0.0 ) || << 319 track.GetVolume()); 305 { << 320 306 smallestReturnedStep = tmpReturnedSt << 321 if ( ( smallestReturnedStep < 0.0 ) || ( tmpReturnedStep <= smallestReturnedStep ) ) 307 eLimitedForSmallestStep = eLimited; << 322 { 308 } << 323 smallestReturnedStep = tmpReturnedStep; 309 << 324 eLimitedForSmallestStep = eLimited; 310 if (eLimited == kDoNot) << 325 } 311 { << 326 312 // -- Step not limited by this geome << 327 if (eLimited == kDoNot) 313 fParallelWorldSafeties[i] = fParalle << 328 { 314 fParallelWorldIsLimiting[i] = false; << 329 // -- Step not limited by this geometry 315 } << 330 fParallelWorldSafeties[i] = fParallelWorldNavigators[i]->ComputeSafety(endTrack.GetPosition()); 316 else << 331 fParallelWorldIsLimiting[i] = false; 317 { << 332 } 318 fParallelWorldIsLimiting[i] = true; << 333 else 319 } << 334 { 320 } << 335 fParallelWorldIsLimiting[i] = true; 321 << 336 } 322 // -- update with smallest safety: << 337 } 323 fParallelWorldSafety = fParallelWorldSaf << 338 324 ? fParallelWorldSa << 339 // -- update with smallest safety: 325 } << 340 fParallelWorldSafety = fParallelWorldSafeties[i] < fParallelWorldSafety ? fParallelWorldSafeties[i] : fParallelWorldSafety ; 326 << 341 } 327 // -- no geometry limitation among all geo << 342 328 // -- Beware : the returnedStep must be ph << 343 // -- no geometry limitation among all geometries, can return currentMinimumStep (or DBL_MAX): 329 if ( eLimitedForSmallestStep == kDoNot ) << 344 // -- Beware : the returnedStep must be physically meaningful, even if we say "NotCandidateForSelection" ! 330 { << 345 if ( eLimitedForSmallestStep == kDoNot ) 331 returnedStep = currentMinimumStep; << 346 { 332 } << 347 returnedStep = currentMinimumStep; 333 // -- proposed step length of limiting geo << 348 } 334 if ( eLimitedForSmallestStep == kUnique | << 349 // -- proposed step length of limiting geometry: 335 eLimitedForSmallestStep == kSharedOth << 350 if ( eLimitedForSmallestStep == kUnique || 336 { << 351 eLimitedForSmallestStep == kSharedOther ) 337 *selection = CandidateForSelection; << 352 { 338 returnedStep = smallestReturnedStep; << 353 *selection = CandidateForSelection; 339 } << 354 returnedStep = smallestReturnedStep; 340 else if ( eLimitedForSmallestStep == kShar << 355 } 341 { << 356 else if ( eLimitedForSmallestStep == kSharedTransport) 342 // -- Expand to disable its selection in << 357 { 343 returnedStep = smallestReturnedStep* (1. << 358 returnedStep = smallestReturnedStep* (1.0 + 1.0e-9); // -- Expand to disable its selection in Step Manager comparison 344 } << 359 } 345 << 360 346 // -- and smallest safety among geometries << 361 // -- and smallest safety among geometries: 347 proposedSafety = fParallelWorldSafety ; << 362 proposedSafety = fParallelWorldSafety ; 348 } << 363 } 349 364 350 // -- returns step length, and proposedSafet 365 // -- returns step length, and proposedSafety 351 return returnedStep; 366 return returnedStep; 352 } 367 } 353 368 354 G4VParticleChange* G4ParallelGeometriesLimiter << 369 355 AlongStepDoIt( const G4Track& track, const G4S << 370 G4VParticleChange* G4ParallelGeometriesLimiterProcess::AlongStepDoIt( const G4Track& track, >> 371 const G4Step& ) 356 { 372 { >> 373 357 fDummyParticleChange.Initialize(track); 374 fDummyParticleChange.Initialize(track); 358 return &fDummyParticleChange; 375 return &fDummyParticleChange; 359 } 376 } 360 377 361 void G4ParallelGeometriesLimiterProcess:: << 378 362 SetProcessManager(const G4ProcessManager* mgr) << 379 void G4ParallelGeometriesLimiterProcess::SetProcessManager(const G4ProcessManager* mgr) 363 { 380 { 364 G4BiasingProcessSharedData *sharedData(nullp 381 G4BiasingProcessSharedData *sharedData(nullptr); 365 382 366 // -- initialize sharedData pointer: 383 // -- initialize sharedData pointer: 367 if ( G4BiasingProcessSharedData::fSharedData << 384 if ( G4BiasingProcessSharedData::fSharedDataMap.Find(mgr) == G4BiasingProcessSharedData::fSharedDataMap.End() ) 368 { << 385 { 369 sharedData = new G4BiasingProcessSharedDat << 386 sharedData = new G4BiasingProcessSharedData( mgr ); 370 G4BiasingProcessSharedData::fSharedDataMap << 387 G4BiasingProcessSharedData::fSharedDataMap[mgr] = sharedData; 371 } << 388 } 372 else << 389 else sharedData = G4BiasingProcessSharedData::fSharedDataMap[mgr] ; 373 { << 390 374 sharedData = G4BiasingProcessSharedData:: << 375 } << 376 << 377 // -- add itself to the shared data: 391 // -- add itself to the shared data: 378 if ( sharedData->fParallelGeometriesLimiterP << 392 if ( sharedData->fParallelGeometriesLimiterProcess == nullptr ) sharedData->fParallelGeometriesLimiterProcess = this; 379 { << 380 sharedData->fParallelGeometriesLimiterProc << 381 } << 382 else 393 else 383 { << 394 { 384 G4ExceptionDescription ed; << 395 G4ExceptionDescription ed; 385 ed << " Trying to add more than one G4Para << 396 ed << " Trying to add more than one G4ParallelGeometriesLimiterProcess process to the process manager " << mgr 386 << mgr << 397 << " (process manager for `" << mgr->GetParticleType()->GetParticleName() << "'). Only one is needed. Call ignored." << G4endl; 387 << " (process manager for `" << mgr->Ge << 398 G4Exception(" G4ParallelGeometriesLimiterProcess::SetProcessManager(...)", 388 << "'). Only one is needed. Call ignore << 399 "BIAS.GEN.29", 389 G4Exception(" G4ParallelGeometriesLimiterP << 400 JustWarning, 390 "BIAS.GEN.29", JustWarning, ed << 401 ed); 391 } << 402 } 392 } 403 } 393 404 394 G4int G4ParallelGeometriesLimiterProcess:: << 405 395 GetParallelWorldIndex( const G4VPhysicalVolume << 406 G4int G4ParallelGeometriesLimiterProcess::GetParallelWorldIndex( const G4VPhysicalVolume* parallelWorld ) const 396 { 407 { 397 G4int toReturn = -1; 408 G4int toReturn = -1; 398 G4int iWorld = 0; 409 G4int iWorld = 0; 399 for ( auto world : fParallelWorlds ) 410 for ( auto world : fParallelWorlds ) 400 { << 401 if ( world == parallelWorld ) << 402 { 411 { 403 toReturn = iWorld; << 412 if ( world == parallelWorld ) 404 break; << 413 { >> 414 toReturn = iWorld; >> 415 break; >> 416 } >> 417 iWorld++; 405 } 418 } 406 ++iWorld; << 407 } << 408 return toReturn; 419 return toReturn; 409 } 420 } 410 421 411 G4int G4ParallelGeometriesLimiterProcess:: << 422 412 GetParallelWorldIndex( const G4String& paralle << 423 G4int G4ParallelGeometriesLimiterProcess::GetParallelWorldIndex( G4String parallelWorldName ) const 413 { 424 { 414 G4VPhysicalVolume* aWorld = fTransportationM << 425 G4VPhysicalVolume* aWorld = fTransportationManager->IsWorldExisting( parallelWorldName ); // note aWorld might be nullptr 415 // note aWorld might be nullptr << 416 return GetParallelWorldIndex( aWorld ); 426 return GetParallelWorldIndex( aWorld ); 417 } 427 } >> 428 418 429