Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // class G4NavigationLogger Implementation 27 // 28 // Author: G.Cosmo, 2010 29 // -------------------------------------------------------------------- 30 31 #include <iomanip> 32 #include <CLHEP/Units/SystemOfUnits.h> 33 34 #include "G4NavigationLogger.hh" 35 #include "G4GeometryTolerance.hh" 36 37 using CLHEP::millimeter; 38 39 G4NavigationLogger::G4NavigationLogger(const G4String& id) 40 : fId(id) 41 { 42 } 43 44 G4NavigationLogger::~G4NavigationLogger() = default; 45 46 // ******************************************************************** 47 // PreComputeStepLog 48 // ******************************************************************** 49 // 50 void 51 G4NavigationLogger::PreComputeStepLog(const G4VPhysicalVolume* motherPhysical, 52 G4double motherSafety, 53 const G4ThreeVector& localPoint) const 54 { 55 G4VSolid* motherSolid = motherPhysical->GetLogicalVolume()->GetSolid(); 56 G4String fType = fId + "::ComputeStep()"; 57 58 if ( fVerbose == 1 || fVerbose > 4 ) 59 { 60 G4cout << "*************** " << fType << " *****************" << G4endl 61 << " VolType " 62 << std::setw(15) << "Safety/mm" << " " 63 << std::setw(15) << "Distance/mm" << " " 64 << std::setw(52) << "Position (local coordinates)" 65 << " - Solid" << G4endl; 66 G4cout << " Mother " 67 << std::setw(15) << motherSafety / millimeter << " " 68 << std::setw(15) << "N/C" << " " << localPoint << " - " 69 << motherSolid->GetEntityType() << ": " << motherSolid->GetName() 70 << G4endl; 71 } 72 if ( motherSafety < 0.0 ) 73 { 74 std::ostringstream message; 75 message << "Negative Safety In Voxel Navigation !" << G4endl 76 << " Current solid " << motherSolid->GetName() 77 << " gave negative safety: " << motherSafety / millimeter << G4endl 78 << " for the current (local) point " << localPoint; 79 message << " Solid info: " << *motherSolid << G4endl; 80 G4Exception(fType, "GeomNav0003", FatalException, message); 81 } 82 if( motherSolid->Inside(localPoint)==kOutside ) 83 { 84 std::ostringstream message; 85 message << "Point is outside Current Volume - " << G4endl 86 << " Point " << localPoint / millimeter 87 << " is outside current volume '" << motherPhysical->GetName() 88 << "'" << G4endl; 89 G4double estDistToSolid= motherSolid->DistanceToIn(localPoint); 90 message << " Estimated isotropic distance to solid (distToIn)= " 91 << estDistToSolid << G4endl; 92 if( estDistToSolid > 100.0 * motherSolid->GetTolerance() ) 93 { 94 message << " Solid info: " << *motherSolid << G4endl; 95 G4Exception(fType, "GeomNav0003", JustWarning, message, 96 "Point is far outside Current Volume !" ); 97 } 98 else 99 { 100 G4Exception(fType, "GeomNav1001", JustWarning, message, 101 "Point is a little outside Current Volume."); 102 } 103 } 104 105 // Verification / verbosity 106 // 107 if ( fVerbose > 1 ) 108 { 109 static const G4int precVerf = 16; // Precision 110 G4long oldprec = G4cout.precision(precVerf); 111 G4cout << " - Information on mother / key daughters ..." << G4endl; 112 G4cout << " Type " << std::setw(12) << "Solid-Name" << " " 113 << std::setw(3*(6+precVerf)) << " local point" << " " 114 << std::setw(4+precVerf) << "solid-Safety" << " " 115 << std::setw(4+precVerf) << "solid-Step" << " " 116 << std::setw(17) << "distance Method " 117 << std::setw(3*(6+precVerf)) << " local direction" << " " 118 << G4endl; 119 G4cout << " Mother " << std::setw(12) << motherSolid->GetName() << " " 120 << std::setw(4+precVerf) << localPoint << " " 121 << std::setw(4+precVerf) << motherSafety << " " 122 << G4endl; 123 G4cout.precision(oldprec); 124 } 125 } 126 127 // ******************************************************************** 128 // AlongComputeStepLog 129 // ******************************************************************** 130 // 131 void 132 G4NavigationLogger::AlongComputeStepLog(const G4VSolid* sampleSolid, 133 const G4ThreeVector& samplePoint, 134 const G4ThreeVector& sampleDirection, 135 const G4ThreeVector& localDirection, 136 G4double sampleSafety, 137 G4double sampleStep) const 138 { 139 // Check to see that the resulting point is indeed in/on volume. 140 // This check could eventually be made only for successful candidate. 141 142 if ( sampleStep < kInfinity ) 143 { 144 G4ThreeVector intersectionPoint; 145 intersectionPoint = samplePoint + sampleStep * sampleDirection; 146 EInside insideIntPt = sampleSolid->Inside(intersectionPoint); 147 G4String fType = fId + "::ComputeStep()"; 148 149 G4String solidResponse = "-kInside-"; 150 if (insideIntPt == kOutside) 151 { solidResponse = "-kOutside-"; } 152 else if (insideIntPt == kSurface) 153 { solidResponse = "-kSurface-"; } 154 155 if ( fVerbose == 1 || fVerbose > 4 ) 156 { 157 G4cout << " Invoked Inside() for solid: " 158 << sampleSolid->GetName() 159 << ". Solid replied: " << solidResponse << G4endl 160 << " For point p: " << intersectionPoint 161 << ", considered as 'intersection' point." << G4endl; 162 } 163 164 G4double safetyIn = -1, safetyOut = -1; // Set to invalid values 165 G4double newDistIn = -1, newDistOut = -1; 166 if( insideIntPt != kInside ) 167 { 168 safetyIn = sampleSolid->DistanceToIn(intersectionPoint); 169 newDistIn = sampleSolid->DistanceToIn(intersectionPoint, 170 sampleDirection); 171 } 172 if( insideIntPt != kOutside ) 173 { 174 safetyOut = sampleSolid->DistanceToOut(intersectionPoint); 175 newDistOut = sampleSolid->DistanceToOut(intersectionPoint, 176 sampleDirection); 177 } 178 if( insideIntPt != kSurface ) 179 { 180 std::ostringstream message; 181 message.precision(16); 182 message << "Conflicting response from Solid." << G4endl 183 << " Inaccurate solid DistanceToIn" 184 << " for solid " << sampleSolid->GetName() << G4endl 185 << " Solid gave DistanceToIn = " 186 << sampleStep << " yet returns " << solidResponse 187 << " for this point !" << G4endl 188 << " Original Point = " << samplePoint << G4endl 189 << " Original Direction = " << sampleDirection << G4endl 190 << " Intersection Point = " << intersectionPoint << G4endl 191 << " Safety values: " << G4endl; 192 if ( insideIntPt != kInside ) 193 { 194 message << " DistanceToIn(p) = " << safetyIn; 195 } 196 if ( insideIntPt != kOutside ) 197 { 198 message << " DistanceToOut(p) = " << safetyOut; 199 } 200 message << G4endl; 201 message << " Solid Parameters: " << *sampleSolid; 202 G4Exception(fType, "GeomNav1001", JustWarning, message); 203 } 204 else 205 { 206 // If it is on the surface, *ensure* that either DistanceToIn 207 // or DistanceToOut returns a finite value ( >= Tolerance). 208 // 209 if( std::max( newDistIn, newDistOut ) <= 210 G4GeometryTolerance::GetInstance()->GetSurfaceTolerance() ) 211 { 212 std::ostringstream message; 213 message << "Zero from both Solid DistanceIn and Out(p,v)." << G4endl 214 << " Identified point for which the solid " 215 << sampleSolid->GetName() << G4endl 216 << " has MAJOR problem: " << G4endl 217 << " --> Both DistanceToIn(p,v) and DistanceToOut(p,v) " 218 << "return Zero, an equivalent value or negative value." 219 << G4endl 220 << " Solid: " << sampleSolid << G4endl 221 << " Point p= " << intersectionPoint << G4endl 222 << " Direction v= " << sampleDirection << G4endl 223 << " DistanceToIn(p,v) = " << newDistIn << G4endl 224 << " DistanceToOut(p,v,..) = " << newDistOut << G4endl 225 << " Safety values: " << G4endl 226 << " DistanceToIn(p) = " << safetyIn << G4endl 227 << " DistanceToOut(p) = " << safetyOut; 228 G4Exception(fType, "GeomNav0003", FatalException, message); 229 } 230 } 231 232 // Verification / verbosity 233 // 234 if ( fVerbose > 1 ) 235 { 236 static const G4int precVerf= 20; // Precision 237 G4long oldprec = G4cout.precision(precVerf); 238 G4cout << "Daughter " 239 << std::setw(12) << sampleSolid->GetName() << " " 240 << std::setw(4+precVerf) << samplePoint << " " 241 << std::setw(4+precVerf) << sampleSafety << " " 242 << std::setw(4+precVerf) << sampleStep << " " 243 << std::setw(16) << "distanceToIn" << " " 244 << std::setw(4+precVerf) << localDirection << " " 245 << G4endl; 246 G4cout.precision(oldprec); 247 } 248 } 249 } 250 251 // ******************************************************************** 252 // CheckDaughterEntryPoint 253 // ******************************************************************** 254 // 255 void 256 G4NavigationLogger::CheckDaughterEntryPoint(const G4VSolid* sampleSolid, 257 const G4ThreeVector& samplePoint, 258 const G4ThreeVector& sampleDirection, 259 const G4VSolid* motherSolid, 260 const G4ThreeVector& localPoint, 261 const G4ThreeVector& localDirection, 262 G4double motherStep, 263 G4double sampleStep) const 264 { 265 const G4double kCarTolerance = motherSolid->GetTolerance(); 266 267 // Double check the expected condition of being called 268 // 269 G4bool SuspiciousDaughterDist = ( sampleStep >= motherStep ) 270 && ( sampleStep < kInfinity ); 271 272 if( sampleStep >= kInfinity ) 273 { 274 G4ExceptionDescription msg; 275 msg.precision(12); 276 msg << " WARNING - Called with 'infinite' step. " << G4endl; 277 msg << " Checks have no meaning if daughter step is infinite." << G4endl; 278 msg << " kInfinity = " << kInfinity / millimeter << G4endl; 279 msg << " sampleStep = " << sampleStep / millimeter << G4endl; 280 msg << " sampleStep < kInfinity " << (sampleStep<kInfinity) << G4endl; 281 msg << " kInfinity - sampleStep " << (kInfinity-sampleStep) / millimeter << G4endl; 282 msg << " Returning immediately."; 283 G4Exception("G4NavigationLogger::CheckDaughterEntryPoint()", 284 "GeomNav0003", JustWarning, msg); 285 return; 286 } 287 288 // The intersection point with the daughter is after the exit point 289 // from the mother volume !! 290 // This is legal / allowed to occur only if the mother is concave 291 // **************************************************************** 292 // If mother is convex the daughter volume must be encountered 293 // before the exit from the current volume! 294 295 // Check #1) whether the track will re-enter the current mother 296 // in the extension past its current exit point 297 G4ThreeVector localExitMotherPos = localPoint+motherStep*localDirection; 298 G4double distExitToReEntry = motherSolid->DistanceToIn(localExitMotherPos, 299 localDirection); 300 301 // Check #2) whether the 'entry' point in the daughter is inside the mother 302 // 303 G4ThreeVector localEntryInDaughter = localPoint+sampleStep*localDirection; 304 EInside insideMother = motherSolid->Inside( localEntryInDaughter ); 305 306 G4String solidResponse = "-kInside-"; 307 if (insideMother == kOutside) { solidResponse = "-kOutside-"; } 308 else if (insideMother == kSurface) { solidResponse = "-kSurface-"; } 309 310 G4double distToReEntry = distExitToReEntry + motherStep; 311 G4ThreeVector localReEntryPoint = localPoint+distToReEntry*localDirection; 312 313 // Clear error -- Daughter entry point is bad 314 constexpr G4double eps= 1.0e-10; 315 G4bool DaughterEntryIsOutside = SuspiciousDaughterDist 316 && ( (sampleStep * (1.0+eps) < distToReEntry) || (insideMother == kOutside ) ); 317 G4bool EntryIsMotherExit = std::fabs(sampleStep-motherStep) < kCarTolerance; 318 319 // Check for more subtle error - is exit point of daughter correct ? 320 G4ThreeVector sampleEntryPoint = samplePoint+sampleStep*sampleDirection; 321 G4double sampleCrossingDist = sampleSolid->DistanceToOut( sampleEntryPoint, 322 sampleDirection ); 323 G4double sampleExitDist = sampleStep+sampleCrossingDist; 324 G4ThreeVector sampleExitPoint = samplePoint+sampleExitDist*sampleDirection; 325 326 G4bool TransitProblem = ( (sampleStep < motherStep) 327 && (sampleExitDist > motherStep + kCarTolerance) ) 328 || ( EntryIsMotherExit && (sampleCrossingDist > kCarTolerance) ); 329 330 if( DaughterEntryIsOutside 331 || TransitProblem 332 || (SuspiciousDaughterDist && (fVerbose > 3) ) ) 333 { 334 G4ExceptionDescription msg; 335 msg.precision(16); 336 337 if( DaughterEntryIsOutside ) 338 { 339 msg << "WARNING> Intersection distance to Daughter volume is further" 340 << " than the distance to boundary." << G4endl 341 << " It appears that part of the daughter volume is *outside*" 342 << " this mother. " << G4endl; 343 msg << " One of the following checks signaled a problem:" << G4endl 344 << " -sampleStep (dist to daugh) < mother-exit dist + distance " 345 << "to ReEntry point for mother " << G4endl 346 << " -position of daughter intersection is outside mother volume." 347 << G4endl; 348 } 349 else if( TransitProblem ) 350 { 351 G4double protrusion = sampleExitDist - motherStep; 352 353 msg << "WARNING> Daughter volume extends beyond mother boundary. " 354 << G4endl; 355 if ( ( sampleStep < motherStep ) 356 && (sampleExitDist > motherStep + kCarTolerance ) ) 357 { 358 // 1st Issue with Daughter 359 msg << " Crossing distance in the daughter causes is to extend" 360 << " beyond the mother exit. " << G4endl; 361 msg << " Length protruding = " << protrusion << G4endl; 362 } 363 if( EntryIsMotherExit ) 364 { 365 // 1st Issue with Daughter 366 msg << " Intersection distance to Daughter is within " 367 << " tolerance of the distance" << G4endl; 368 msg << " to the mother boundary * and * " << G4endl; 369 msg << " the crossing distance in the daughter is > tolerance." 370 << G4endl; 371 } 372 } 373 else 374 { 375 msg << "NearMiss> Intersection to Daughter volume is in extension past the" 376 << " current exit point of the mother volume." << G4endl; 377 msg << " This is not an error - just an unusual occurrence," 378 << " possible in the case of concave volume. " << G4endl; 379 } 380 msg << "---- Information about intersection with daughter, mother: " 381 << G4endl; 382 msg << " sampleStep (daughter) = " << sampleStep << G4endl 383 << " motherStep = " << motherStep << G4endl 384 << " distToRentry(mother) = " << distToReEntry << G4endl 385 << " Inside(entry pnt daug): " << solidResponse << G4endl 386 << " dist across daughter = " << sampleCrossingDist << G4endl; 387 msg << " Mother Name (Solid) : " << motherSolid->GetName() << G4endl 388 << " In local (mother) coordinates: " << G4endl 389 << " Starting Point = " << localPoint << G4endl 390 << " Direction = " << localDirection << G4endl 391 << " Exit Point (mother)= " << localExitMotherPos << G4endl 392 << " Entry Point (daughter)= " << localPoint+sampleStep*localDirection 393 << G4endl; 394 if( distToReEntry < kInfinity ) 395 { 396 msg << " ReEntry Point (mother)= " << localReEntryPoint << G4endl; 397 } 398 else 399 { 400 msg << " No ReEntry - track does not encounter mother volume again! " 401 << G4endl; 402 } 403 msg << " Daughter Name (Solid): " << sampleSolid->GetName() << G4endl 404 << " In daughter coordinates: " << G4endl 405 << " Starting Point = " << samplePoint << G4endl 406 << " Direction = " << sampleDirection << G4endl 407 << " Entry Point (daughter)= " << sampleEntryPoint 408 << G4endl; 409 msg << " Description of mother solid: " << G4endl 410 << *motherSolid << G4endl 411 << " Description of daughter solid: " << G4endl 412 << *sampleSolid << G4endl; 413 G4String fType = fId + "::ComputeStep()"; 414 415 if( DaughterEntryIsOutside || TransitProblem ) 416 { 417 G4Exception(fType, "GeomNav0003", JustWarning, msg); 418 } 419 else 420 { 421 G4cout << fType 422 << " -- Checked distance of Entry to daughter vs exit of mother" 423 << G4endl; 424 G4cout << msg.str(); 425 G4cout << G4endl; 426 } 427 } 428 } 429 430 // ******************************************************************** 431 // PostComputeStepLog 432 // ******************************************************************** 433 // 434 void 435 G4NavigationLogger::PostComputeStepLog(const G4VSolid* motherSolid, 436 const G4ThreeVector& localPoint, 437 const G4ThreeVector& localDirection, 438 G4double motherStep, 439 G4double motherSafety) const 440 { 441 if ( fVerbose == 1 || fVerbose > 4 ) 442 { 443 G4cout << " Mother " 444 << std::setw(15) << motherSafety << " " 445 << std::setw(15) << motherStep << " " << localPoint << " - " 446 << motherSolid->GetEntityType() << ": " << motherSolid->GetName() 447 << G4endl; 448 } 449 if( ( motherStep < 0.0 ) || ( motherStep >= kInfinity) ) 450 { 451 G4String fType = fId + "::ComputeStep()"; 452 G4long oldPrOut = G4cout.precision(16); 453 G4long oldPrErr = G4cerr.precision(16); 454 std::ostringstream message; 455 message << "Current point is outside the current solid !" << G4endl 456 << " Problem in Navigation" << G4endl 457 << " Point (local coordinates): " 458 << localPoint << G4endl 459 << " Local Direction: " << localDirection << G4endl 460 << " Solid: " << motherSolid->GetName(); 461 motherSolid->DumpInfo(); 462 G4Exception(fType, "GeomNav0003", FatalException, message); 463 G4cout.precision(oldPrOut); 464 G4cerr.precision(oldPrErr); 465 } 466 if ( fVerbose > 1 ) 467 { 468 static const G4int precVerf = 20; // Precision 469 G4long oldprec = G4cout.precision(precVerf); 470 G4cout << " Mother " << std::setw(12) << motherSolid->GetName() << " " 471 << std::setw(4+precVerf) << localPoint << " " 472 << std::setw(4+precVerf) << motherSafety << " " 473 << std::setw(4+precVerf) << motherStep << " " 474 << std::setw(16) << "distanceToOut" << " " 475 << std::setw(4+precVerf) << localDirection << " " 476 << G4endl; 477 G4cout.precision(oldprec); 478 } 479 } 480 481 // ******************************************************************** 482 // ComputeSafetyLog 483 // ******************************************************************** 484 // 485 void 486 G4NavigationLogger::ComputeSafetyLog(const G4VSolid* solid, 487 const G4ThreeVector& point, 488 G4double safety, 489 G4bool isMotherVolume, 490 G4int banner) const 491 { 492 if( banner < 0 ) 493 { 494 banner = static_cast<G4int>(isMotherVolume); 495 } 496 if( fVerbose >= 1 ) 497 { 498 G4String volumeType = isMotherVolume ? " Mother " : "Daughter"; 499 if (banner != 0) 500 { 501 G4cout << "************** " << fId << "::ComputeSafety() ****************" 502 << G4endl; 503 G4cout << " VolType " 504 << std::setw(15) << "Safety/mm" << " " 505 << std::setw(52) << "Position (local coordinates)" 506 << " - Solid" << G4endl; 507 } 508 G4cout << volumeType 509 << std::setw(15) << safety << " " << point << " - " 510 << solid->GetEntityType() << ": " << solid->GetName() << G4endl; 511 } 512 } 513 514 // ******************************************************************** 515 // PrintDaughterLog 516 // ******************************************************************** 517 // 518 void 519 G4NavigationLogger::PrintDaughterLog (const G4VSolid* sampleSolid, 520 const G4ThreeVector& samplePoint, 521 G4double sampleSafety, 522 G4bool withStep, 523 const G4ThreeVector& sampleDirection, G4double sampleStep ) const 524 { 525 if ( fVerbose >= 1 ) 526 { 527 G4long oldPrec = G4cout.precision(8); 528 G4cout << "Daughter " 529 << std::setw(15) << sampleSafety << " "; 530 if (withStep) // (sampleStep != -1.0 ) 531 { 532 G4cout << std::setw(15) << sampleStep << " "; 533 } 534 else 535 { 536 G4cout << std::setw(15) << "Not-Available" << " "; 537 } 538 G4cout << samplePoint << " - " 539 << sampleSolid->GetEntityType() << ": " << sampleSolid->GetName(); 540 if( withStep ) 541 { 542 G4cout << " dir= " << sampleDirection; 543 } 544 G4cout << G4endl; 545 G4cout.precision(oldPrec); 546 } 547 } 548 549 // ******************************************************************** 550 // CheckAndReportBadNormal 551 // ******************************************************************** 552 // 553 G4bool 554 G4NavigationLogger:: 555 CheckAndReportBadNormal(const G4ThreeVector& unitNormal, 556 const G4ThreeVector& localPoint, 557 const G4ThreeVector& localDirection, 558 G4double step, 559 const G4VSolid* solid, 560 const char* msg ) const 561 { 562 G4double normMag2 = unitNormal.mag2(); 563 G4bool badLength = ( std::fabs ( normMag2 - 1.0 ) > CLHEP::perMillion ); 564 565 if( badLength ) 566 { 567 G4double normMag = std::sqrt(normMag2); 568 G4ExceptionDescription message; 569 message.precision(10); 570 message << "============================================================" 571 << G4endl; 572 message << " WARNING> Normal is not a unit vector. " 573 << " - but |normal| = " << normMag 574 << " - and |normal|^2 = " << normMag2 << G4endl 575 << " which differ from 1.0 by: " << G4endl 576 << " |normal|-1 = " << normMag - 1.0 577 << " and |normal|^2 - 1 = " << normMag2 - 1.0 << G4endl 578 << " n = " << unitNormal << G4endl; 579 message << " Info string: " << msg << G4endl; 580 message << "============================================================" 581 << G4endl; 582 583 message.precision(16); 584 585 message << " Information on call to DistanceToOut: " << G4endl; 586 message << " Position = " << localPoint << G4endl 587 << " Direction = " << localDirection << G4endl; 588 message << " Obtained> distance = " << step << G4endl; 589 message << " > Exit position = " << localPoint+step*localDirection 590 << G4endl; 591 message << " Parameters of solid: " << G4endl; 592 message << *solid; 593 message << "============================================================"; 594 595 G4String fMethod = fId + "::ComputeStep()"; 596 G4Exception( fMethod, "GeomNav0003", JustWarning, message); 597 } 598 return badLength; 599 } 600 601 // ******************************************************************** 602 // CheckAndReportBadNormal - due to Rotation Matrix 603 // ******************************************************************** 604 // 605 G4bool 606 G4NavigationLogger:: 607 CheckAndReportBadNormal(const G4ThreeVector& rotatedNormal, 608 const G4ThreeVector& originalNormal, 609 const G4RotationMatrix& rotationM, 610 const char* msg ) const 611 { 612 G4double normMag2 = rotatedNormal.mag2(); 613 G4bool badLength = ( std::fabs ( normMag2 - 1.0 ) > CLHEP::perMillion ); 614 615 if( badLength ) 616 { 617 G4double normMag = std::sqrt(normMag2); 618 G4ExceptionDescription message; 619 message.precision(10); 620 message << "============================================================" 621 << G4endl; 622 message << " WARNING> Rotated n(ormal) is not a unit vector. " << G4endl 623 << " |normal| = " << normMag 624 << " and |normal|^2 = " << normMag2 << G4endl 625 << " Diff from 1.0: " << G4endl 626 << " |normal|-1 = " << normMag - 1.0 627 << " and |normal|^2 - 1 = " << normMag2 - 1.0 << G4endl; 628 message << " Rotated n = (" << rotatedNormal.x() << "," << rotatedNormal.y() << "," 629 << rotatedNormal.z() << ")" << G4endl; 630 message << " Original n = (" << originalNormal.x() << "," << originalNormal.y() << "," 631 << originalNormal.z() << ")" << G4endl; 632 message << " Info string: " << msg << G4endl; 633 message << "============================================================" 634 << G4endl; 635 636 message.precision(16); 637 638 message << " Information on RotationMatrix : " << G4endl; 639 message << " Original: " << G4endl; 640 message << rotationM << G4endl; 641 message << " Inverse (used in transformation): " << G4endl; 642 message << rotationM.inverse() << G4endl; 643 message << "============================================================"; 644 645 G4String fMethod = fId + "::ComputeStep()"; 646 G4Exception( fMethod, "GeomNav0003", JustWarning, message); 647 } 648 return badLength; 649 } 650 651 // ******************************************************************** 652 // ReportOutsideMother 653 // ******************************************************************** 654 // 655 // Report Exception if point is outside mother. 656 // Fatal exception will be used if either 'checkMode error is > triggerDist 657 // 658 void 659 G4NavigationLogger::ReportOutsideMother(const G4ThreeVector& localPoint, 660 const G4ThreeVector& localDirection, 661 const G4VPhysicalVolume* physical, 662 G4double triggerDist) const 663 { 664 const G4LogicalVolume* logicalVol = physical != nullptr 665 ? physical->GetLogicalVolume() : nullptr; 666 const G4VSolid* solid = logicalVol != nullptr 667 ? logicalVol->GetSolid() : nullptr; 668 669 G4String fMethod = fId + "::ComputeStep()"; 670 671 if( solid == nullptr ) 672 { 673 G4Exception(fMethod, "GeomNav0003", FatalException, 674 "Erroneous call to ReportOutsideMother: no Solid is available"); 675 return; 676 } 677 const G4double kCarTolerance = solid->GetTolerance(); 678 679 // Double check reply - it should be kInfinity 680 const G4double distToOut = solid->DistanceToOut(localPoint, localDirection); 681 const EInside inSolid = solid->Inside(localPoint); 682 const G4double safetyToIn = solid->DistanceToIn(localPoint); 683 const G4double safetyToOut = solid->DistanceToOut(localPoint); 684 // const G4double distToInPos = 685 // solid->DistanceToIn(localPoint, localDirection); 686 687 // 1. Check consistency between Safety obtained and report from distance 688 // We must ensure that (mother)Safety <= 0.0 689 // in the case that the point is outside! 690 // [ If this is not the case, this problem can easily go undetected, 691 // except in Check mode ! ] 692 if( safetyToOut > kCarTolerance 693 && ( distToOut < 0.0 || distToOut >= kInfinity ) ) 694 { 695 G4ExceptionDescription msg1; 696 // fNavClerk->ReportBadSafety(localPoint, localDirection, 697 // motherPhysical, motherSafety, motherStep); 698 msg1 << " Dangerous inconsistency in response of solid." << G4endl 699 << " Solid type: " << solid->GetEntityType() 700 << " Name= " << solid->GetName() << G4endl; 701 msg1 << " Mother volume gives safety > 0 despite being called for *Outside* point " 702 << G4endl 703 << " Location = " << localPoint << G4endl 704 << " Direction= " << localDirection << G4endl 705 << " - Safety (Isotropic d) = " << safetyToOut << G4endl 706 << " - Intersection Distance= " << distToOut << G4endl 707 << G4endl; 708 G4Exception( fMethod, "GeomNav0123", JustWarning, msg1); 709 } 710 711 // 2. Inconsistency - Too many distances are zero (or will be rounded to zero) 712 713 // if( std::fabs(distToOut) < kCarTolerance 714 // && std::fabs(distToInPos) < kCarTolerance ) 715 // { 716 // If both distanceToIn and distanceToOut (p,v) are zero for 717 // one direction, the particle could get stuck! 718 // } 719 720 G4ExceptionDescription msg; 721 msg.precision(10); 722 723 if( std::fabs(distToOut) < kCarTolerance ) 724 { 725 // 3. Soft error - safety is not rounded to zero 726 // Report nothing - except in 'loud' mode 727 if( fReportSoftWarnings ) 728 { 729 msg << " Warning> DistanceToOut(p,v): " 730 << "Distance from surface is not rounded to zero" << G4endl; 731 } 732 else 733 { 734 return; 735 } 736 } 737 else 738 { 739 // 4. General message - complain that the point is outside! 740 // and provide all information about the current location, 741 // direction and the answers of the solid 742 msg << "============================================================" 743 << G4endl; 744 msg << " WARNING> Current Point appears to be Outside mother volume !! " 745 << G4endl; 746 msg << " Response of DistanceToOut was negative or kInfinity" 747 << " when called in " << fMethod << G4endl; 748 } 749 750 // Generate and 'print'/stream all the information needed 751 this->ReportVolumeAndIntersection(msg, localPoint, localDirection, physical); 752 753 // Default for distance of 'major' error 754 if( triggerDist <= 0.0 ) 755 { 756 triggerDist = std::max ( 1.0e+6 * kCarTolerance, // Well beyond tolerance 757 fMinTriggerDistance ); 758 } 759 760 G4bool majorError = inSolid == kOutside 761 ? ( safetyToIn > triggerDist ) 762 : ( safetyToOut > triggerDist ); 763 764 G4ExceptionSeverity exceptionType = JustWarning; 765 if ( majorError ) 766 { 767 exceptionType = FatalException; 768 } 769 770 G4Exception( fMethod, "GeomNav0003", exceptionType, msg); 771 } 772 773 namespace G4NavigationLogger_Namespace 774 { 775 const G4String EInsideNames[3] = { "kOutside", "kSurface", "kInside" }; 776 } 777 778 void G4NavigationLogger:: 779 ReportVolumeAndIntersection( std::ostream& os, 780 const G4ThreeVector& localPoint, 781 const G4ThreeVector& localDirection, 782 const G4VPhysicalVolume* physical ) const 783 { 784 G4String fMethod = fId + "::ComputeStep()"; 785 const G4LogicalVolume* logicalVol = physical != nullptr 786 ? physical->GetLogicalVolume() : nullptr; 787 const G4VSolid* solid = logicalVol != nullptr 788 ? logicalVol->GetSolid() : nullptr; 789 if( solid == nullptr ) 790 { 791 os << " ERROR> Solid is not available. Logical Volume = " 792 << logicalVol << std::endl; 793 return; 794 } 795 const G4double kCarTolerance = solid->GetTolerance(); 796 797 // Double check reply - it should be kInfinity 798 const G4double distToOut = solid->DistanceToOut(localPoint, localDirection); 799 const G4double distToOutNeg = solid->DistanceToOut(localPoint, 800 -localDirection); 801 const EInside inSolid = solid->Inside(localPoint); 802 const G4double safetyToIn = solid->DistanceToIn(localPoint); 803 const G4double safetyToOut = solid->DistanceToOut(localPoint); 804 805 const G4double distToInPos = solid->DistanceToIn(localPoint, localDirection); 806 const G4double distToInNeg = solid->DistanceToIn(localPoint, -localDirection); 807 808 const G4ThreeVector exitNormal = solid->SurfaceNormal(localPoint); 809 810 // Double check whether points nearby are in/surface/out 811 const G4double epsilonDist = 1000.0 * kCarTolerance; 812 const G4ThreeVector PointPlusDir = localPoint + epsilonDist * localDirection; 813 const G4ThreeVector PointMinusDir = localPoint - epsilonDist * localDirection; 814 const G4ThreeVector PointPlusNorm = localPoint + epsilonDist * exitNormal; 815 const G4ThreeVector PointMinusNorm = localPoint - epsilonDist * exitNormal; 816 817 const EInside inPlusDir = solid->Inside(PointPlusDir); 818 const EInside inMinusDir = solid->Inside(PointMinusDir); 819 const EInside inPlusNorm = solid->Inside(PointPlusNorm); 820 const EInside inMinusNorm = solid->Inside(PointMinusNorm); 821 822 // Basic information 823 os << " Current physical volume = " << physical->GetName() << G4endl; 824 os << " Position (loc) = " << localPoint << G4endl 825 << " Direction (dir) = " << localDirection << G4endl; 826 os << " For confirmation:" << G4endl; 827 os << " Response of DistanceToOut (loc, +dir)= " << distToOut << G4endl; 828 os << " Response of DistanceToOut (loc, -dir)= " << distToOutNeg << G4endl; 829 830 os << " Inside responds = " << inSolid << " , ie: "; 831 if( inSolid == kOutside ) 832 { 833 os << " Outside -- a problem, as observed in " << fMethod << G4endl; 834 } 835 else if( inSolid == kSurface ) 836 { 837 os << " Surface -- unexpected / inconsistent response ! " << G4endl; 838 } 839 else 840 { 841 os << " Inside -- unexpected / inconsistent response ! " << G4endl; 842 } 843 os << " Obtain safety(ToIn) = " << safetyToIn << G4endl; 844 os << " Obtain safety(ToOut) = " << safetyToOut << G4endl; 845 os << " Response of DistanceToIn (loc, +dir)= " << distToInPos << G4endl; 846 os << " Response of DistanceToIn (loc, -dir)= " << distToInNeg << G4endl; 847 848 os << " Exit Normal at loc = " << exitNormal << G4endl; 849 os << " Dir . Normal = " << exitNormal.dot( localDirection ); 850 os << G4endl; 851 852 os << " Checking points moved from position by distance/direction." << G4endl 853 << " Solid responses: " << G4endl 854 << " +eps in direction : " 855 << G4NavigationLogger_Namespace::EInsideNames[inPlusDir] 856 << " +eps in Normal : " 857 << G4NavigationLogger_Namespace::EInsideNames[inPlusNorm] << G4endl 858 << " -eps in direction : " 859 << G4NavigationLogger_Namespace::EInsideNames[inMinusDir] 860 << " -eps in Normal : " 861 << G4NavigationLogger_Namespace::EInsideNames[inMinusNorm] << G4endl; 862 863 os << " Parameters of solid: " << G4endl; 864 os << *solid; 865 os << "============================================================"; 866 } 867