Opticks Presentations, Refs
Details in above presentations + notes : https://bitbucket.org/simoncblyth/opticks/src/master/notes/progress.rst
JUNO ISSUES
NNVT : MaskTail impinges MaskVirtual
HAMA : BodySolid impinges MaskTail
BirksConstant1 : 1,000,000x TOO BIG
OPTICKS PRIM ISSUES
nmskSolidMask : ellipsoid hole at "apex" issue
nmskSolidMaskTail : very thin cylinder "lip" issues
nmskSolidMaskVirtual : cone precision + near-apex issues
https://simoncblyth.bitbucket.io/env/presentation/opticks_20221117_mask_debug_and_tmm.html
NNVT : ONE overlap issue visible, MaskTail impinges MaskVirtual
(using ct.sh : Opticks CSG on CPU)
HAMA : ONE overlap issue, BodySolid impinges MaskTail
(using ct.sh : Opticks CSG on CPU)
HAMA : BodySolid impinges MaskTail (mct.sh)
HAMA : after bug 33 fix
junosw/Simulation/SimSvc/MultiFilmSimSvc
epsilon:MultiFilmSimSvc blyth$ find . -type f ./CMakeLists.txt ./python/MultiFilmSimSvc/__init__.py ./MultiFilmSimSvc/MultiFilmModel.h ./src/OpticalSystem.h ./src/Layer.h ./src/Material.h ./src/Layer.cc ## Layer, ThickLayer, ThinLayer ./src/Matrix.h ./src/OpticalSystem.cc ./src/MultiFilmModel.cc ./src/Material.cc ./src/Matrix.cc
CPU/GPU : using complex
#ifdef WITH_THRUST using thrust::complex ; //GPU #else using std::complex ; //CPU #endif // same complex TMM math on CPU/GPU
template<typename T> struct Layr { T d, pad ; // d:thickness : zero means incoherent #ifdef WITH_THRUST thrust::complexn, st, ct, rs, rp, ts, tp ; #else std::complex n, st, ct, rs, rp, ts, tp ; #endif Matx S, P ; }; template <typename T, int N> struct Stack { Layr<T> ll[N] ; // stack of N layers Layr<T> comp ; // composite for the N layers ART_<T> art ; // results eg A,R,T Stack(T wl, T minus_cos_theta, const StackSpec<T>& ss); };
https://github.com/simoncblyth/j/blob/main/Layr/Layr.h
ALT: multi-GB "ART" textures (Yuxiang Hu) TODO: compare
Impl: arrays of simple struct
epsilon:Layr blyth$ ./LayrTest.sh ana
CFLayrTest
a : EGet : scan__EGet__cpu_thr_double
b : EGet : scan__EGet__cpu_thr_float
c : EGet : scan__EGet__gpu_thr_double
d : EGet : scan__EGet__gpu_thr_float
...
m : R12860 : scan__R12860__cpu_pom_double
n : R12860 : scan__R12860__cpu_thr_double
o : R12860 : scan__R12860__cpu_thr_float
p : R12860 : scan__R12860__gpu_thr_double
q : R12860 : scan__R12860__gpu_thr_float
In [1]: CF(m,q,0.05)
Out[1]:
CF(m,q,0.05) : scan__R12860__cpu_pom_double vs scan__R12860__gpu_thr_float
lls : 0.000442 : 0.000442 : -0.000414
comps : 0.000341 : 0.000341 : -6.17e-05
arts : 6.2e-05 : 6.2e-05 : -6.2e-05
pmtcat:R12860 tt:5 lt:q : j/Layr/LayrTest scan__R12860__gpu_thr_float ni 900 wl 440
+------------------------------+----------+----------+----------+----------+----------+
| R12860 arts\comps 0.05| m:cpd| n:ctd| o:ctf| p:gtd| q:gtf|
+==============================+==========+==========+==========+==========+==========+
| m:cpd| 0| 0.0003325| 0.000301| 0.0003325| 0.0003407|
+------------------------------+----------+----------+----------+----------+----------+ max difference of all param between scans
| n:ctd| 6.064e-05| 0| 4.829e-05| 7.445e-14| 4.829e-05|
+------------------------------+----------+----------+----------+----------+----------+
| o:ctf| 5.454e-05| 6.101e-06| 0| 4.829e-05| 3.977e-05|
+------------------------------+----------+----------+----------+----------+----------+
| p:gtd| 6.064e-05| 1.321e-14| 6.101e-06| 0| 4.829e-05|
+------------------------------+----------+----------+----------+----------+----------+
| q:gtf| 6.199e-05| 1.523e-06| 7.451e-06| 1.523e-06| 0|
+------------------------------+----------+----------+----------+----------+----------+
In [1]: ARTPlot(m, 0.05)
S/P-Pol : perp./within plane
S/P Polarization : has huge effect on A,R,T in both directions : AOI > 90 is reversed stack
4 : A
Absorption : large S/P-polarization difference in both directions
4 : R
Only reflection at glancing incidence (90 deg) : large S/P-pol. difference for Vacuum->Pyrex
4 : T
Pyrex->Vacuum : Above critical angle : no transmission, only reflect or absorb
Standalone Advantages
https://github.com/simoncblyth/j/ |
https://bitbucket.org/simoncblyth/opticks/ |
"CustomG4OpBoundaryProcess" FIX
opticks:u4/InstrumentedG4OpBoundaryProcess.cc
j:PMTFastSim Standalone PMT geometry and Optical Model
Optical only Geant4 simulation, with full step point recording
N=0/1 ./U4SimulateTest.sh
Geant4 Simtrace intersection : 2D geometry plotting
N=0/1 ./U4SimtraceTest.sh
CustomG4OpBoundaryProcess ?
BUT : need to change very nasty Geant4 impl:
inline sboundary::sboundary():
_E2_t(make_float2( 2.f*n1c1/(n1c1+n2c2) , 2.f*n1c1/(n2c1+n1c2) )),// (ts,tp) _E2_r(make_float2( _E2_t.x - 1.f , n2*_E2_t.y/n1 - 1.f )),// (rs,rp) A_transverse(cross(p.mom, orient*normal)), E1_perp(dot(p.pol, A_transverse)), E1(make_float2(E1_perp,sqrtf(1.f-E1_perp*E1_perp)))), E2_t(_E2_t*E1),RR(normalize(E2_r)), E2_r(_E2_r*E1),TT(normalize(E2_t)), { p.mom = reflect ? p.mom + 2.0f*c1*orient*normal : eta*(p.mom) + (eta*c1 - c2)*orient*normal ; A_parallel = normalize(cross(p.mom, A_transverse)); p.pol = ( reflect ? ( tir ? -p.pol + 2.f*EdotN*orient*normal : RR.x*A_transverse + RR.y*A_parallel ) : TT.x*A_transverse + TT.y*A_parallel ) ; } // IMPL BASED ON + VALIDATED AGAINST GEANT4
Reflect/Refract : INCORRECT POLARIZATION
void junoPMTOpticalModel::Reflect() { dir -= 2.*(dir*norm)*norm; pol -= 2.*(pol*norm)*norm; } void junoPMTOpticalModel::Refract() { dir = (real(_cos_theta4) - _cos_theta1*_n1/_n4)*norm + (_n1/_n4)*dir; pol = (pol-(pol*dir)*dir).unit(); }
G4OpBoundaryProcess polarization from:
Opticks : sysrap/sboundary.h qudarap/qsim.h follows G4, ===>
Derive Fresnel from Maxwell Boundary Conditions
G4OpBoundaryProcess/qsim.h/sboundary.h : Only S-polarized survives | junoPMTOpticalModel::Reflect : very different |
Brewster (or polarizing) incident angle th1 : tan(th1) = n2/n1 ; th1 + th2 = pi/2
G4OpBoundaryProcess/qsim.h/sboundary.h : partial pol | junoPMTOpticalModel::Refract : not partially pol |
Natural 2-volume PMT (Pyrex + Vacuum) : NOT COMPATIBLE WITH FastSim
body hidden under inner1 inner2
body is FastSim envelope volume
CURRENT : Unnatural 4-volume PMT (Pyrex+Pyrex+Vacuum+Vacuum) => Half Fake
Current MultiLayer POM
+---------------pmt-Pyrex----------------+ | | | | | +----body-Pyrex-(FSim-env)---+ | | | +------------------------+ | | | | | | | | | | | | | | | | | inner1-Vacuum |-| | | | | |1e-3 | | | | | | | | | +~~coincident~face~~~~~~~+ | | | | | | | | | | | | | | | | | inner2-Vacuum | | | | | | | | | | | | | | | | | +------------------------+ | | | +----------------------------+ | | | | | +----------------------------------------+
80 G4bool junoPMTOpticalModel::ModelTrigger(const G4FastTrack &fastTrack)
81 { // Contorted as "pre-trigger" on where next
83 if(fastTrack.GetPrimaryTrack()->GetVolume() == _inner2_phys){
84 return false;
85 }
...
89 pos = fastTrack.GetPrimaryTrackLocalPosition();
90 dir = fastTrack.GetPrimaryTrackLocalDirection();
94
95 if(fastTrack.GetPrimaryTrack()->GetVolume() == _inner1_phys){
96 whereAmI = kInVacuum;
97 }else{
98 whereAmI = kInGlass;
99 }
100
101 if(whereAmI == kInGlass){
102 dist1 = _inner1_solid->DistanceToIn(pos, dir);
103 dist2 = _inner2_solid->DistanceToIn(pos, dir);
104
105 if(dist1 == kInfinity){
106 return false;
107 }else if(dist1>dist2){
108 return false;
109 }else{
110 return true;
111 }
112 }else{
113 dist1 = _inner1_solid->DistanceToOut(pos, dir);
114 dist2 = _inner2_solid->DistanceToIn(pos, dir);
115
116 if(dist2 == kInfinity){
117 return true;
118 }
119 }
120 return false;
121 }
Simplified MultiLayer POM
+---------------pmt-Pyrex----------------+ | | | | | | | +~inner~Vacuum~(FSim~env)+ | | ! ! | | ! ! | | ! ! | | ! ! | | ! ! | | + + | | | | | | | | | | | | | | | | | | | | | | +------------------------+ | | | | | | | +----------------------------------------+
G4bool junoPMTOpticalModelSimple::ModelTrigger(
const G4FastTrack &fastTrack)
{
// Simple + Cheap due to natural geometry
return fastTrack.GetPrimaryTrackLocalPosition().z() > 0. ;
}
https://github.com/simoncblyth/j/blob/main/PMTFastSim/junoPMTOpticalModelSimple.cc
Simplified MultiLayer POM
+---------------pmt-Pyrex----------------+ | | | | | | | +~inner~Vacuum~(FSim~env)+ | | ! ! | | ! ! | | ! ! | | ! ! | | ! ! | | + + | | | | | | | | | | | | | | | | | | | | | | +------------------------+ | | | | | | | +----------------------------------------+
void junoPMTOpticalModelSimple::DoIt(const G4FastTrack& fastTrack, G4FastStep &fastStep) { G4double energy = fastTrack.GetPrimaryTrack()->GetKineticEnergy(); wavelength_nm = twopi*hbarc/energy/nm ; position = fastTrack.GetPrimaryTrackLocalPosition(); direction = fastTrack.GetPrimaryTrackLocalDirection(); polarization = fastTrack.GetPrimaryTrackLocalPolarization(); G4VSolid* envelope_solid = fastTrack.GetEnvelopeSolid(); surface_normal = envelope_solid->SurfaceNormal(position); minus_cos_theta = direction*surface_normal ; whereAmI = minus_cos_theta < 0. ? kInGlass : kInVacuum ; StackSpecspec ; // ... skip : collect refractive indices, thickness into spec ... Stack stack( wavelength_nm, minus_cos_theta, spec ); Stack stackNormal(wavelength_nm, -1. , spec ); // ... }
Custom Boundary POM
+---------------pmt-Pyrex----------------+ | | | | | | | +~inner~Vacuum~~~~~~~~~~~+ | | ! ! | | ! ! | | ! ! | | ! ! | | ! ! | | + + | | | | | | | | | | | | | | | | | | | | | | +------------------------+ | | | | | | | +----------------------------------------+
OpSurfaceName[0] == '@'
Custom Boundary Process : Advantages
Current FastSim POM | 4 Solid, 4 LV, 4 PV |
Custom Boundary POM | 2 Solid, 2 LV, 2 PV |
Disadvantages
Advantages far outweigh disadvantages
CustomART::maybe_doIt
inline char CustomART::maybe_doIt( const char* OpticalSurfaceName, const G4Track& aTrack, const G4Step& aStep ) { if( OpticalSurfaceName == nullptr || OpticalSurfaceName[0] != '@') return 'N' ; const G4AffineTransform& transform = aTrack.GetTouchable() ->GetHistory()->GetTopTransform(); G4ThreeVector localPoint = transform.TransformPoint(theGlobalPoint); if(localPoint.z() <= 0) return 'Z' ; return doIt(aTrack, aStep) ; }
doIt TMM calc, runs only for:
#include "IPMTAccessor.h" #include "Layr.h" #include "U4Touchable.h" struct CustomART { const IPMTAccessor* accessor ; // JPMT.h OR PMTAccessor.h G4double& theTransmittance ; // doIt sets these G4double& theReflectivity ; G4double& theEfficiency ; const G4ThreeVector& theGlobalPoint ; const G4ThreeVector& OldMomentum ; const G4ThreeVector& OldPolarization ; const G4ThreeVector& theRecoveredNormal ; const G4double& thePhotonMomentum ; CustomART( const IPMTAccessor* accessor, G4double& theTransmittance, G4double& theReflectivity, G4double& theEfficiency, const G4ThreeVector& theGlobalPoint, const G4ThreeVector& OldMomentum, const G4ThreeVector& OldPolarization, const G4ThreeVector& theRecoveredNormal, const G4double& thePhotonMomentum ); char maybe_doIt(const char* OpticalSurfaceName, const G4Track& aTrack, const G4Step& aStep ); char doIt(const G4Track& aTrack, const G4Step& aStep ); };
opticks/src/master/u4/CustomART.h
TO BT BT BT BT SR SR BT BR BR BT SR SR SR BT BR BT SR BT SA Lots of fakes
00 01 [02] 03 [04] 05 06 [07] 08 09 [10] 11 12 13 [14] 15 [16] 17 [18] 19 (7/20 Fake)
TO BT BT SR SR BR BR SR SR SR BR SR BR SR SA 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 Simpler history, no fakes 00 01 03 05 06 08 09 11 12 13 15 17 19
u4t ; ./U4SimulateTest.sh cf In [12]: np.c_[ar[:,0],np.arange(len(ar)),br[:,0]] Out[12]: array([[-113. , 0. , 200. , 0. , 0. , -113. , 0. , 200. , 0. ], [-113. , 0. , 170.163, 0.137, 1. , -113. , 0. , 170.163, 0.137], [-112.83 , 0. , 164.918, 0.164, 2. , -112.83 , 0. , 164.917, 0.164], [-112.83 , 0. , 164.917, 0.164, 3. , -156.577, 0. , -148.846, 1.22 ], [-135.824, 0. , 0. , 1.012, 4. , -95. , 0. , -104.211, 1.474], [-156.577, 0. , -148.846, 1.778, 5. , -248.807, 0. , 7.28 , 2.108], [ -95. , 0. , -104.211, 2.166, 6. , 53.206, 0. , 180.727, 3.269], [-238.764, 0. , -0. , 3.071, 7. , 245.605, 0. , -35.443, 4.235], [-248.807, 0. , 7.28 , 3.112, 8. , 95. , 0. , -99.428, 4.781], [ 53.205, 0. , 180.727, 4.274, 9. , 177.724, 0. , -134.574, 5.08 ], [ 214.06 , 0. , 0. , 5.507, 10. , 141.059, 0. , 152.451, 6.046], [ 245.605, 0. , -35.443, 5.749, 11. , -239.66 , 0. , -55.195, 7.492], [ 95. , 0. , -99.428, 6.583, 12. , 237.91 , 0. , 54.597, 9.127], [ 177.724, 0. , -134.574, 7.041, 13. , 50. , 0. , -63.74 , 9.867], [ 160.533, 0. , 0. , 7.732, 14. , 58.352, 0. , -69. , 9.9 ], [ 141.059, 0. , 152.451, 8.245, 15. , 0. , 0. , 0. , 0. ], [-138.46 , 0. , 0. , 9.867, 16. , 0. , 0. , 0. , 0. ], [-239.66 , 0. , -55.195, 10.455, 17. , 0. , 0. , 0. , 0. ], [ 0.427, 0. , 0. , 11.71 , 18. , 0. , 0. , 0. , 0. ], [ 237.91 , 0. , 54.596, 12.523, 19. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 20. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 21. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 22. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 23. , 0. , 0. , 0. , 0. ],
ar | a.record[PID] | N=0 current geom | degenerate and fake intersect points |
bb | b.record[PID] | N=1 natural geom | less points, simpler history |
Need point-to-point mapping to compare
u4t ; ./U4SimulateTest.sh cf In [2]: b2a ## point-to-point mapping to skip a fakes Out[2]: array([ 0, 1, 3, 5, 6, 8, 9, 11, 12, 13, 15, 17, 19]) In [4]: abr = np.c_[ar[b2a,0],br[:len(b2a),0],ar[b2a,0]-br[:len(b2a),0]] ; abr Out[4]: array([[-113. , 0. , 200. , 0. , -113. , 0. , 200. , 0. , 0. , 0. , 0. , 0. ], [-113. , 0. , 170.163, 0.137, -113. , 0. , 170.163, 0.137, 0. , 0. , 0. , 0. ], [-112.83 , 0. , 164.917, 0.164, -112.83 , 0. , 164.917, 0.164, 0. , 0. , 0. , -0. ], [-156.577, 0. , -148.846, 1.778, -156.577, 0. , -148.846, 1.22 , -0. , 0. , 0. , 0.558], [ -95. , 0. , -104.211, 2.166, -95. , 0. , -104.211, 1.474, 0. , 0. , 0. , 0.692], [-248.807, 0. , 7.28 , 3.112, -248.807, 0. , 7.28 , 2.108, 0. , 0. , -0. , 1.004], [ 53.205, 0. , 180.727, 4.274, 53.206, 0. , 180.727, 3.269, -0. , 0. , 0. , 1.004], [ 245.605, 0. , -35.443, 5.749, 245.605, 0. , -35.443, 4.235, 0. , 0. , 0. , 1.514], [ 95. , 0. , -99.428, 6.583, 95. , 0. , -99.428, 4.781, 0. , 0. , 0. , 1.802], [ 177.724, 0. , -134.574, 7.041, 177.724, 0. , -134.574, 5.08 , 0. , 0. , 0. , 1.96 ], [ 141.059, 0. , 152.451, 8.245, 141.059, 0. , 152.451, 6.046, -0. , 0. , 0. , 2.199], [-239.66 , 0. , -55.195, 10.455, -239.66 , 0. , -55.195, 7.492, 0. , 0. , 0. , 2.963], [ 237.91 , 0. , 54.596, 12.523, 237.91 , 0. , 54.597, 9.127, 0. , 0. , -0. , 3.397]], dtype=float32)
Positions match closely, some times are way off
rvtime_ = lambda r:np.diff(r[:,0,3]) rvstep_ = lambda r:np.diff(r[:,0,:3],axis=0 ) rvdist_ = lambda r:np.sqrt(np.sum(rvstep_(r)*rvstep_(r),axis=1)) rvspeed_ = lambda r:rvdist_(r)/rvtime_(r) In [14]: np.c_[rvtime_(ar[b2a]), rvtime_(br[:len(b2a)]), rvdist_(ar[b2a]), rvdist_(br[:len(b2a)]), rvspeed_(ar[b2a]),rvspeed_(br[:len(b2a)])]
Out[14]: array([[ 0.137, 0.137, 29.837, 29.837, 218.038, 218.038], ## Water [ 0.027, 0.027, 5.249, 5.249, 196.216, 196.215], ## Pyrex [ 1.615, 1.057, 316.798, 316.798, 196.215, 299.792], ## Vacuum [ 0.388, 0.254, 76.053, 76.053, 196.215, 299.792], [ 0.946, 0.634, 189.965, 189.965, 200.744, 299.792], ## comb. of Vacuum and Pyrex speeds, split at Fake [ 1.162, 1.162, 348.275, 348.275, 299.792, 299.792], [ 1.475, 0.965, 289.392, 289.392, 196.215, 299.792], [ 0.834, 0.546, 163.634, 163.634, 196.215, 299.792], [ 0.458, 0.3 , 89.881, 89.881, 196.215, 299.792], [ 1.204, 0.965, 289.357, 289.357, 240.315, 299.792], ## comb. of Vacuum and Pyrex speeds, split at Fake [ 2.21 , 1.447, 433.663, 433.663, 196.215, 299.792], [ 2.068, 1.635, 490.027, 490.027, 236.919, 299.792]], dtype=float32)
N=0 | Pyrex speed within PMT Vacuum | FastSim->SlowSim transitions miss speed setup ? |
N=1 | Always Vacuum speed in Vacuum | All standard Geant4 with customized G4OpBoundaryProcess |
Why Low Dependency Access ?
QE scan over 100 energy points, all PMTs
get_pmtid_qe( pmtid, en );
IPMTSimParamSvc | 7.70 s |
PMTSimParamData | 0.30 s |
IPMTSimParamSvc/PMTSimParamData | 26.10 |
junosw/-/merge_requests/126 MERGED AFTER ~3 WEEKS |
junosw/-/issues/66 |
junosw/-/tree/blyth-66-low-dependency-PMT-data-access |
Current Approach : extg4 translated
Geant4 -> GGeo -> CSG |
DRASTIC CODE REDUCTION NEAR
Geant4 -> U4Tree.h/stree.h -> CSG |
|
stree/snode/scsg/snd -> CSGFoundry/CSGSolid/CSGPrim/CSGNode |
junosw : Natural PMT Geometry Branch
Primary | Support |
---|---|
CustomG4OpBoundaryProcess CustomART.h Layr.h | PMTSimParamData (merged in MR 126) PMTAccessor/IPMTAccessor (j/Layr) HamamatsuR12860PMTManager NNVTMCPPMTManager |
Opticks : Custom boundary equivalent