File indexing completed on 2026-04-09 07:49:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <csignal>
0013 #include "SLOG.hh"
0014
0015
0016 #include "spath.h"
0017 #include "ssys.h"
0018
0019 #include "SEvt.hh"
0020 #include "SSim.hh"
0021 #include "SOpticksResource.hh"
0022
0023 #include "U4VolumeMaker.hh"
0024 #include "U4Recorder.hh"
0025
0026 #include "SEventConfig.hh"
0027 #include "U4GDML.h"
0028 #include "U4Tree.h"
0029
0030 #include "CSGFoundry.h"
0031
0032 #include "CSGOptiX.h"
0033
0034
0035 #ifdef WITH_QS
0036 #include "QSim.hh"
0037 #endif
0038
0039
0040 #include "G4CXOpticks.hh"
0041
0042 using namespace std;
0043
0044 const plog::Severity G4CXOpticks::LEVEL = SLOG::EnvLevel("G4CXOpticks", "DEBUG");
0045
0046 U4SensorIdentifier* G4CXOpticks::SensorIdentifier = nullptr ;
0047 void G4CXOpticks::SetSensorIdentifier( U4SensorIdentifier* sid ){ SensorIdentifier = sid ; }
0048
0049
0050 G4CXOpticks* G4CXOpticks::INSTANCE = nullptr ;
0051 G4CXOpticks* G4CXOpticks::Get(){ return INSTANCE ; }
0052 const U4Tree* G4CXOpticks::GetU4Tree(){ return INSTANCE ? INSTANCE->tr : nullptr ; }
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 G4CXOpticks* G4CXOpticks::SetGeometry()
0064 {
0065 G4CXOpticks* gx = new G4CXOpticks ;
0066 gx->setGeometry();
0067 return gx ;
0068 }
0069
0070 G4CXOpticks* G4CXOpticks::SetGeometryFromGDML()
0071 {
0072 G4CXOpticks* gx = new G4CXOpticks ;
0073 gx->setGeometryFromGDML();
0074 return gx ;
0075 }
0076
0077
0078
0079 G4CXOpticks* G4CXOpticks::SetGeometry(const G4VPhysicalVolume* world)
0080 {
0081 G4CXOpticks* gx = new G4CXOpticks ;
0082 gx->setGeometry(world);
0083 return gx ;
0084 }
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 G4CXOpticks* G4CXOpticks::SetGeometry_JUNO(const G4VPhysicalVolume* world, const G4VSensitiveDetector* sd, NPFold* jpmt, const NP* jlut )
0100 {
0101 LOG(LEVEL) << "[" ;
0102
0103
0104 SSim::CreateOrReuse();
0105 SSim::AddExtraSubfold("jpmt", jpmt );
0106 SSim::AddMultiFilm(snam::MULTIFILM, jlut);
0107
0108 SEvt::CreateOrReuse() ;
0109
0110
0111 int opticksMode = SEventConfig::IntegrationMode();
0112 if(opticksMode == 0 || opticksMode == 2) SetNoGPU() ;
0113
0114 LOG(info) << "[ WITH_G4CXOPTICKS opticksMode " << opticksMode << " sd " << sd ;
0115
0116 G4CXOpticks* gx = nullptr ;
0117
0118 if( opticksMode == 0 || opticksMode == 1 || opticksMode == 3 || opticksMode == 2 )
0119 {
0120 gx = SetGeometry(world) ;
0121 SaveGeometry();
0122 }
0123
0124 LOG(LEVEL) << "]" ;
0125 return gx ;
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 void G4CXOpticks::Finalize()
0147 {
0148 LOG(LEVEL);
0149 }
0150
0151 bool G4CXOpticks::NoGPU = false ;
0152 void G4CXOpticks::SetNoGPU(bool no_gpu){ NoGPU = no_gpu ; }
0153 bool G4CXOpticks::IsNoGPU(){ return NoGPU ; }
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 G4CXOpticks::G4CXOpticks()
0172 :
0173 sim(SSim::CreateOrReuse()),
0174 tr(nullptr),
0175 wd(nullptr),
0176 fd(nullptr),
0177 cx(nullptr),
0178 #ifdef WITH_QS
0179 qs(nullptr),
0180 #endif
0181 t0(schrono::stamp())
0182 {
0183 init();
0184 }
0185
0186 void G4CXOpticks::init()
0187 {
0188 INSTANCE = this ;
0189 LOG(LEVEL) << Desc() << std::endl << desc();
0190 }
0191
0192 G4CXOpticks::~G4CXOpticks()
0193 {
0194 schrono::TP t1 = schrono::stamp();
0195 double dt = schrono::duration(t0, t1 );
0196 LOG(LEVEL) << "lifetime " << std::setw(10) << std::fixed << std::setprecision(3) << dt << " s " ;
0197 }
0198
0199
0200 std::string G4CXOpticks::Desc()
0201 {
0202 return CSGOptiX::Desc() ;
0203 }
0204
0205 std::string G4CXOpticks::desc() const
0206 {
0207 std::stringstream ss ;
0208 ss << "G4CXOpticks::desc"
0209 << " sim " << ( sim ? "Y" : "N" )
0210 << " tr " << ( tr ? "Y" : "N" )
0211 << " wd " << ( wd ? "Y" : "N" )
0212 << " fd " << ( fd ? "Y" : "N" )
0213 << " cx " << ( cx ? "Y" : "N" )
0214 #ifdef WITH_QS
0215 << " qs " << ( qs ? "Y" : "N" )
0216 #endif
0217 ;
0218 std::string s = ss.str();
0219 return s ;
0220 }
0221
0222
0223
0224
0225
0226
0227
0228 void G4CXOpticks::setGeometryFromGDML()
0229 {
0230 LOG(LEVEL) << " argumentless " ;
0231
0232 if(spath::has_CFBaseFromGEOM())
0233 {
0234 LOG(LEVEL) << " has_CFBaseFromGEOM " ;
0235 setGeometry(spath::Resolve("$CFBaseFromGEOM/origin.gdml"));
0236 }
0237 else
0238 {
0239 LOG(fatal) << " failed to setGeometryFromGDML " ;
0240 assert(0);
0241 }
0242 }
0243
0244
0245 void G4CXOpticks::setGeometry()
0246 {
0247 if(spath::has_CFBaseFromGEOM())
0248 {
0249 LOG(LEVEL) << " SomeGDMLPath " ;
0250 setGeometry(SOpticksResource::SomeGDMLPath());
0251 }
0252 else if(ssys::hasenv_("GEOM"))
0253 {
0254
0255 LOG(LEVEL) << " GEOM/U4VolumeMaker::PV " ;
0256 setGeometry( U4VolumeMaker::PV() );
0257 }
0258 else if(SOpticksResource::CFBaseFromGEOM())
0259 {
0260 LOG(LEVEL) << "[ CSGFoundry::Load " ;
0261 CSGFoundry* cf = CSGFoundry::Load() ;
0262 LOG(LEVEL) << "] CSGFoundry::Load " ;
0263
0264 LOG(LEVEL) << "[ setGeometry(cf) " ;
0265 setGeometry(cf);
0266 LOG(LEVEL) << "] setGeometry(cf) " ;
0267 }
0268 else
0269 {
0270 LOG(fatal) << " failed to setGeometry " ;
0271 assert(0);
0272 }
0273 }
0274
0275
0276
0277 void G4CXOpticks::setGeometry(const char* gdmlpath)
0278 {
0279 LOG(LEVEL) << " gdmlpath [" << gdmlpath << "]" ;
0280 const G4VPhysicalVolume* world = U4GDML::Read(gdmlpath);
0281
0282 setGeometry(world);
0283 }
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315 void G4CXOpticks::setGeometry(const G4VPhysicalVolume* world )
0316 {
0317 LOG(LEVEL) << "[ G4VPhysicalVolume world " << world ;
0318 assert(world);
0319 wd = world ;
0320
0321 assert(sim && "sim instance should have been grabbed/created in ctor" );
0322 stree* st = sim->get_tree();
0323
0324 LOG(LEVEL) << "[U4Tree::Create " ;
0325 tr = U4Tree::Create(st, world, SensorIdentifier ) ;
0326 LOG(LEVEL) << "]U4Tree::Create " ;
0327
0328
0329 LOG(LEVEL) << "[SSim::initSceneFromTree" ;
0330 sim->initSceneFromTree();
0331 LOG(LEVEL) << "]SSim::initSceneFromTree" ;
0332
0333
0334 LOG(LEVEL) << "[CSGFoundry::CreateFromSim" ;
0335 CSGFoundry* fd_ = CSGFoundry::CreateFromSim() ;
0336 LOG(LEVEL) << "]CSGFoundry::CreateFromSim" ;
0337
0338
0339 LOG(LEVEL) << "[setGeometry(fd_)" ;
0340 setGeometry(fd_);
0341 LOG(LEVEL) << "]setGeometry(fd_)" ;
0342
0343 LOG(info) << Desc() ;
0344
0345 LOG(LEVEL) << "] G4VPhysicalVolume world " << world ;
0346 }
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364 const char* G4CXOpticks::setGeometry_saveGeometry = ssys::getenvvar("G4CXOpticks__setGeometry_saveGeometry") ;
0365 void G4CXOpticks::setGeometry(CSGFoundry* fd_)
0366 {
0367 setGeometry_(fd_);
0368 }
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390 void G4CXOpticks::setGeometry_(CSGFoundry* fd_)
0391 {
0392 fd = fd_ ;
0393 LOG(LEVEL) << "[ fd " << fd ;
0394
0395 bool hasDevice = SEventConfig::HasDevice();
0396
0397 if(NoGPU == false && hasDevice == true)
0398 {
0399 LOG(LEVEL) << "[ CSGOptiX::Create " ;
0400 cx = CSGOptiX::Create(fd);
0401 LOG(LEVEL) << "] CSGOptiX::Create " ;
0402 }
0403 else
0404 {
0405 LOG(info)
0406 << " skip CSGOptiX::Create as NoGPU set OR failed to detect CUDA capable device "
0407 << " NoGPU " << NoGPU
0408 << " hasDevice " << ( hasDevice ? "YES" : "NO " )
0409 ;
0410 }
0411
0412 #ifdef WITH_QS
0413 qs = cx ? cx->sim : nullptr ;
0414
0415 QSim* qsg = QSim::Get() ;
0416
0417 LOG(LEVEL)
0418 << " cx " << ( cx ? "Y" : "N" )
0419 << " qs " << ( qs ? "Y" : "N" )
0420 << " QSim::Get " << ( qsg ? "Y" : "N" )
0421 ;
0422
0423 assert( qs == qsg );
0424 #endif
0425
0426
0427 LOG(LEVEL) << "] fd " << fd ;
0428
0429
0430
0431 if( setGeometry_saveGeometry != nullptr )
0432 {
0433 LOG(info) << "[ G4CXOpticks__setGeometry_saveGeometry " ;
0434 saveGeometry(setGeometry_saveGeometry);
0435 LOG(info) << "] G4CXOpticks__setGeometry_saveGeometry " ;
0436 }
0437 }
0438
0439
0440
0441
0442 std::string G4CXOpticks::descSimulate() const
0443 {
0444 SEvt* sev = SEvt::Get_EGPU() ;
0445 assert(sev);
0446 std::stringstream ss ;
0447 ss
0448 << "[G4CXOpticks::descSimulate" << std::endl
0449 << sev->descSimulate()
0450 << "]G4CXOpticks::descSimulate" << std::endl
0451 ;
0452
0453 std::string str = ss.str();
0454 return str ;
0455 }
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466 void G4CXOpticks::simulate(int eventID, bool reset_ )
0467 {
0468 LOG_IF(fatal, NoGPU) << "NoGPU SKIP" ;
0469 if(NoGPU) return ;
0470
0471 LOG(LEVEL) << "[ " << eventID;
0472 LOG(LEVEL) << desc() ;
0473
0474 assert(cx);
0475
0476 #ifdef WITH_QS
0477 assert(qs);
0478 qs->simulate(eventID, reset_ );
0479 #else
0480 cx->simulate(eventID, reset_);
0481 #endif
0482
0483
0484 LOG(LEVEL) << "] " << eventID ;
0485
0486 }
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499 void G4CXOpticks::reset(int eventID)
0500 {
0501 LOG_IF(fatal, NoGPU) << "NoGPU SKIP" ;
0502 if(NoGPU) return ;
0503
0504 assert( SEventConfig::IsRGModeSimulate() );
0505
0506 unsigned num_hit_0 = SEvt::GetNumHit_EGPU() ;
0507 LOG(LEVEL) << "[ " << eventID << " num_hit_0 " << num_hit_0 ;
0508
0509 #ifdef WITH_QS
0510 assert(qs);
0511 qs->reset(eventID);
0512 #else
0513 cx->reset(eventID);
0514 #endif
0515
0516 unsigned num_hit_1 = SEvt::GetNumHit_EGPU() ;
0517 LOG(LEVEL) << "] " << eventID << " num_hit_1 " << num_hit_1 ;
0518 }
0519
0520
0521
0522
0523
0524 void G4CXOpticks::simtrace(int eventID)
0525 {
0526 LOG_IF(fatal, NoGPU) << "NoGPU SKIP" ;
0527 if(NoGPU) return ;
0528
0529 LOG(LEVEL) << "[" ;
0530
0531 #ifdef WITH_QS
0532 assert(qs);
0533 qs->simtrace(eventID);
0534 #else
0535 assert(cx);
0536 cx->simtrace(eventID);
0537 #endif
0538
0539
0540 LOG(LEVEL) << "]" ;
0541 }
0542
0543 void G4CXOpticks::render()
0544 {
0545 LOG_IF(fatal, NoGPU) << "NoGPU SKIP" ;
0546 if(NoGPU) return ;
0547
0548 LOG(LEVEL) << "[" ;
0549 assert( cx );
0550 assert( SEventConfig::IsRGModeRender() );
0551 cx->render() ;
0552 LOG(LEVEL) << "]" ;
0553 }
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577 void G4CXOpticks::saveGeometry() const
0578 {
0579 const char* dir = SEventConfig::OutFold() ;
0580 LOG(LEVEL) << "dir [" << ( dir ? dir : "-" ) ;
0581 saveGeometry(dir) ;
0582 }
0583
0584
0585
0586 void G4CXOpticks::saveGeometry(const char* dir_) const
0587 {
0588 LOG(LEVEL) << " dir_ " << dir_ ;
0589 const char* dir = spath::Resolve(dir_);
0590 LOG(LEVEL) << "[ " << ( dir ? dir : "-" ) ;
0591 LOG(info) << "[ " << ( dir ? dir : "-" ) ;
0592 std::cout << "G4CXOpticks::saveGeometry [ " << ( dir ? dir : "-" ) << std::endl ;
0593
0594 if(wd) U4GDML::Write(wd, dir, "origin.gdml" );
0595 if(fd) fd->save(dir) ;
0596
0597 LOG(LEVEL) << "] " << ( dir ? dir : "-" ) ;
0598 }
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625 void G4CXOpticks::SaveGeometry()
0626 {
0627 LOG_IF(error, INSTANCE==nullptr) << " INSTANCE nullptr : NOTHING TO SAVE " ;
0628 if(INSTANCE == nullptr) return ;
0629
0630 const char* dir = ssys::getenvvar(SaveGeometry_KEY) ;
0631 LOG_IF(LEVEL, dir == nullptr ) << " not saving as envvar not set " << SaveGeometry_KEY ;
0632 if(dir == nullptr) return ;
0633 LOG(info) << " save to dir " << dir << " configured via envvar " << SaveGeometry_KEY ;
0634 INSTANCE->saveGeometry(dir);
0635 }
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648 void G4CXOpticks::SensitiveDetector_Initialize(int eventID)
0649 {
0650 LOG(LEVEL) << " eventID " << eventID ;
0651 U4Recorder* recorder = U4Recorder::Get();
0652 if(recorder)
0653 {
0654 recorder->BeginOfEventAction_(eventID);
0655 }
0656 }
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710 void G4CXOpticks::SensitiveDetector_EndOfEvent(int eventID)
0711 {
0712 LOG(LEVEL) << " eventID " << eventID ;
0713 U4Recorder* recorder = U4Recorder::Get();
0714 if(recorder)
0715 {
0716 recorder->EndOfEventAction_(eventID);
0717 }
0718 }
0719
0720
0721 void from_gdml(filesystem::path gdml_file, filesystem::path out_prefix)
0722 {
0723 G4GDMLParser parser;
0724 parser.Read(gdml_file.string(), false);
0725
0726 const G4VPhysicalVolume *world = parser.GetWorldVolume();
0727
0728 if (!world)
0729 {
0730 LOG_ERROR << "Failed creatng G4 volume from GDML " << gdml_file << endl;
0731 }
0732 else
0733 {
0734 G4CXOpticks *g4cx = G4CXOpticks::SetGeometry(world);
0735
0736 auto outpath = out_prefix / gdml_file.stem();
0737
0738 g4cx->saveGeometry(outpath.string().c_str());
0739
0740 LOG_INFO << "Created G4 volume " << world->GetName() << " from " << gdml_file << endl;
0741 LOG_INFO << "Saved CSG tree to " << outpath << endl;
0742
0743 delete g4cx;
0744 }
0745 }