JUNO Opticks - Geo Fixes: >100x faster

  • ZSolid::ApplyZCutTree applied to both NNVT and Hama PMTs
    • Avoid PROFLIGATE : G4ItersectionSolid Z-Cut
    • With : ZSolid::ApplyZCutTree : Actually Cut the CSG Tree
  • fixed base_steel G4Polycone with multiple R-inner
    • improved Opticks G4Polycone translation
    • avoids overlap with sStrutBallhead
  • ray trace renders and render times following geometry fixes
    • timings : no standout bottlenecks remain
    • > 100x faster than times from July
  • G4Sphere phiCut thetaCut : Opticks translation bug
    • LHCb RICH : needs fix for their mirror geometry
    • fixing with unbounded primitives : CSG_PHICUT CSG_THETACUT
Simon C Blyth, 2021/12/23

hmsk_solidMaskTail_X4Mesh

NNVT PMT Solid : PROFLIGATE G4ItersectionSolid Z-Cut

Using G4IntersectionSolid to apply Z-cut to PMT


344 void NNVTMCPPMTManager::helper_make_solid_profligate_tail_cut()
345 {
346     std::cout << "NNVTMCPPMTManager::helper_make_solid_profligate_tail_cut" << std::endl ;
347     // inner2
348     G4double helper_sep_tube_r = m_pmt_r;
349     const double tail_height = m_pmt_h - m_z_equator;
350     const double tail_half_height = tail_height / 2;
351     const G4ThreeVector cut_tail_displacement(0., 0., -tail_half_height);
352     G4VSolid* cut_tail_solid = new G4Tubs("CutTail_NNVTMCPPMT_Solid",
353                                           0.,
354                                           helper_sep_tube_r+1E-9*mm,
355                                           tail_half_height,
356                                           0., 360.*degree);
357     inner2_solid = new G4IntersectionSolid( GetName() + "_inner2_tail_solid",
358                                             inner2_solid,
359                                             cut_tail_solid,
360                                             NULL,
361                                             cut_tail_displacement);
362

 

SOLUTION ACTUALLY CUT THE CSG TREE using https://github.com/simoncblyth/j/blob/main/PMTSim/ZSolid.hh

G4VSolid* ZSolid::ApplyZCutTree( const G4VSolid* original, double zcut)

ZSolid::ApplyZCutTree to NNVT PMT Solid : Makes Simpler


nnvt_body_solid [-1] nameprefix _body_solid  NODE:5 PRIM:3 UNDEFINED:5 EXCLUDE:0 INCLUDE:0 MIXED:0 Order:IN

                        Uni
                        U
                        3


        Uni                     Tub
        U                       U
        1                       4


Ell             Pol
U               U
0               2


0               -193            -299    zdelta

184             -174            -213    az1
-184            -213            -386    az0
_head   _1_2    _neck           _tail
 zcut -200
solid_zcut [-1] nameprefix _body_solid_  NODE:3 PRIM:2 UNDEFINED:3 EXCLUDE:0 INCLUDE:0 MIXED:0 Order:IN

        Uni
        U
        1


Ell             Pol
U               U
0               2


0               -193    zdelta

184             -174    az1
-184            -200    az0
head    1_2     neck


nnvt_maker_zcut-500.0

nnvt_maker_zcut-400.0

nnvt_maker_zcut-350.0

nnvt_maker_zcut-300.0

nnvt_maker_zcut-200.0

nnvt_maker_zcut-183.25

nnvt_body_phys

nnvt_body_phys_nurs

nnvt_body_phys_nurs_pdyn

nnvt_body_phys_nurs_pdyn_prtc_obto

nnvt_body_phys_pdyn

Opticks-Offline CMake Integration

opticks/cmake/Modules/FindOpticks.cmake used from offline/cmake/JUNODependencies.cmake:

if(DEFINED ENV{OPTICKS_PREFIX})
   set(CMAKE_MODULE_PATH
      ${CMAKE_MODULE_PATH} "$ENV{JUNOTOP}/opticks/cmake/Modules")
   find_package(Opticks QUIET MODULE)
   message(STATUS
      "${CMAKE_CURRENT_LIST_FILE} : Opticks_FOUND:${Opticks_FOUND}" )
endif()

Then subsequently packages needing Opticks headers add dependency line:

$<$<BOOL:${Opticks_FOUND}>:${Opticks_TARGET}>

Much easier than integration with CMT Offline : as can use CMake targets

PolyconeWithMultipleRmin_X4Mesh

base_steel : G4Polycone with two R_inner

PolyconeWithMultipleRmin_xxs_isect

Geant4 Intersect Positions

GEOM=PolyconeWithMultipleRmin ~/opticks/extg4/xxs.sh

3dbec_cxr_solid_r7@ copy

SLA=r7@ ./cxr_solid.sh   ## 1:base_steel

Geometry Changes Since Last Performance Check

uni_acrylic3_0_figs_positions_mpplt_pid.png

cxs.sh OptiX 7, 2D intersect scatter plots

spurious intersects evident

* interfering subtraction-of-subtraction issue

uni_acrylic1_0_figs_positions_mpplt_pid.png

--additionacrylic-simplify-csg
do not subtract cavities for daughter volumes

Hama_1_figs_positions_mpnky_pid.png

mask tail cutting across PMT bulb ?

Hama_1_figs_positions_mpplt_pid.png

Hama_2_figs_positions_mpnky_pid.png

Hama_2_figs_positions_mpplt_pid.png

Hama_4_figs_positions_mpnky_pid.png

Hama_4_figs_positions_mpplt_pid.png

Hama_16_figs_positions_mpnky_pid.png

Improve cross-section view quality ?

* needs development :

* target gensteps according to 2D histo of intersects

* progressive refinement

Hama_16_figs_positions_mpplt_pid.png

CSGOptiX (NVIDIA OptiX 7) renderers

Not built by standard Opticks build, need:

cd ~/opticks/CSGOptiX/
b7                       ## short for opticks-build7

Using CSGOptiX/tests/CSGOptiXSimulateTest.cc:

cxs.sh        ## creates 2D cross section .png scatter plots

Using CSGOptiX/tests/CSGOptiXRenderTest.cc:

cxr_view.sh
cxr_solid.sh
cxr_overview.sh
cxr.sh         ## creates 3D render .jpg of geometry

At bottom left of all cxr .jpg is launch time(seconds) for 2M pixels (1920x1080)

sWorld_cam_0_t0_cxr_view___eye_0,0.6,0.4__zoom_1__tmin_0.4_sWorld.jpg

MOI=sWorld EYE=0,0.6,0.4 TMIN=0.4 ./cxr_view.sh

NNVT:0:1000_cam_0_t0_cxr_view___eye_-2,-2,-2,1__look_0,0,2,1__zoom_1__tmin_0.4_NNVT:0:1000.jpg

MOI=NNVT:0:1000 EYE=-2,-2,-2 LOOK=0,0,2,1 TMIN=0.4 ./cxr_view.sh

NNVT:0:1000_cam_0_t0_cxr_view___eye_-2,-2,-2,1__zoom_1__tmin_0.4_NNVT:0:1000.jpg

MOI=NNVT:0:1000 EYE=-2,-2,-2 TMIN=0.4 ./cxr_view.sh

NNVT:0:1000_cam_0_t0_cxr_view___eye_0,1,-2,1__zoom_1__tmin_0.4_NNVT:0:1000.jpg

MOI=NNVT:0:1000 EYE=0,1,-2 TMIN=0.4 ./cxr_view.sh

NNVT:0:1000_cam_0_t0_cxr_view___eye_0,2,-4,1__zoom_1__tmin_0.4_NNVT:0:1000.jpg

MOI=NNVT:0:1000 EYE=0,2,-4 TMIN=0.4 ./cxr_view.sh

sWaterTube_cam_0_t0_cxr_view___eye_0,1,-0.5__look_0,0,-0.5__zoom_1__tmin_0.4_sWaterTube.jpg

MOI=sWaterTube EYE=0,1,-0.5 LOOK=0,0,-0.5 TMIN=0.4 ./cxr_view.sh

sWaterTube_cam_0_t0_cxr_view___eye_0,1,-0.5__look_0,0,-0.5__zoom_1__tmin_1_sWaterTube.jpg

MOI=sWaterTube EYE=0,1,-0.5 LOOK=0,0,-0.5 TMIN=1 ./cxr_view.sh

sWaterTube_cam_0_t0_cxr_view___eye_0,1,-1,1__look_0,0,-1__zoom_1__tmin_0.4_sWaterTube.jpg

MOI=sWaterTube EYE=0,1,-1 LOOK=0,0,-1 TMIN=1 ./cxr_view.sh

sWaterTube_cam_0_t0_cxr_view___eye_0,1,-1,1__zoom_1__tmin_0.4_sWaterTube.jpg

MOI=sWaterTube EYE=0,1,-1 LOOK=0,0,0 TMIN=0.4 ./cxr_view.sh

Current JUNO Geometry : Auto-Factorized by "progeny digest"

ridx plc vol component name note (3dbec4dc)
0 1 3084 3084:sWorld non-repeated remainder
1 25600 5 5:PMT_3inch_pmt_solid 4 types of PMT
2 12612 5 5:NNVTMCPPMTsMask
3 5000 5 5:HamamatsuR12860sMask
4 2400 4 4:mask_PMT_20inch_vetosMask
5 590 1 1:sStrutBallhead 4 parts of Fastener but not instanced together as are sibling volumes that happen to line up rather than parent-child
6 590 1 1:uni1
7 590 1 1:base_steel
8 590 1 1:uni_acrylic1
9 504 130 130:sPanel repeated parts of TT

~/opticks/ana/ggeo.sh --mmtrim --mmsmry

cxr_solid.sh renders

cxr_solid.sh renders of single "Solids" in Opticks sense

Actually composite corresponding to "factors" of the geometry

Renders of the 10 auto-factorized JUNO solids follow.

3dbec_cxr_solid_r0@

SLA=r0@ ./cxr_solid.sh    ## 3084:sWorld

3dbec_cxr_solid_r1@

SLA=r1@ ./cxr_solid.sh   ## 5:PMT_3inch_pmt_solid

3dbec_cxr_solid_r2@

SLA=r2@ ./cxr_solid.sh  ## 5:NNVTMCPPMTsMask

3dbec_cxr_solid_r3@

SLA=r3@ ./cxr_solid.sh   ## 5:HamamatsuR12860sMask

3dbec_cxr_solid_r4@

SLA=r4@ ./cxr_solid.sh   ## 4:mask_PMT_20inch_vetosMask

3dbec_cxr_solid_r5@

SLA=r5@ ./cxr_solid.sh   ## 1:sStrutBallhead

3dbec_cxr_solid_r6@

SLA=r6@ ./cxr_solid.sh   ## 1:uni1

3dbec_cxr_solid_r7@

SLA=r7@ ./cxr_solid.sh   ## 1:base_steel

3dbec_cxr_solid_r8@

SLA=r8@ ./cxr_solid.sh    ## 1:uni_acrylic1

3dbec_cxr_solid_r9@

SLA=r9@ ./cxr_solid.sh    ## 130:sPanel

cxr_view.sh renders varying included geometry

cxr_view.sh from same position, changing included geometry

cxr_views.sh:

emms=$(seq 0 9)
for emm in $emms ; do
    EMM=$emm, ./cxr_view.sh
done

cxr_view_cam_0_t0_cxr_view_sWaterTube.jpg

t0 : tilde-zero : ~0 : meaning ALL

cxr_view_cam_0_0,_cxr_view_sWaterTube.jpg

3084:sWorld

cxr_view_cam_0_1,_cxr_view_sWaterTube.jpg

5:PMT_3inch_pmt_solid

cxr_view_cam_0_2,_cxr_view_sWaterTube.jpg

5:NNVTMCPPMTsMask

cxr_view_cam_0_3,_cxr_view_sWaterTube.jpg

5:HamamatsuR12860sMask

cxr_view_cam_0_4,_cxr_view_sWaterTube.jpg

4:mask_PMT_20inch_vetosMask

cxr_view_cam_0_5,_cxr_view_sWaterTube.jpg

1:sStrutBallhead

cxr_view_cam_0_6,_cxr_view_sWaterTube.jpg

1:uni1

cxr_view_cam_0_7,_cxr_view_sWaterTube.jpg

1:base_steel

cxr_view_cam_0_8,_cxr_view_sWaterTube.jpg

1:uni_acrylic1

cxr_view_cam_0_9,_cxr_view_sWaterTube.jpg

130:sPanel

sWaterTube timings whilst varying geometry

idx -e time(s) relative enabled geometry description 3dbec4dc  
0 5, 0.0004 0.0004 ONLY: 1:sStrutBallhead  
1 7, 0.0004 0.0004 ONLY: 1:base_steel  
2 8, 0.0005 0.0005 ONLY: 1:uni_acrylic1  
3 6, 0.0005 0.0005 ONLY: 1:uni1  
4 1, 0.0006 0.0006 ONLY: 5:PMT_3inch_pmt_solid NOTABLY FAST cf 20inch
5 9, 0.0006 0.0006 ONLY: 130:sPanel  
6 4, 0.0011 0.0011 ONLY: 4:mask_PMT_20inch_vetosMask  
7 3, 0.0022 0.0022 ONLY: 5:HamamatsuR12860sMask NOTABLY SLOW cf 3inch
8 2, 0.0031 0.0031 ONLY: 5:NNVTMCPPMTsMask
9 0, 0.0035 0.0035 ONLY: 3084:sWorld
10 t0 0.0067 0.0067 ALL  

cxr_overview.sh renders

Using cxr_scan.sh to repeateadly invoke cxr_overview.sh with different -e options

ridx plc vol component name note (3dbec4dc)
0 1 3084 3084:sWorld non-repeated remainder
1 25600 5 5:PMT_3inch_pmt_solid 4 types of PMT
2 12612 5 5:NNVTMCPPMTsMask
3 5000 5 5:HamamatsuR12860sMask
4 2400 4 4:mask_PMT_20inch_vetosMask
5 590 1 1:sStrutBallhead 4 parts of Fastener but not instanced together as are sibling volumes that happen to line up rather than parent-child
6 590 1 1:uni1
7 590 1 1:base_steel
8 590 1 1:uni_acrylic1
9 504 130 130:sPanel repeated parts of TT

cxr_overview_emm_t0_moi_-1_ALL.jpg

-e t0 : ALL

cxr_overview_emm_1,2,3,4_moi_-1.jpg

-e 1,2,3,4 : ONLY PMTs

cxr_overview_emm_0,_moi_-1.jpg

-e 0, : ONLY 0 : 3084:sWorld

cxr_overview_emm_1,_moi_-1.jpg

-e 1, : ONLY 1 : 5:PMT_3inch_pmt_solid

cxr_overview_emm_2,_moi_-1.jpg

-e 2, : ONLY 2 : 5:NNVTMCPPMTsMask

cxr_overview_emm_3,_moi_-1.jpg

-e 3, : ONLY 3 : 5:HamamatsuR12860sMask

cxr_overview_emm_4,_moi_-1.jpg

-e 4, : ONLY 4 : 4:mask_PMT_20inch_vetosMask

cxr_overview_emm_5,_moi_-1.jpg

-e 5, : ONLY 5 : 1:sStrutBallhead

cxr_overview_emm_6,_moi_-1.jpg

-e 6, : ONLY 6 : 1:uni1

cxr_overview_emm_7,_moi_-1.jpg

-e 7, : ONLY 7 : 1:base_steel

cxr_overview_emm_8,_moi_-1.jpg

-e 8, : ONLY 8 : 1:uni_acrylic1

cxr_overview_emm_9,_moi_-1.jpg

-e 9, : ONLY 9 : 130:sPanel

cxr_overview_emm_t0,_moi_-1.jpg

-e t0, : NOT 0 : 3084:sWorld

cxr_overview_emm_t1,_moi_-1.jpg

-e t1, : NOT 1 : 5:PMT_3inch_pmt_solid

cxr_overview_emm_t2,_moi_-1.jpg

-e t2, : NOT 2 : 5:NNVTMCPPMTsMask

cxr_overview_emm_t3,_moi_-1.jpg

-e t3, : NOT 3 : 5:HamamatsuR12860sMask

cxr_overview_emm_t4,_moi_-1.jpg

-e t4, : NOT 4 : 4:mask_PMT_20inch_vetosMask

cxr_overview_emm_t5,_moi_-1.jpg

-e t5, : NOT 5 : 1:sStrutBallhead

cxr_overview_emm_t6,_moi_-1.jpg

-e t6, : NOT 6 : 1:uni1

cxr_overview_emm_t7,_moi_-1.jpg

-e t7, : NOT 7 : 1:base_steel

cxr_overview_emm_t8,_moi_-1.jpg

-e t8, : NOT 8 : 1:uni_acrylic1

cxr_overview_emm_t9,_moi_-1.jpg

-e t9, : NOT 9 : 130:sPanel

[Dec] JUNO : OptiX 7 Ray Trace Times ~2M-pix : TITAN RTX

idx -e time(s) relative enabled geometry description 3dbec4dc
0 5, 0.0004 0.0643 ONLY: 1:sStrutBallhead
1 9, 0.0004 0.0658 ONLY: 130:sPanel
2 7, 0.0005 0.0782 ONLY: 1:base_steel
3 8, 0.0006 0.0966 ONLY: 1:uni_acrylic1
4 6, 0.0006 0.1009 ONLY: 1:uni1
5 1, 0.0009 0.1476 ONLY: 5:PMT_3inch_pmt_solid FAST cf 20in
6 4, 0.0015 0.2386 ONLY: 4:mask_PMT_20inch_vetosMask
7 3, 0.0033 0.5373 ONLY: 5:HamamatsuR12860sMask SLOW cf 3in
8 0, 0.0040 0.6556 ONLY: 3084:sWorld
9 2, 0.0040 0.6627 ONLY: 5:NNVTMCPPMTsMask SLOW cf 3in
10 t4, 0.0050 0.8307 EXCL: 4:mask_PMT_20inch_vetosMask
11 t2, 0.0051 0.8391 EXCL: 5:NNVTMCPPMTsMask
12 t3, 0.0052 0.8514 EXCL: 5:HamamatsuR12860sMask
13 t6, 0.0053 0.8799 EXCL: 1:uni1
14 t7, 0.0054 0.8809 EXCL: 1:base_steel
15 t0 0.0054 0.8843 ALL
16 t5, 0.0054 0.8843 EXCL: 1:sStrutBallhead
17 t9, 0.0054 0.8855 EXCL: 130:sPanel
18 t1, 0.0054 0.8860 EXCL: 5:PMT_3inch_pmt_solid
19 t8, 0.0055 0.9013 EXCL: 1:uni_acrylic1
20 t0, 0.0059 0.9753 EXCL: 3084:sWorld
21 1,2,3,4 0.0061 1.0000 ONLY PMT
22 t8,0 0.0062 1.0217 EXCL: 1:uni_acrylic1 3084:sWorld

[July] JUNO Geometry : OptiX 7 Ray Trace Times ~2M-pix : TITAN RTX

idx -e time(s) relative enabled geometry description
0 9, 0.0017 0.1702 ONLY: 130:sPanel
1 7, 0.0017 0.1714 ONLY: 1:base_steel
2 6, 0.0019 0.1923 ONLY: 1:uni1
3 5, 0.0027 0.2780 ONLY: 1:sStrutBallhead
4 4, 0.0032 0.3268 ONLY: 5:mask_PMT_20inch_vetosMask
5 1, 0.0032 0.3287 ONLY: 5:PMT_3inch_pmt_solid
6 2, 0.0055 0.5669 ONLY: 5:NNVTMCPPMTsMask
7 3, 0.0074 0.7582 ONLY: 5:HamamatsuR12860sMask
8 1,2,3,4 0.0097 1.0000 ONLY PMT
9 t8,0 0.0099 1.0179 EXCL: 1:uni_acrylic3 3084:sWorld
10 0, 0.1171 12.0293 ONLY: 3084:sWorld
11 t8, 0.1186 12.1769 EXCL: 1:uni_acrylic3
12 t0, 0.5278 54.2066 EXCL: 3084:sWorld
13 8, 0.5310 54.5298 ONLY: 1:uni_acrylic3
14 t3, 0.6017 61.7954 EXCL: 5:HamamatsuR12860sMask
15 t2, 0.6043 62.0620 EXCL: 5:NNVTMCPPMTsMask
16 t5, 0.6171 63.3787 EXCL: 1:sStrutBallhead
17 t6, 0.6196 63.6301 EXCL: 1:uni1
18 t7, 0.6226 63.9458 EXCL: 1:base_steel
19 t0 0.6240 64.0879 3084:sWorld
20 t4, 0.6243 64.1169 EXCL: 5:mask_PMT_20inch_vetosMask
21 t9, 0.6335 65.0636 EXCL: 130:sPanel
22 t1, 0.6391 65.6384 EXCL: 5:PMT_3inch_pmt_solid

cxr commands for renders and table

## generate renders and json metadata

cx
./cxr_scan.sh      # repeating ./cxr_overview.sh
./cxr_grab.sh      # from workstation to laptop

## generation of RST table (from metadata) and s5 presentation pages

./cxr_pub.sh cp | sh
./cxr_pub.sh s5

./cxr_table.sh

cxr_geochain_SphereWithPhiSegment_difference_old

LHCb RICH mirror geometry reveals bug

cxr_geochain_SphereWithPhiSegment_difference_new

Fixed bug, but approach has problems:

Better approach : New Unbounded Primitives

CSG_PHICUT

cosPhi1, sinPhi1, cosPhi2, sinPhi2

  • fewer planes in "cutter" shape
CSG_THETACUT
cosTheta1, sinTheta1, cosTheta2, sinTheta2

Working with LHCb RICH student (Lucas) to implement

SphereWithPhiSegment_xxs_isect

CSG_PHICUT : XY cross section : slice of cake shape

need intersects with two half-planes at phi1 and phi2

New unbounded primitive CSG_PHICUT : intersect_node_phicut

bool intersect_node_phicut( float4& isect, const quad& q0, const float t_min, const float3& ray_origin, const float3& ray_direction )
{
    const float cosPhi0 = q0.f.x ;
    const float sinPhi0 = q0.f.y ;
    const float cosPhi1 = q0.f.z ;
    const float sinPhi1 = q0.f.w ;

    // dot products with normal0  [ sinPhi0, -cosPhi0, 0.f ]
    float d_n0 = ray_direction.x*sinPhi0 + ray_direction.y*(-cosPhi0) ;
    float o_n0 = ray_origin.x*sinPhi0 + ray_origin.y*(-cosPhi0) ;
    float t0 = d_n0 == 0.f ? t_min : -o_n0/d_n0 ;
    float side0 = ray_origin.x*cosPhi0 + ray_origin.y*sinPhi0 + ( ray_direction.x*cosPhi0 + ray_direction.y*sinPhi0 )*t0 ;
    if(side0 < 0.f) t0 = t_min ;    // Disqualify intersect with other half plane 

    // dot products with normal1   [ -sinPhi1,  cosPhi1, 0.f ]
    float d_n1 = ray_direction.x*(-sinPhi1) + ray_direction.y*cosPhi1 ;
    float o_n1 = ray_origin.x*(-sinPhi1) + ray_origin.y*cosPhi1 ;
    float t1 = d_n1 == 0.f ? t_min : -o_n1/d_n1 ;
    float side1 = ray_origin.x*cosPhi1 + ray_origin.y*sinPhi1 + ( ray_direction.x*cosPhi1 + ray_direction.y*sinPhi1 )*t1 ;
    if(side1 < 0.f) t1 = t_min ;    // Disqualify intersect with other half plane 

    float t_near = fminf(t0,t1);  // order the intersects
    float t_far  = fmaxf(t0,t1);
    float t_cand = t_near > t_min  ?  t_near : ( t_far > t_min ? t_far : t_min ) ;
    bool valid_intersect = t_cand > t_min ;
    if( valid_intersect )
    {
        isect.x = t_cand == t1 ? -sinPhi1 :  sinPhi0 ;
        isect.y = t_cand == t1 ?  cosPhi1 : -cosPhi0 ;
        isect.z = 0.f ;
        isect.w = t_cand ;
    }
    return valid_intersect ;
}

CSGNodeScanTest_iphi_figs_scanplot.png

opticks/CSG/tests/CSGNodeScanTest.{cc,py,sh}

* CPU test of GPU ray trace code

* isect : intersect normal + distance