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