Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/navigation/src/G4NavigationLogger.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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