Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:34

0001 #include <sstream>
0002 #include <cstring>
0003 #include <csignal>
0004 #include <cassert>
0005 #include <iostream>
0006 #include <iomanip>
0007 #include <vector>
0008 
0009 #include "ssys.h"
0010 #include "sseq.h"
0011 #include "sstr.h"
0012 #include "spath.h"
0013 #include "sdirectory.h"
0014 #include "salloc.h"
0015 
0016 #include "scontext.h"
0017 
0018 #include "sbuild.h"
0019 #include "sphoton.h"
0020 
0021 #include "SPath.hh"   // only SPath::Make to replace
0022 
0023 
0024 
0025 #include "SEventConfig.hh"
0026 #include "SRG.h"  // raygenmode
0027 #include "SRM.h"  // runningmode
0028 #include "SComp.h"
0029 #include "OpticksPhoton.hh"
0030 
0031 #include "SLOG.hh"
0032 
0033 const plog::Severity SEventConfig::LEVEL = SLOG::EnvLevel("SEventConfig", "DEBUG") ;
0034 
0035 int         SEventConfig::_IntegrationModeDefault = -1 ;
0036 const char* SEventConfig::_EventModeDefault = Minimal ;
0037 const char* SEventConfig::_EventNameDefault = nullptr ;
0038 const char* SEventConfig::_RunningModeDefault = "SRM_DEFAULT" ;
0039 int         SEventConfig::_StartIndexDefault = 0 ;
0040 int         SEventConfig::_NumEventDefault = 1 ;
0041 const char* SEventConfig::_NumPhotonDefault = nullptr ;
0042 const char* SEventConfig::_NumGenstepDefault = nullptr ;
0043 int         SEventConfig::_EventSkipaheadDefault = 100000 ;  // APPROPRIATE SKIPAHEAD DEPENDS ON HOW MANY RANDOMS CONSUMED BY PHOTON SIMULATION
0044 const char* SEventConfig::_G4StateSpecDefault = "1000:38" ;
0045 const char* SEventConfig::_G4StateSpecNotes   = "38=2*17+4 is appropriate for MixMaxRng" ;
0046 int         SEventConfig::_G4StateRerunDefault = -1 ;
0047 
0048 const char* SEventConfig::_MaxBounceNotes = "NB bounce limit is now separate from the non-PRODUCTION record limit which is inherent from sseq.h sseq::SLOTS " ;
0049 const char* SEventConfig::_MaxTimeNotes = "NB time limit(ns) can truncate simulation together with bounce limit, default timer limit is so high to be unlimited " ;
0050 
0051 
0052 float SEventConfig::_MaxTimeDefault = 1.e27f ; // crazy high default (ns) effectively meaning no limit
0053 
0054 int SEventConfig::_MaxBounceDefault = 31 ;  // was previously too small at 9
0055 int SEventConfig::_MaxRecordDefault = 0 ;
0056 int SEventConfig::_MaxRecDefault = 0 ;
0057 int SEventConfig::_MaxAuxDefault = 0 ;
0058 int SEventConfig::_MaxSupDefault = 0 ;
0059 int SEventConfig::_MaxSeqDefault = 0 ;
0060 int SEventConfig::_MaxPrdDefault = 0 ;
0061 int SEventConfig::_MaxTagDefault = 0 ;
0062 int SEventConfig::_MaxFlatDefault = 0 ;
0063 
0064 int SEventConfig::_ModeSaveDefault = 0 ;
0065 int SEventConfig::_ModeClientDefault = 0 ;
0066 int SEventConfig::_ModeLiteDefault = 0 ;
0067 int SEventConfig::_ModeMergeDefault = 0 ;
0068 float SEventConfig::_MergeWindowDefault = 0.f ;  // ns
0069 
0070 float SEventConfig::_MaxExtentDomainDefault = 1000.f ;  // mm  : domain compression used by *rec*
0071 float SEventConfig::_MaxTimeDomainDefault = 10.f ; // ns
0072 
0073 const char* SEventConfig::_OutFoldDefault = "$DefaultOutputDir" ;
0074 const char* SEventConfig::_OutNameDefault = nullptr ;
0075 const char* SEventConfig::_EventReldirDefault = "ALL${VERSION:-0}_${OPTICKS_EVENT_NAME:-no_opticks_event_name}" ; // coordinate with kEventName
0076 const char* SEventConfig::_RGModeDefault = "simulate" ;
0077 const char* SEventConfig::_HitMaskDefault = "SD" ;
0078 
0079 
0080 #if defined(RNG_XORWOW)
0081 const char* SEventConfig::_MaxSlotDefault =  ;
0082 const char* SEventConfig::_MaxGenstepDefault = WITH_STATE_LIMIT ;
0083 const char* SEventConfig::_MaxPhotonDefault = WITH_STATE_LIMIT ;
0084 const char* SEventConfig::_MaxSimtraceDefault = WITH_STATE_LIMIT ;
0085 const char* SEventConfig::_MaxCurandDefault = WITH_STATE_LIMIT ;
0086 
0087 #elif defined(RNG_PHILOX) || defined(RNG_PHILITEOX)
0088 const char* SEventConfig::_MaxSlotDefault = "0" ;     // see SEventConfig::SetDevice : set according to VRAM
0089 const char* SEventConfig::_MaxGenstepDefault = NO_STATE_LIMIT_GENSTEP ;  // adhoc
0090 const char* SEventConfig::_MaxPhotonDefault = NO_STATE_LIMIT ;
0091 const char* SEventConfig::_MaxSimtraceDefault = NO_STATE_LIMIT ;
0092 const char* SEventConfig::_MaxCurandDefault = NO_STATE_LIMIT ;
0093 #endif
0094 
0095 
0096 // HUH: former default was ALL_
0097 const char* SEventConfig::_GatherCompDefault = SComp::NONE_ ;
0098 const char* SEventConfig::_SaveCompDefault = SComp::NONE_ ;
0099 
0100 float SEventConfig::_PropagateEpsilonDefault = 0.05f ;
0101 float SEventConfig::_PropagateEpsilon0Default = 0.05f ;
0102 const char* SEventConfig::_PropagateEpsilon0MaskDefault = "TO,CK,SI,SC,RE" ; // THESE MOSTLY HAPPEN AWAY FROM BOUNDARIES
0103 unsigned SEventConfig::_PropagateRefineDefault = 0u ;
0104 float SEventConfig::_PropagateRefineDistanceDefault = 5000.f ;
0105 
0106 
0107 const char* SEventConfig::_InputGenstepDefault = nullptr ;
0108 const char* SEventConfig::_InputGenstepSelectionDefault = nullptr ;
0109 const char* SEventConfig::_InputPhotonDefault = nullptr ;
0110 const char* SEventConfig::_InputPhotonFrameDefault = nullptr ;
0111 float       SEventConfig::_InputPhotonChangeTimeDefault = -1.f ;   // -ve time means leave ASIS
0112 const char* SEventConfig::_InputPhotonRecordTimeDefault = nullptr ;   // ns
0113 const char* SEventConfig::_InputPhotonRecordSliceDefault = nullptr ;
0114 
0115 int         SEventConfig::_IntegrationMode = ssys::getenvint(kIntegrationMode, _IntegrationModeDefault );
0116 const char* SEventConfig::_EventMode = ssys::getenvvar(kEventMode, _EventModeDefault );
0117 const char* SEventConfig::_EventName  = ssys::getenvvar(kEventName,  _EventNameDefault );
0118 const char* SEventConfig::_DeviceName  = nullptr ;
0119 int         SEventConfig::_RunningMode = SRM::Type(ssys::getenvvar(kRunningMode, _RunningModeDefault));
0120 
0121 
0122 
0123 
0124 int         SEventConfig::_StartIndex = ssys::getenvint(kStartIndex, _StartIndexDefault );
0125 int         SEventConfig::_NumEvent = ssys::getenvint(kNumEvent, _NumEventDefault );
0126 
0127 std::vector<int64_t>* SEventConfig::_GetNumPhotonPerEvent()
0128 {
0129     const char* spec = ssys::getenvvar(kNumPhoton,  _NumPhotonDefault );
0130     return sstr::ParseIntSpecList<int64_t>( spec, ',' );
0131 }
0132 std::vector<int64_t>* SEventConfig::_NumPhotonPerEvent = _GetNumPhotonPerEvent() ;
0133 
0134 
0135 std::vector<int64_t>* SEventConfig::_GetNumGenstepPerEvent()
0136 {
0137     const char* spec = ssys::getenvvar(kNumGenstep,  _NumGenstepDefault );
0138     return sstr::ParseIntSpecList<int64_t>( spec, ',' );
0139 }
0140 std::vector<int64_t>* SEventConfig::_NumGenstepPerEvent = _GetNumGenstepPerEvent() ;
0141 
0142 
0143 /**
0144 SEventConfig::_GetNumPhoton
0145 ----------------------------
0146 
0147 Used by some tests that define a sequence of photon counts as inputs::
0148 
0149     OPTICKS_NUM_PHOTON=M1,2,3,4 OPTICKS_NUM_EVENT=4 SEventConfigTest
0150     OPTICKS_NUM_PHOTON=G1,2,3,4 OPTICKS_NUM_EVENT=4 SEventConfigTest
0151 
0152 
0153 Expected to define the below of envvars with equal numbers of entries::
0154 
0155    OPTICKS_NUM_PHOTON=M1,2,3,4
0156    OPTICKS_NUM_GENSTEP=1,1,1,1
0157 
0158 
0159 **/
0160 int64_t SEventConfig::_GetNumPhoton(int idx)
0161 {
0162     if(_NumPhotonPerEvent == nullptr) return 0 ;
0163 
0164     int nevt0 = NumEvent() ;
0165     int nevt1 = _NumPhotonPerEvent->size() ;
0166     bool match = nevt0 == nevt1 ;
0167     LOG_IF(fatal, !match)
0168         << " NumEvent MISMATCH BETWEEN "
0169         << std::endl
0170         << " nevt0:_NumEvent               " << nevt0 << "( from " << kNumEvent  << ":" << ( getenv(kNumEvent) ? getenv(kNumEvent) : "-" ) << ") "
0171         << " nevt1:_NumPhotonPerEvent.size " << nevt1 << "( from " << kNumPhoton << ":" << ( getenv(kNumPhoton) ? getenv(kNumPhoton) : "-" ) << ") "
0172         ;
0173     assert( match );
0174     if(idx < 0 ) idx += nevt0 ;   // allow -ve indices to count from the back
0175     if(idx >= nevt0) return 0 ;
0176 
0177     return (*_NumPhotonPerEvent)[idx] ;
0178 }
0179 
0180 
0181 int64_t SEventConfig::_GetNumGenstep(int idx)
0182 {
0183     if(_NumGenstepPerEvent == nullptr) return 0 ;
0184 
0185     int nevt0 = NumEvent() ;
0186     int nevt1 = _NumGenstepPerEvent->size() ;
0187     bool match = nevt0 == nevt1 ;
0188     LOG_IF(fatal, !match)
0189         << " NumEvent MISMATCH BETWEEN "
0190         << std::endl
0191         << " nevt0:_NumEvent                " << nevt0 << "( from " << kNumEvent   << ":" << ( getenv(kNumEvent) ? getenv(kNumEvent) : "-" ) << ") "
0192         << " nevt1:_NumGenstepPerEvent.size " << nevt1 << "( from " << kNumGenstep << ":" << ( getenv(kNumGenstep) ? getenv(kNumGenstep) : "-" ) << ") "
0193         ;
0194     assert( match );
0195     if(idx < 0 ) idx += nevt0 ;   // allow -ve indices to count from the back
0196     if(idx >= nevt0) return 0 ;
0197 
0198     return (*_NumGenstepPerEvent)[idx] ;
0199 }
0200 
0201 
0202 /**
0203 SEventConfig::_GetNumEvent
0204 --------------------------
0205 
0206 ::
0207 
0208     OPTICKS_NUM_EVENT=4 OPTICKS_NUM_PHOTON=M1:3 OPTICKS_NUM_GENSTEP=M1:3 SEventConfigTest
0209 
0210 **/
0211 
0212 int SEventConfig::_GetNumEvent()
0213 {
0214     bool have_NumPhotonPerEvent = _NumPhotonPerEvent && _NumPhotonPerEvent->size() > 0 ;
0215     bool have_NumGenstepPerEvent = _NumGenstepPerEvent && _NumGenstepPerEvent->size() > 0 ;
0216 
0217     int numEvent_fromPhotonList  = have_NumPhotonPerEvent ? _NumPhotonPerEvent->size() : 0 ;
0218     int numEvent_fromGenstepList = have_NumGenstepPerEvent ? _NumGenstepPerEvent->size() : 0 ;
0219     int numEvent_fromList = std::max(numEvent_fromPhotonList, numEvent_fromGenstepList);
0220 
0221     if( numEvent_fromPhotonList > 0 && numEvent_fromGenstepList > 0 )
0222     {
0223         assert( numEvent_fromPhotonList == numEvent_fromGenstepList );
0224     }
0225 
0226     bool override_NumEvent = numEvent_fromList > 0  && numEvent_fromList != _NumEvent ;
0227 
0228     LOG_IF(error, override_NumEvent )
0229         << " Overriding NumEvent "
0230         << "(" << kNumEvent  << ")"
0231         << " value " << _NumEvent
0232         << " as inconsistent with NumPhoton OR NumGenstep list length "
0233         << "\n"
0234         << "(" << kNumPhoton << ")"
0235         << " numEvent_fromPhotonList " << numEvent_fromPhotonList
0236         << "\n"
0237         << "(" << kNumGenstep << ")"
0238         << " numEvent_fromGenstepList " << numEvent_fromGenstepList
0239         ;
0240     return override_NumEvent ? numEvent_fromList : _NumEvent ;
0241 }
0242 
0243 
0244 int64_t SEventConfig::NumPhoton( int idx){ return _GetNumPhoton(idx) ; }
0245 
0246 int SEventConfig::NumGenstep(int idx){ return _GetNumGenstep(idx) ; }
0247 int SEventConfig::NumEvent(){         return _GetNumEvent() ; }
0248 int SEventConfig::EventIndex(int idx){ return _StartIndex + idx ; }
0249 int SEventConfig::EventIndexArg(int index){ return index == MISSING_INDEX ? -1 : index - _StartIndex ; }
0250 
0251 bool SEventConfig::IsFirstEvent(int idx){ return idx == 0 ; }  // 0-based idx (such as Geant4 eventID)
0252 bool SEventConfig::IsLastEvent(int idx){ return idx == NumEvent()-1 ; }  // 0-based idx (such as Geant4 eventID)
0253 
0254 
0255 int         SEventConfig::_EventSkipahead = ssys::getenvint(kEventSkipahead, _EventSkipaheadDefault) ;
0256 const char* SEventConfig::_G4StateSpec  = ssys::getenvvar(kG4StateSpec,  _G4StateSpecDefault );
0257 int         SEventConfig::_G4StateRerun = ssys::getenvint(kG4StateRerun, _G4StateRerunDefault) ;
0258 
0259 int64_t SEventConfig::_MaxCurand    = ssys::getenv_ParseInt64(kMaxCurand,   _MaxCurandDefault ) ;
0260 int64_t SEventConfig::_MaxSlot      = ssys::getenv_ParseInt64(kMaxSlot,     _MaxSlotDefault ) ;
0261 int64_t SEventConfig::_MaxGenstep   = ssys::getenv_ParseInt64(kMaxGenstep,  _MaxGenstepDefault ) ;
0262 int64_t SEventConfig::_MaxPhoton    = ssys::getenv_ParseInt64(kMaxPhoton,   _MaxPhotonDefault ) ;
0263 int64_t SEventConfig::_MaxSimtrace  = ssys::getenv_ParseInt64(kMaxSimtrace, _MaxSimtraceDefault ) ;
0264 
0265 float SEventConfig::_MaxTime    = ssys::getenvfloat(kMaxTime, _MaxTimeDefault );    // ns
0266 int SEventConfig::_MaxBounce    = ssys::getenvint(kMaxBounce, _MaxBounceDefault ) ;
0267 int SEventConfig::_MaxRecord    = ssys::getenvint(kMaxRecord, _MaxRecordDefault ) ;
0268 int SEventConfig::_MaxRec       = ssys::getenvint(kMaxRec, _MaxRecDefault ) ;
0269 int SEventConfig::_MaxAux       = ssys::getenvint(kMaxAux, _MaxAuxDefault ) ;
0270 int SEventConfig::_MaxSup       = ssys::getenvint(kMaxSup, _MaxSupDefault ) ;
0271 int SEventConfig::_MaxSeq       = ssys::getenvint(kMaxSeq,  _MaxSeqDefault ) ;
0272 int SEventConfig::_MaxPrd       = ssys::getenvint(kMaxPrd,  _MaxPrdDefault ) ;
0273 int SEventConfig::_MaxTag       = ssys::getenvint(kMaxTag,  _MaxTagDefault ) ;
0274 int SEventConfig::_MaxFlat      = ssys::getenvint(kMaxFlat,  _MaxFlatDefault ) ;
0275 
0276 int SEventConfig::_ModeSave     = ssys::getenvint(  kModeSave, _ModeSaveDefault ) ;
0277 int SEventConfig::_ModeClient     = ssys::getenvint(  kModeClient, _ModeClientDefault ) ;
0278 int SEventConfig::_ModeLite      = ssys::getenvint(  kModeLite,  _ModeLiteDefault ) ;
0279 int SEventConfig::_ModeMerge     = ssys::getenvint(  kModeMerge, _ModeMergeDefault ) ;
0280 float SEventConfig::_MergeWindow = ssys::getenvfloat(kMergeWindow,  _MergeWindowDefault ) ;
0281 
0282 float SEventConfig::_MaxExtentDomain  = ssys::getenvfloat(kMaxExtentDomain, _MaxExtentDomainDefault );
0283 float SEventConfig::_MaxTimeDomain    = ssys::getenvfloat(kMaxTimeDomain,   _MaxTimeDomainDefault );    // ns
0284 
0285 const char* SEventConfig::_OutFold = ssys::getenvvar(kOutFold, _OutFoldDefault );
0286 const char* SEventConfig::_OutName = ssys::getenvvar(kOutName, _OutNameDefault );
0287 const char* SEventConfig::_EventReldir = ssys::getenvvar(kEventReldir, _EventReldirDefault );
0288 int SEventConfig::_RGMode = SRG::Type(ssys::getenvvar(kRGMode, _RGModeDefault)) ;
0289 unsigned SEventConfig::_HitMask  = OpticksPhoton::GetFlagMask(ssys::getenvvar(kHitMask, _HitMaskDefault )) ;
0290 
0291 unsigned SEventConfig::_GatherComp  = SComp::Mask(ssys::getenvvar(kGatherComp, _GatherCompDefault )) ;
0292 unsigned SEventConfig::_SaveComp    = SComp::Mask(ssys::getenvvar(kSaveComp,   _SaveCompDefault )) ;
0293 
0294 
0295 float SEventConfig::_PropagateEpsilon = ssys::getenvfloat(kPropagateEpsilon, _PropagateEpsilonDefault ) ;
0296 float SEventConfig::_PropagateEpsilon0 = ssys::getenvfloat(kPropagateEpsilon0, _PropagateEpsilon0Default ) ;
0297 unsigned SEventConfig::_PropagateEpsilon0Mask  = OpticksPhoton::GetFlagMask(ssys::getenvvar(kPropagateEpsilon0Mask, _PropagateEpsilon0MaskDefault )) ;
0298 std::string SEventConfig::PropagateEpsilon0MaskLabel(){  return OpticksPhoton::FlagMaskLabel( _PropagateEpsilon0Mask ) ; }
0299 unsigned SEventConfig::_PropagateRefine = ssys::getenvunsigned(kPropagateRefine, _PropagateRefineDefault ) ;
0300 float SEventConfig::_PropagateRefineDistance = ssys::getenvfloat(kPropagateRefineDistance, _PropagateRefineDistanceDefault ) ;
0301 
0302 const char* SEventConfig::_InputGenstep = ssys::getenvvar(kInputGenstep, _InputGenstepDefault );
0303 const char* SEventConfig::_InputGenstepSelection = ssys::getenvvar(kInputGenstepSelection, _InputGenstepSelectionDefault );
0304 const char* SEventConfig::_InputPhoton = ssys::getenvvar(kInputPhoton, _InputPhotonDefault );
0305 const char* SEventConfig::_InputPhotonFrame = ssys::getenvvar(kInputPhotonFrame, _InputPhotonFrameDefault );
0306 float       SEventConfig::_InputPhotonChangeTime = ssys::getenvfloat(kInputPhotonChangeTime, _InputPhotonChangeTimeDefault ) ;
0307 const char* SEventConfig::_InputPhotonRecordTime = ssys::getenvvar(kInputPhotonRecordTime, _InputPhotonRecordTimeDefault ) ;
0308 const char* SEventConfig::_InputPhotonRecordSlice = ssys::getenvvar(kInputPhotonRecordSlice, _InputPhotonRecordSliceDefault );
0309 
0310 
0311 int         SEventConfig::IntegrationMode(){ return _IntegrationMode ; }
0312 bool        SEventConfig::GPU_Simulation(){  return _IntegrationMode == 1 || _IntegrationMode == 3 ; }
0313 bool        SEventConfig::CPU_Simulation(){  return _IntegrationMode == 2 || _IntegrationMode == 3 ; }
0314 
0315 const char* SEventConfig::EventMode(){ return _EventMode ; }
0316 const char* SEventConfig::EventName(){ return _EventName ; }
0317 const char* SEventConfig::DeviceName(){ return _DeviceName ; }
0318 bool        SEventConfig::HasDevice(){ return _DeviceName != nullptr ; }
0319 
0320 
0321 /**
0322 SEventConfig::RunningMode controlled via envvar OPTICKS_RUNNING_MODE
0323 ----------------------------------------------------------------------
0324 
0325 * SRM_DEFAULT
0326 * SRM_TORCH
0327 * SRM_INPUT_PHOTON
0328 * SRM_INPUT_GENSTEP
0329 * SRM_GUN
0330 
0331 
0332 **/
0333 
0334 
0335 int         SEventConfig::RunningMode(){ return _RunningMode ; }
0336 const char* SEventConfig::RunningModeLabel(){ return SRM::Name(_RunningMode) ; }
0337 
0338 bool SEventConfig::IsRunningModeDefault(){      return RunningMode() == SRM_DEFAULT ; }
0339 bool SEventConfig::IsRunningModeG4StateSave(){  return RunningMode() == SRM_G4STATE_SAVE ; }
0340 bool SEventConfig::IsRunningModeG4StateRerun(){ return RunningMode() == SRM_G4STATE_RERUN ; }
0341 
0342 bool SEventConfig::IsRunningModeTorch(){         return RunningMode() == SRM_TORCH ; }
0343 bool SEventConfig::IsRunningModeInputPhoton(){   return RunningMode() == SRM_INPUT_PHOTON ; }
0344 bool SEventConfig::IsRunningModeInputGenstep(){  return RunningMode() == SRM_INPUT_GENSTEP ; }
0345 bool SEventConfig::IsRunningModeGun(){           return RunningMode() == SRM_GUN ; }
0346 
0347 
0348 int SEventConfig::EventSkipahead(){ return _EventSkipahead ; }
0349 const char* SEventConfig::G4StateSpec(){  return _G4StateSpec ; }
0350 
0351 /**
0352 SEventConfig::G4StateRerun
0353 ----------------------------
0354 
0355 When rerun mode is not enabled returns -1 even when rerun id is set.
0356 
0357 For a single photon rerun example see u4/tests/U4SimulateTest.cc
0358 which uses U4Recorder::saveOrLoadStates from U4Recorder::PreUserTrackingAction_Optical
0359 
0360 **/
0361 int SEventConfig::G4StateRerun()
0362 {
0363     bool rerun_enabled = IsRunningModeG4StateRerun() ;
0364     return rerun_enabled && _G4StateRerun > -1 ? _G4StateRerun : -1  ;
0365 }
0366 
0367 
0368 
0369 int64_t SEventConfig::MaxCurand(){ return _MaxCurand ; }
0370 int64_t SEventConfig::MaxSlot(){   return _MaxSlot ; }
0371 
0372 int64_t SEventConfig::MaxGenstep(){  return _MaxGenstep ; }
0373 int64_t SEventConfig::MaxPhoton(){   return _MaxPhoton ; }
0374 int64_t SEventConfig::MaxSimtrace(){   return _MaxSimtrace ; }
0375 
0376 
0377 int64_t SEventConfig::MaxBounce(){   return _MaxBounce ; }
0378 float SEventConfig::MaxTime(){   return _MaxTime ; }
0379 
0380 int64_t SEventConfig::MaxRecord(){   return _MaxRecord ; }
0381 int64_t SEventConfig::MaxRec(){      return _MaxRec ; }
0382 int64_t SEventConfig::MaxAux(){      return _MaxAux ; }
0383 int64_t SEventConfig::MaxSup(){      return _MaxSup ; }
0384 int64_t SEventConfig::MaxSeq(){      return _MaxSeq ; }
0385 int64_t SEventConfig::MaxPrd(){      return _MaxPrd ; }
0386 int64_t SEventConfig::MaxTag(){      return _MaxTag ; }
0387 int64_t SEventConfig::MaxFlat(){     return _MaxFlat ; }
0388 
0389 int64_t SEventConfig::ModeSave(){    return _ModeSave ; }
0390 int64_t SEventConfig::ModeClient(){    return _ModeClient ; }
0391 int64_t SEventConfig::ModeLite(){      return _ModeLite ; }
0392 int64_t SEventConfig::ModeMerge(){     return _ModeMerge ; }
0393 float   SEventConfig::MergeWindow(){   return _MergeWindow ; }
0394 
0395 float SEventConfig::MaxExtentDomain(){ return _MaxExtentDomain ; }
0396 float SEventConfig::MaxTimeDomain(){   return _MaxTimeDomain ; }
0397 
0398 const char* SEventConfig::OutFold(){   return _OutFold ; }
0399 const char* SEventConfig::OutName(){   return _OutName ; }
0400 
0401 /**
0402 SEventConfig::EventReldir
0403 ---------------------------
0404 
0405 Usually left at the default of::
0406 
0407      ALL${VERSION:-0}_${OPTICKS_EVENT_NAME:-no_opticks_event_name}
0408 
0409 Note that if OPTICKS_EVENT_NAME is defined it is constrained by
0410 SEventConfig::Initialize_EventName to contain the build context string,
0411 eg Debug_Philox.
0412 
0413 **/
0414 const char* SEventConfig::EventReldir(){   return _EventReldir ; }
0415 unsigned SEventConfig::HitMask(){     return _HitMask ; }
0416 
0417 unsigned SEventConfig::GatherComp(){  return _GatherComp ; }
0418 unsigned SEventConfig::SaveComp(){    return _SaveComp ; }
0419 
0420 
0421 float SEventConfig::PropagateEpsilon(){ return _PropagateEpsilon ; }
0422 float SEventConfig::PropagateEpsilon0(){ return _PropagateEpsilon0 ; }
0423 unsigned SEventConfig::PropagateEpsilon0Mask(){ return _PropagateEpsilon0Mask ; }
0424 unsigned SEventConfig::PropagateRefine(){         return _PropagateRefine ; }
0425 float    SEventConfig::PropagateRefineDistance(){ return _PropagateRefineDistance ; }
0426 
0427 
0428 /**
0429 SEventConfig::_InputGenstepPath
0430 --------------------------------
0431 
0432 OPTICKS_INPUT_GENSTEP
0433     must provide a path with %d format tokens that are filled with idx
0434 
0435 **/
0436 
0437 const char* SEventConfig::_InputGenstepPath(int idx)
0438 {
0439     return sstr::Format(_InputGenstep, idx ) ;
0440 }
0441 const char* SEventConfig::InputGenstep(int idx)
0442 {
0443     return ( idx == -1 || _InputGenstep == nullptr ) ? _InputGenstep : _InputGenstepPath(idx) ;
0444 }
0445 const char* SEventConfig::InputGenstepSelection(int /*idx*/) // for now one selection for all eventID
0446 {
0447     return _InputGenstepSelection  ;
0448 }
0449 
0450 
0451 
0452 
0453 
0454 
0455 bool SEventConfig::InputGenstepPathExists(int idx)
0456 {
0457     const char* path = SEventConfig::InputGenstep(idx);
0458     return path ? spath::Exists(path) : false ;
0459 }
0460 
0461 
0462 
0463 /**
0464 SEventConfig::InputPhoton control via OPTICKS_INPUT_PHOTON envvar
0465 ------------------------------------------------------------------
0466 
0467 Pick the array of input_photons to use,
0468 default none, eg "RainXZ_Z230_10k_f8.npy"
0469 
0470 * when configured SEvt::initInputPhoton loads the input photons array
0471 * within Opticks the photons are uploaded to the GPU with QEvt::setInputPhoton
0472 
0473 Techniques to get the same input photons into Geant4 simulations, eg for A-B comparisons
0474 between Opticks and Geant4 depend on the level of access to G4Event that is
0475 afforded by the simulation framework.
0476 
0477 * JUNOSW/GtOpticksTool "GenTool" uses a mutate interface to inject the photons via HepMC
0478 
0479 * G4CXApp.h used from the raindrop example uses are more direct approach with
0480   U4VPrimaryGenerator::GeneratePrimaries_From_Photons using direct access to G4Event
0481 
0482 
0483 When input photons are configured and found the accessor SEvt::hasInputPhoton
0484 returns true which is consulted by SEvt::addInputGenstep resulting in creation
0485 of the input photon genstep via SEvent::MakeInputPhotonGenstep.
0486 
0487 Adding this fabricated input photon genstep kicks off the configured allocations.
0488 
0489 **/
0490 
0491 const char* SEventConfig::InputPhoton(){   return _InputPhoton ; }
0492 
0493 
0494 /**
0495 SEventConfig::InputPhotonFrame control via OPTICKS_INPUT_PHOTON_FRAME envvar
0496 ------------------------------------------------------------------------------
0497 
0498 Pick the frame in which to inject the input photons,
0499 using MOI style specification eg "NNVT:0:1000"
0500 
0501 
0502 **/
0503 const char* SEventConfig::InputPhotonFrame(){       return _InputPhotonFrame ; }
0504 float       SEventConfig::InputPhotonChangeTime(){  return _InputPhotonChangeTime ; }
0505 const char* SEventConfig::InputPhotonRecordTime(){  return _InputPhotonRecordTime ; }
0506 const char* SEventConfig::InputPhotonRecordSlice(){ return _InputPhotonRecordSlice ; }
0507 
0508 
0509 int SEventConfig::RGMode(){  return _RGMode ; }
0510 bool SEventConfig::IsRGModeRender(){   return RGMode() == SRG_RENDER   ; }
0511 bool SEventConfig::IsRGModeSimtrace(){ return RGMode() == SRG_SIMTRACE ; }
0512 bool SEventConfig::IsRGModeSimulate(){ return RGMode() == SRG_SIMULATE ; }
0513 bool SEventConfig::IsRGModeTest(){     return RGMode() == SRG_TEST ; }
0514 const char* SEventConfig::RGModeLabel(){ return SRG::Name(_RGMode) ; }
0515 
0516 
0517 
0518 
0519 void SEventConfig::SetDebugHeavy(){         SetEventMode(DebugHeavy) ; }
0520 void SEventConfig::SetDebugLite(){          SetEventMode(DebugLite) ; }
0521 void SEventConfig::SetNothing(){            SetEventMode(Nothing)           ; }
0522 void SEventConfig::SetMinimal(){            SetEventMode(Minimal)           ; }
0523 void SEventConfig::SetHit(){                SetEventMode(Hit)               ; }
0524 void SEventConfig::SetHitPhoton(){          SetEventMode(HitPhoton)         ; }
0525 void SEventConfig::SetHitPhotonSeq(){       SetEventMode(HitPhotonSeq)      ; }
0526 void SEventConfig::SetHitSeq(){             SetEventMode(HitSeq)            ; }
0527 
0528 bool SEventConfig::IsDebugHeavy(){        return _EventMode && strcmp(_EventMode, DebugHeavy) == 0 ; }
0529 bool SEventConfig::IsDebugLite(){         return _EventMode && strcmp(_EventMode, DebugLite) == 0 ; }
0530 bool SEventConfig::IsNothing(){           return _EventMode && strcmp(_EventMode, Nothing) == 0 ; }
0531 bool SEventConfig::IsMinimal(){           return _EventMode && strcmp(_EventMode, Minimal) == 0 ; }
0532 bool SEventConfig::IsHit(){               return _EventMode && strcmp(_EventMode, Hit) == 0 ; }
0533 bool SEventConfig::IsHitPhoton(){         return _EventMode && strcmp(_EventMode, HitPhoton) == 0 ; }
0534 bool SEventConfig::IsHitPhotonSeq(){      return _EventMode && strcmp(_EventMode, HitPhotonSeq) == 0 ; }
0535 bool SEventConfig::IsHitSeq(){            return _EventMode && strcmp(_EventMode, HitSeq) == 0 ; }
0536 
0537 bool SEventConfig::IsMinimalOrNothing(){ return IsMinimal() ||  IsNothing() ; }
0538 
0539 
0540 std::string SEventConfig::DescEventMode()  // static
0541 {
0542     std::stringstream ss ;
0543     ss
0544        << "[SEventConfig::DescEventMode\n"
0545        << " EventMode[" << EventMode() << "] EventMode_NOTE[" << EventMode_NOTE() << "]"
0546        << "\n"
0547        << "]SEventConfig::DescEventMode\n"
0548        ;
0549 
0550     std::string str = ss.str() ;
0551     return str ;
0552 }
0553 
0554 std::string SEventConfig::DescEventModeCheck()  // static
0555 {
0556     std::stringstream ss ;
0557     ss
0558        << "[SEventConfig::DescEventModeCheck\n"
0559        << " IsDebugHeavy   " << ( IsDebugHeavy() ? "YES" : "NO " )
0560        << "\n"
0561        << " IsDebugLite    " << ( IsDebugLite() ? "YES" : "NO " )
0562        << "\n"
0563        << " IsNothing      " << ( IsNothing() ? "YES" : "NO " )
0564        << "\n"
0565        << " IsMinimal      " << ( IsMinimal() ? "YES" : "NO " )
0566        << "\n"
0567        << " IsHit          " << ( IsHit() ? "YES" : "NO " )
0568        << "\n"
0569        << " IsHitPhoton    " << ( IsHitPhoton() ? "YES" : "NO " )
0570        << "\n"
0571        << " IsHitPhotonSeq " << ( IsHitPhotonSeq() ? "YES" : "NO " )
0572        << "\n"
0573        << " IsHitSeq       " << ( IsHitSeq() ? "YES" : "NO " )
0574        << "\n"
0575        << "]SEventConfig::DescEventModeCheck\n"
0576        ;
0577 
0578     std::string str = ss.str() ;
0579     return str ;
0580 }
0581 
0582 
0583 void SEventConfig::SetIntegrationMode(int mode){ _IntegrationMode = mode ; LIMIT_Check() ; }
0584 void SEventConfig::SetEventMode(const char* mode){ _EventMode = mode ? strdup(mode) : nullptr ; LIMIT_Check() ; }
0585 void SEventConfig::SetEventName(const char* name){ _EventName = name ? strdup(name) : nullptr ; LIMIT_Check() ; }
0586 void SEventConfig::SetRunningMode(const char* mode){ _RunningMode = SRM::Type(mode) ; LIMIT_Check() ; }
0587 
0588 void SEventConfig::SetStartIndex(int index0){        _StartIndex = index0 ; LIMIT_Check() ; }
0589 void SEventConfig::SetNumEvent(int nevt){            _NumEvent = nevt ; LIMIT_Check() ; }
0590 void SEventConfig::SetG4StateSpec(const char* spec){ _G4StateSpec = spec ? strdup(spec) : nullptr ; LIMIT_Check() ; }
0591 void SEventConfig::SetG4StateRerun(int id){          _G4StateRerun = id ; LIMIT_Check() ; }
0592 
0593 void SEventConfig::SetMaxCurand(int max_curand){ _MaxCurand = max_curand ; LIMIT_Check() ; }
0594 void SEventConfig::SetMaxSlot(int max_slot){     _MaxSlot    = max_slot  ; LIMIT_Check() ; }
0595 
0596 void SEventConfig::SetMaxGenstep(int max_genstep){ _MaxGenstep = max_genstep ; LIMIT_Check() ; }
0597 void SEventConfig::SetMaxPhoton( int max_photon){  _MaxPhoton  = max_photon  ; LIMIT_Check() ; }
0598 void SEventConfig::SetMaxSimtrace( int max_simtrace){  _MaxSimtrace  = max_simtrace  ; LIMIT_Check() ; }
0599 
0600 void SEventConfig::SetMaxBounce( int max_bounce){  _MaxBounce  = max_bounce  ; LIMIT_Check() ; }
0601 void SEventConfig::SetMaxTime(   float max_time){   _MaxTime   = max_time  ; LIMIT_Check() ; }
0602 
0603 void SEventConfig::SetMaxRecord( int max_record){  _MaxRecord  = max_record  ; LIMIT_Check() ; }
0604 void SEventConfig::SetMaxRec(    int max_rec){     _MaxRec     = max_rec     ; LIMIT_Check() ; }
0605 void SEventConfig::SetMaxAux(    int max_aux){     _MaxAux     = max_aux     ; LIMIT_Check() ; }
0606 void SEventConfig::SetMaxSup(    int max_sup){     _MaxSup     = max_sup     ; LIMIT_Check() ; }
0607 void SEventConfig::SetMaxSeq(    int max_seq){     _MaxSeq     = max_seq     ; LIMIT_Check() ; }
0608 void SEventConfig::SetMaxPrd(    int max_prd){     _MaxPrd     = max_prd     ; LIMIT_Check() ; }
0609 void SEventConfig::SetMaxTag(    int max_tag){     _MaxTag     = max_tag     ; LIMIT_Check() ; }
0610 void SEventConfig::SetMaxFlat(    int max_flat){     _MaxFlat    = max_flat     ; LIMIT_Check() ; }
0611 
0612 void SEventConfig::SetModeSave(  int mode ){    _ModeSave  = mode  ; LIMIT_Check() ; ORDER_Check() ; }
0613 void SEventConfig::SetModeClient(  int mode ){    _ModeClient  = mode  ; LIMIT_Check() ; ORDER_Check() ; }
0614 void SEventConfig::SetModeLite(   int mode ){    _ModeLite   = mode  ; LIMIT_Check() ; ORDER_Check() ; }
0615 void SEventConfig::SetModeMerge(  int mode ){    _ModeMerge  = mode  ; LIMIT_Check() ; ORDER_Check() ; }
0616 void SEventConfig::SetMergeWindow( float merge_window_ns ){  _MergeWindow  = merge_window_ns    ; LIMIT_Check() ; ORDER_Check() ; }
0617 
0618 void SEventConfig::SetMaxExtentDomain( float max_extent){ _MaxExtentDomain = max_extent  ; LIMIT_Check() ; }
0619 void SEventConfig::SetMaxTimeDomain(   float max_time){   _MaxTimeDomain = max_time  ; LIMIT_Check() ; }
0620 
0621 
0622 void SEventConfig::SetOutFold(   const char* outfold){   _OutFold = outfold ? strdup(outfold) : nullptr ; LIMIT_Check() ; }
0623 void SEventConfig::SetOutName(   const char* outname){   _OutName = outname ? strdup(outname) : nullptr ; LIMIT_Check() ; }
0624 void SEventConfig::SetEventReldir(   const char* v){   _EventReldir = v ? strdup(v) : nullptr ; LIMIT_Check() ; }
0625 void SEventConfig::SetHitMask(   const char* abrseq, char delim){  _HitMask = OpticksPhoton::GetFlagMask(abrseq,delim) ; }
0626 
0627 void SEventConfig::SetRGModeSimulate(){  SetRGMode( SRG::SIMULATE_ ); }
0628 void SEventConfig::SetRGModeSimtrace(){  SetRGMode( SRG::SIMTRACE_ ); }
0629 void SEventConfig::SetRGModeRender(){    SetRGMode( SRG::RENDER_ ); }
0630 void SEventConfig::SetRGModeTest(){      SetRGMode( SRG::TEST_ ); }
0631 
0632 void SEventConfig::SetRGMode( const char* mode)
0633 {
0634     int prior_RGMode = _RGMode ;
0635     _RGMode = SRG::Type(mode) ;
0636     bool changed_mode = prior_RGMode != _RGMode ;
0637     if(changed_mode)
0638     {
0639         LOG(LEVEL) << " mode changed calling Initialize_Comp " ;
0640         Initialize_Comp();
0641         LOG(LEVEL) << " DescGatherComp " << DescGatherComp() ;
0642         LOG(LEVEL) << " DescSaveComp   " << DescSaveComp() ;
0643     }
0644     LIMIT_Check() ;
0645 }
0646 
0647 
0648 
0649 
0650 
0651 void SEventConfig::SetPropagateEpsilon(float eps){ _PropagateEpsilon = eps ; LIMIT_Check() ; }
0652 void SEventConfig::SetPropagateEpsilon0(float eps){ _PropagateEpsilon0 = eps ; LIMIT_Check() ; }
0653 void SEventConfig::SetPropagateEpsilon0Mask(const char* abrseq, char delim){ _PropagateEpsilon0Mask = OpticksPhoton::GetFlagMask(abrseq,delim) ; }
0654 void SEventConfig::SetPropagateRefine(        unsigned refine){       _PropagateRefine         = refine ; LIMIT_Check() ; }
0655 void SEventConfig::SetPropagateRefineDistance(float refine_distance){ _PropagateRefineDistance = refine_distance ; LIMIT_Check() ; }
0656 
0657 void SEventConfig::SetInputGenstep(const char* ig){   _InputGenstep = ig ? strdup(ig) : nullptr ; LIMIT_Check() ; }
0658 void SEventConfig::SetInputGenstepSelection(const char* igsel){   _InputGenstepSelection = igsel ? strdup(igsel) : nullptr ; LIMIT_Check() ; }
0659 void SEventConfig::SetInputPhoton(const char* ip){   _InputPhoton = ip ? strdup(ip) : nullptr ; LIMIT_Check() ; }
0660 void SEventConfig::SetInputPhotonFrame(const char* ip){   _InputPhotonFrame = ip ? strdup(ip) : nullptr ; LIMIT_Check() ; }
0661 void SEventConfig::SetInputPhotonChangeTime(float t0){    _InputPhotonChangeTime = t0 ; LIMIT_Check() ; }
0662 void SEventConfig::SetInputPhotonRecordTime(const char* rt){    _InputPhotonRecordTime = rt ? strdup(rt) : nullptr ; LIMIT_Check() ; }
0663 void SEventConfig::SetInputPhotonRecordSlice(const char* rs){   _InputPhotonRecordSlice = rs ? strdup(rs) : nullptr ; LIMIT_Check() ; }
0664 
0665 void SEventConfig::SetGatherComp_(unsigned mask){ _GatherComp = mask ; }
0666 void SEventConfig::SetGatherComp(const char* names, char delim){  SetGatherComp_( SComp::Mask(names,delim)) ; }
0667 bool SEventConfig::GatherRecord(){  return ( _GatherComp & SCOMP_RECORD ) != 0 ; }
0668 
0669 void SEventConfig::SetSaveComp_(unsigned mask){ _SaveComp = mask ; }
0670 void SEventConfig::SetSaveComp(const char* names, char delim){  SetSaveComp_( SComp::Mask(names,delim)) ; }
0671 bool SEventConfig::IsCompConfigured(){ return _GatherComp != 0 || _SaveComp != 0 ; }
0672 
0673 
0674 //std::string SEventConfig::DescHitMask(){   return OpticksPhoton::FlagMaskLabel( _HitMask ) ; }
0675 std::string SEventConfig::HitMaskLabel(){  return OpticksPhoton::FlagMaskLabel( _HitMask ) ; }
0676 
0677 std::string SEventConfig::DescGatherComp(){ return SComp::Desc( _GatherComp ) ; }
0678 std::string SEventConfig::DescSaveComp(){   return SComp::Desc( _SaveComp ) ; } // used from SEvt::save
0679 
0680 
0681 /**
0682 SEventConfig::HasComp_
0683 -----------------------
0684 
0685 returns true when all bits set within the query mask (*q_mask* formed from *q_names* *q_delim*)
0686 are present within *comps*
0687 
0688 **/
0689 
0690 bool SEventConfig::HasComp_(unsigned comp, const char* q_names, char q_delim) // static
0691 {
0692     unsigned q_mask = SComp::Mask(q_names, q_delim);
0693     return ( comp & q_mask  ) == q_mask ;
0694 }
0695 
0696 /**
0697 SEventConfig::HasSaveComp
0698 -------------------------
0699 
0700 returns true when query mask components are all within the save components
0701 
0702 **/
0703 
0704 bool SEventConfig::HasSaveComp(const char* q_names, char q_delim)
0705 {
0706     return HasComp_(_SaveComp, q_names, q_delim ) ;
0707 }
0708 
0709 
0710 /**
0711 SEventConfig::HasGatherComp
0712 -------------------------
0713 
0714 returns true when query mask components are all within the gather components
0715 
0716 **/
0717 
0718 bool SEventConfig::HasGatherComp(const char* q_names, char q_delim)
0719 {
0720     return HasComp_(_GatherComp, q_names, q_delim ) ;
0721 }
0722 
0723 
0724 
0725 
0726 
0727 
0728 
0729 void SEventConfig::GatherCompList( std::vector<unsigned>& gather_comp )
0730 {
0731     SComp::CompListMask(gather_comp, GatherComp() );
0732 }
0733 int SEventConfig::NumGatherComp()
0734 {
0735     return SComp::CompListCount(GatherComp() );
0736 }
0737 
0738 void SEventConfig::SaveCompList( std::vector<unsigned>& save_comp )
0739 {
0740     SComp::CompListMask(save_comp, SaveComp() );
0741 }
0742 int SEventConfig::NumSaveComp()
0743 {
0744     return SComp::CompListCount(SaveComp() );
0745 }
0746 
0747 
0748 
0749 
0750 
0751 
0752 
0753 
0754 
0755 
0756 /**
0757 SEventConfig::LIMIT_Check
0758 ---------------------------
0759 
0760 Since moved to compound stag/sflat in stag.h
0761 MaxTag/MaxFlat must now either be 0 or 1, nothing else.
0762 Had a bug previously with MaxTag/MaxFlat 24 that
0763 caused huge memory allocations in debug event modes.
0764 
0765 **/
0766 
0767 int SEventConfig::RecordLimit() // static
0768 {
0769     return sseq::SLOTS ;
0770 }
0771 
0772 void SEventConfig::LIMIT_Check()
0773 {
0774    assert( _IntegrationMode >= -1 && _IntegrationMode <= 3 );
0775 
0776    //assert( _MaxBounce >= 0 && _MaxBounce <  LIMIT ) ;
0777    // MaxBounce should not in principal be limited
0778 
0779    assert( _MaxRecord >= 0 && _MaxRecord <= RecordLimit() ) ;
0780    assert( _MaxRec    >= 0 && _MaxRec    <= RecordLimit() ) ;
0781    assert( _MaxPrd    >= 0 && _MaxPrd    <= RecordLimit() ) ;
0782 
0783    assert( _MaxSeq    >= 0 && _MaxSeq    <= 1 ) ;
0784    assert( _MaxTag    >= 0 && _MaxTag    <= 1 ) ;
0785    assert( _MaxFlat   >= 0 && _MaxFlat   <= 1 ) ;
0786 
0787    assert( _ModeSave == 0 || _ModeSave == 1 );
0788    assert( _ModeClient == 0 || _ModeClient == 1 );
0789    assert( _ModeLite  == 0 || _ModeLite == 1 || _ModeLite == 2 ) ;   // 2 is for debug, in production only 0 or 1 expected
0790    assert( _ModeMerge == 0 || _ModeMerge == 1 );
0791    assert( _MergeWindow >= 0.f );
0792 
0793    assert( _StartIndex >= 0 );
0794 }
0795 
0796 void SEventConfig::ORDER_Check()
0797 {
0798     bool icc = IsCompConfigured();
0799     LOG_IF(fatal, icc)
0800        << "ORDER of config failure"
0801        << " methods attempting to change config called after SEventConfig::IsCompConfigured"
0802        << " [" << (icc ? "YES" : "NO " ) << "] "
0803        << " MOVE SEventConfig::Set calls prior to SEvt instanciation, ie very early to avoid this"
0804        ;
0805 
0806     assert( icc == false );
0807 }
0808 
0809 
0810 
0811 
0812 
0813 std::string SEventConfig::Desc()
0814 {
0815     std::stringstream ss ;
0816     ss
0817        << "[SEventConfig::Desc" << std::endl
0818        << std::setw(25) << kIntegrationMode
0819        << std::setw(20) << " IntegrationMode " << " : " << IntegrationMode()
0820        << std::endl
0821        << std::setw(25) << kEventMode
0822        << std::setw(20) << " EventMode " << " : " << EventMode()
0823        << std::endl
0824        << std::setw(25) << kEventName
0825        << std::setw(20) << " EventName " << " : " << ( EventName() ? EventName() : "-" )
0826        << std::endl
0827        << std::setw(25) << ""
0828        << std::setw(20) << " DeviceName " << " : " << ( DeviceName() ? DeviceName() : "-" )
0829        << std::endl
0830        << std::setw(25) << kRunningMode
0831        << std::setw(20) << " RunningMode " << " : " << RunningMode()
0832        << std::endl
0833        << std::setw(25) << ""
0834        << std::setw(20) << " RunningModeLabel " << " : " << RunningModeLabel()
0835        << std::endl
0836        << std::setw(25) << kNumEvent
0837        << std::setw(20) << " NumEvent " << " : " << NumEvent()
0838        << std::endl
0839        << std::setw(25) << kNumPhoton
0840        << std::setw(20) << " NumPhoton(0) " << " : " << NumPhoton(0)
0841        << std::setw(20) << " NumPhoton(1) " << " : " << NumPhoton(1)
0842        << std::setw(20) << " NumPhoton(-1) " << " : " << NumPhoton(-1)
0843        << std::endl
0844        << std::setw(25) << kNumGenstep
0845        << std::setw(20) << " NumGenstep(0) " << " : " << NumGenstep(0)
0846        << std::setw(20) << " NumGenstep(1) " << " : " << NumGenstep(1)
0847        << std::setw(20) << " NumGenstep(-1) " << " : " << NumGenstep(-1)
0848        << std::endl
0849        << std::setw(25) << kG4StateSpec
0850        << std::setw(20) << " G4StateSpec " << " : " << G4StateSpec()
0851        << std::endl
0852        << std::setw(25) << ""
0853        << std::setw(20) << " G4StateSpecNotes " << " : " << _G4StateSpecNotes
0854        << std::endl
0855        << std::setw(25) << kG4StateRerun
0856        << std::setw(20) << " G4StateRerun " << " : " << G4StateRerun()
0857        << std::endl
0858        << std::setw(25) << kMaxCurand
0859        << std::setw(20) << " MaxCurand " << " : " << MaxCurand()
0860        << std::setw(20) << " MaxCurand/M " << " : " << MaxCurand()/M
0861        << std::endl
0862        << std::setw(25) << kMaxSlot
0863        << std::setw(20) << " MaxSlot " << " : " << MaxSlot()
0864        << std::setw(20) << " MaxSlot/M " << " : " << MaxSlot()/M
0865        << std::endl
0866        << std::setw(25) << kMaxGenstep
0867        << std::setw(20) << " MaxGenstep " << " : " << MaxGenstep()
0868        << std::setw(20) << " MaxGenstep/M " << " : " << MaxGenstep()/M
0869        << std::endl
0870        << std::setw(25) << kMaxPhoton
0871        << std::setw(20) << " MaxPhoton " << " : " << MaxPhoton()
0872        << std::setw(20) << " MaxPhoton/M " << " : " << MaxPhoton()/M
0873        << std::endl
0874        << std::setw(25) << kMaxSimtrace
0875        << std::setw(20) << " MaxSimtrace " << " : " << MaxSimtrace()
0876        << std::setw(20) << " MaxSimtrace/M " << " : " << MaxSimtrace()/M
0877        << std::endl
0878        << std::setw(25) << kMaxBounce
0879        << std::setw(20) << " MaxBounce " << " : " << MaxBounce()
0880        << std::endl
0881        << std::setw(25) << ""
0882        << std::setw(20) << " MaxBounceNotes " << " : " << _MaxBounceNotes
0883        << std::endl
0884        << std::setw(25) << kMaxTime
0885        << std::setw(20) << " MaxTime " << " : " << MaxTime()
0886        << std::endl
0887        << std::setw(25) << ""
0888        << std::setw(20) << " MaxTimeNotes " << " : " << _MaxTimeNotes
0889        << std::endl
0890        << std::setw(25) << kMaxRecord
0891        << std::setw(20) << " MaxRecord " << " : " << MaxRecord()
0892        << std::endl
0893        << std::setw(25) << kMaxRec
0894        << std::setw(20) << " MaxRec " << " : " << MaxRec()
0895        << std::endl
0896        << std::setw(25) << kMaxAux
0897        << std::setw(20) << " MaxAux " << " : " << MaxAux()
0898        << std::endl
0899        << std::setw(25) << kMaxSup
0900        << std::setw(20) << " MaxSup " << " : " << MaxSup()
0901        << std::endl
0902        << std::setw(25) << kMaxSeq
0903        << std::setw(20) << " MaxSeq " << " : " << MaxSeq()
0904        << std::endl
0905        << std::setw(25) << kMaxPrd
0906        << std::setw(20) << " MaxPrd " << " : " << MaxPrd()
0907        << std::endl
0908        << std::setw(25) << kMaxTag
0909        << std::setw(20) << " MaxTag " << " : " << MaxTag()
0910        << std::endl
0911        << std::setw(25) << kMaxFlat
0912        << std::setw(20) << " MaxFlat " << " : " << MaxFlat()
0913        << std::endl
0914        << std::setw(25) << kModeSave
0915        << std::setw(20) << " ModeSave " << " : " << ModeSave()
0916        << std::endl
0917        << std::setw(25) << kModeClient
0918        << std::setw(20) << " ModeClient " << " : " << ModeClient()
0919        << std::endl
0920        << std::setw(25) << kModeLite
0921        << std::setw(20) << " ModeLite " << " : " << ModeLite()
0922        << std::endl
0923        << std::setw(25) << kModeMerge
0924        << std::setw(20) << " ModeMerge " << " : " << ModeMerge()
0925        << std::endl
0926        << std::setw(25) << kMergeWindow
0927        << std::setw(20) << " MergeWindow " << " : " << MergeWindow()
0928        << std::endl
0929        << std::setw(25) << kHitMask
0930        << std::setw(20) << " HitMask " << " : " << HitMask()
0931        << std::endl
0932        << std::setw(25) << ""
0933        << std::setw(20) << " HitMaskLabel " << " : " << HitMaskLabel()
0934        << std::endl
0935        << std::setw(25) << kMaxExtentDomain
0936        << std::setw(20) << " MaxExtentDomain " << " : " << MaxExtentDomain()
0937        << std::endl
0938        << std::setw(25) << kMaxTimeDomain
0939        << std::setw(20) << " MaxTimeDomain " << " : " << MaxTimeDomain()
0940        << std::endl
0941        << std::setw(25) << kRGMode
0942        << std::setw(20) << " RGMode " << " : " << RGMode()
0943        << std::endl
0944        << std::setw(25) << ""
0945        << std::setw(20) << " RGModeLabel " << " : " << RGModeLabel()
0946        << std::endl
0947        << std::setw(25) << kGatherComp
0948        << std::setw(20) << " GatherComp " << " : " << GatherComp()
0949        << std::endl
0950        << std::setw(25) << ""
0951        << std::setw(20) << " DescGatherComp " << " : " << DescGatherComp()
0952        << std::endl
0953        << std::setw(25) << kSaveComp
0954        << std::setw(20) << " SaveComp " << " : " << SaveComp()
0955        << std::endl
0956        << std::setw(25) << ""
0957        << std::setw(20) << " DescSaveComp " << " : " << DescSaveComp()
0958        << std::endl
0959        << std::setw(25) << kOutFold
0960        << std::setw(20) << " OutFold " << " : " << OutFold()
0961        << std::endl
0962        << std::setw(25) << kOutName
0963        << std::setw(20) << " OutName " << " : " << ( OutName() ? OutName() : "-" )
0964        << std::endl
0965        << std::setw(25) << kEventReldir
0966        << std::setw(20) << " EventReldir " << " : " << ( EventReldir() ? EventReldir() : "-" )
0967        << std::endl
0968        << std::setw(25) << kPropagateEpsilon
0969        << std::setw(20) << " PropagateEpsilon " << " : " << std::fixed << std::setw(10) << std::setprecision(4) << PropagateEpsilon()
0970        << std::endl
0971        << std::setw(25) << kPropagateEpsilon0
0972        << std::setw(20) << " PropagateEpsilon0 " << " : " << std::fixed << std::setw(10) << std::setprecision(4) << PropagateEpsilon0()
0973        << std::endl
0974        << std::setw(25) << kPropagateEpsilon0Mask
0975        << std::setw(20) << " PropagateEpsilon0Mask " << " : " << PropagateEpsilon0Mask()
0976        << std::endl
0977        << std::setw(25) << ""
0978        << std::setw(20) << " PropagateEpsilon0MaskLabel " << " : " << PropagateEpsilon0MaskLabel()
0979        << std::endl
0980        << std::setw(25) << kPropagateRefine
0981        << std::setw(20) << " PropagateRefine " << " : " << PropagateRefine()
0982        << std::endl
0983        << std::setw(25) << kPropagateRefineDistance
0984        << std::setw(20) << " PropagateRefineDistance " << " : " << PropagateRefineDistance()
0985        << std::endl
0986        << std::setw(25) << kInputGenstep
0987        << std::setw(20) << " InputGenstep " << " : " << ( InputGenstep() ? InputGenstep() : "-" )
0988        << std::endl
0989        << std::setw(25) << kInputGenstepSelection
0990        << std::setw(20) << " InputGenstepSelection " << " : " << ( InputGenstepSelection() ? InputGenstepSelection() : "-" )
0991        << std::endl
0992        << std::setw(25) << kInputPhoton
0993        << std::setw(20) << " InputPhoton " << " : " << ( InputPhoton() ? InputPhoton() : "-" )
0994        << std::endl
0995        << std::setw(25) << kInputPhotonChangeTime
0996        << std::setw(20) << " InputPhotonChangeTime " << " : " << InputPhotonChangeTime()
0997        << std::endl
0998        << std::setw(25) << kInputPhotonRecordTime
0999        << std::setw(20) << " InputPhotonRecordTime " << " : " << ( InputPhotonRecordTime() ? InputPhotonRecordTime() : "-" )
1000        << std::endl
1001        << std::setw(25) << kInputPhotonRecordSlice
1002        << std::setw(20) << " InputPhotonRecordSlice " << " : " << ( InputPhotonRecordSlice() ? InputPhotonRecordSlice() : "-" )
1003        << std::endl
1004        << std::setw(25) << "RecordLimit() "
1005        << std::setw(20) << " (sseq::SLOTS) " << " : " << RecordLimit()
1006        << std::endl
1007       ;
1008 
1009 
1010     for(int i=0 ; i < NumEvent() ; i++)
1011        ss << std::setw(25) << kNumPhoton
1012           << std::setw(20) << " NumPhoton(" << std::setw(4) << i << ") "
1013           << " : "
1014           << std::setw(10) << NumPhoton(i)
1015           << std::setw(10) << NumPhoton(i)/M << " (M) "
1016           << std::setw(10) << NumPhoton(i)/G << " (G) "
1017           << "\n"
1018           ;
1019 
1020     ss
1021        << DescEventMode()
1022        << std::endl
1023        << "]SEventConfig::Desc"
1024        << std::endl
1025        ;
1026 
1027 
1028     std::string str = ss.str();
1029     return str ;
1030 }
1031 
1032 
1033 /**
1034 SEventConfig::OutDir SEventConfig::OutPath
1035 --------------------------------------------
1036 
1037 Used by CSGOptiX::render_snap
1038 
1039 Expecting the below as the OutName defaults to nullptr::
1040 
1041    $TMP/GEOM/$GEOM/ExecutableName
1042 
1043 **/
1044 
1045 const char* SEventConfig::OutDir()
1046 {
1047     const char* outfold = OutFold();
1048     const char* outname = OutName();
1049 
1050     LOG(LEVEL)
1051         << " outfold " << ( outfold ? outfold : "-" )
1052         << " outname " << ( outname ? outname : "-" )
1053         ;
1054 
1055     const char* dir = outname == nullptr ?
1056                             spath::Resolve( outfold )
1057                             :
1058                             spath::Resolve( outfold, outname )
1059                             ;
1060 
1061     LOG(LEVEL)
1062         << " dir " << ( dir ? dir : "-" )
1063         ;
1064 
1065     sdirectory::MakeDirs(dir,0);
1066     return dir ;
1067 }
1068 
1069 /**
1070 SEventConfig::OutPath
1071 ----------------------
1072 
1073 unique:true
1074     when outpath file exists already increment the index until a non-existing outpath is found
1075 
1076 **/
1077 
1078 const char* SEventConfig::OutPath( const char* stem, int index, const char* ext, bool unique )
1079 {
1080     const char* outfold = OutFold();
1081     const char* outname = OutName();
1082 
1083     LOG(LEVEL)
1084         << " outfold " << ( outfold ? outfold : "-" )
1085         << " outname " << ( outname ? outname : "-" )
1086         << " stem " << ( stem ? stem : "-" )
1087         << " ext " << ( ext ? ext : "-" )
1088         << " index " << index
1089         << " unique " << ( unique ? "Y" : "N" )
1090         ;
1091 
1092     const char* outpath = SPath::Make( outfold, outname, stem, index, ext, FILEPATH);
1093 
1094     if(unique)
1095     {
1096         // increment until find non-existing path
1097         int offset = 0 ;
1098         while( SPath::Exists(outpath) && offset < 100 )
1099         {
1100             offset += 1 ;
1101             outpath = SPath::Make( outfold, outname, stem, index+offset, ext, FILEPATH);
1102         }
1103     }
1104 
1105 
1106     return outpath ;
1107    // HMM: an InPath would use NOOP to not create the dir
1108 }
1109 
1110 const char* SEventConfig::OutPath( const char* reldir, const char* stem, int index, const char* ext, bool unique )
1111 {
1112     const char* outfold = OutFold();
1113     const char* outname = OutName();
1114     LOG(LEVEL)
1115         << " outfold " << ( outfold ? outfold : "-" )
1116         << " outname " << ( outname ? outname : "-" )
1117         << " stem " << ( stem ? stem : "-" )
1118         << " ext " << ( ext ? ext : "-" )
1119         << " index " << index
1120         << " unique " << ( unique ? "Y" : "N" )
1121         ;
1122 
1123     const char* outpath = SPath::Make( outfold, outname, reldir, stem, index, ext, FILEPATH);
1124 
1125     if(unique)
1126     {
1127         // increment until find non-existing path
1128         int offset = 0 ;
1129         while( SPath::Exists(outpath) && offset < 100 )
1130         {
1131             offset += 1 ;
1132             outpath = SPath::Make( outfold, outname, reldir, stem, index+offset, ext, FILEPATH);
1133         }
1134     }
1135     return outpath ;
1136 }
1137 
1138 
1139 std::string SEventConfig::DescOutPath(  const char* stem, int index, const char* ext, bool unique)
1140 {
1141     const char* path = OutPath(stem, index, ext, unique ) ;
1142     std::stringstream ss ;
1143     ss << "SEventConfig::DescOutPath" << std::endl
1144        << " stem " << ( stem ? stem : "-" )
1145        << " index " << index
1146        << " ext " << ( ext ? ext : "-" )
1147        << " unique " << ( unique ? "Y" : "N" )
1148        << std::endl
1149        << " OutFold " << OutFold()
1150        << " OutName " << OutName()
1151        << std::endl
1152        << " OutPath " <<  path
1153        << std::endl
1154        ;
1155     std::string str = ss.str();
1156     return str ;
1157 }
1158 
1159 
1160 
1161 
1162 const char* SEventConfig::OutDir(const char* reldir)
1163 {
1164     const char* dir = spath::Resolve( OutFold(), OutName(), reldir );
1165     sdirectory::MakeDirs(dir, 0);
1166     return dir ;
1167 }
1168 
1169 
1170 scontext* SEventConfig::CONTEXT = nullptr ;
1171 salloc*   SEventConfig::ALLOC = nullptr ;
1172 
1173 std::string SEventConfig::GetGPUMeta(){ return CONTEXT ? CONTEXT->brief() : "ERR-NO-SEventConfig-CONTEXT" ; }
1174 
1175 void SEventConfig::Initialize_Meta()
1176 {
1177     CONTEXT = new scontext ;
1178     ALLOC = new salloc ;
1179 }
1180 
1181 
1182 
1183 
1184 /**
1185 SEventConfig::Initialize
1186 -------------------------
1187 
1188 Canonically invoked from SEvt::SEvt
1189 
1190 * SO: must make any static call adjustments before SEvt instanciation
1191 
1192 
1193 Call stack in OJ running::
1194 
1195     (gdb) bt
1196     #0  SEventConfig::Initialize () at /home/blyth/opticks/sysrap/SEventConfig.cc:1166
1197     #1  0x00007fffbe757a88 in SEvt::SEvt (this=0xc5c7390) at /home/blyth/opticks/sysrap/SEvt.cc:180
1198     #2  0x00007fffbe75c818 in SEvt::Create (ins=0) at /home/blyth/opticks/sysrap/SEvt.cc:1278
1199     #3  0x00007fffbe75cb83 in SEvt::CreateOrReuse (idx=0) at /home/blyth/opticks/sysrap/SEvt.cc:1336
1200     #4  0x00007fffbe75ce11 in SEvt::CreateOrReuse () at /home/blyth/opticks/sysrap/SEvt.cc:1380
1201     #5  0x00007fffc0f99c11 in G4CXOpticks::SetGeometry_JUNO (world=0xa61bd30, sd=0xa230880, jpmt=0xc5933c0, jlut=0xc5c6120) at /home/blyth/opticks/g4cx/G4CXOpticks.cc:106
1202     #6  0x00007fffbdd967a4 in LSExpDetectorConstruction_Opticks::Setup (opticksMode=1, world=0xa61bd30, sd=0xa230880, ppd=0x6595290, psd=0x6595e80, pmtscan=0x0)
1203         at /home/blyth/junosw/Simulation/DetSimV2/DetSimOptions/src/LSExpDetectorConstruction_Opticks.cc:47
1204     #7  0x00007fffbdd5b0e6 in LSExpDetectorConstruction::setupOpticks (this=0xa277810, world=0xa61bd30) at /home/blyth/junosw/Simulation/DetSimV2/DetSimOptions/src/LSExpDetectorConstruction.cc:472
1205     #8  0x00007fffbdd5a986 in LSExpDetectorConstruction::Construct (this=0xa277810) at /home/blyth/junosw/Simulation/DetSimV2/DetSimOptions/src/LSExpDetectorConstruction.cc:393
1206     #9  0x00007fffc67ca92e in G4RunManager::InitializeGeometry() () from /cvmfs/juno.ihep.ac.cn/el9_amd64_gcc11/Release/J25.4.0/ExternalLibs/Geant4/10.04.p02.juno/lib64/libG4run.so
1207 
1208 
1209 
1210 
1211 
1212 
1213 DebugHeavy
1214     far too heavy for most debugging/validation
1215 DebugLite
1216     mode with photon, record, seq,  genstep covers most needs
1217 
1218 
1219 Future
1220 ~~~~~~~
1221 
1222 * maybe move home from SEvt to SSim, as only one SSim but can be two or more SEvt sometimes
1223 
1224 **/
1225 
1226 int SEventConfig::Initialize_COUNT = 0 ;
1227 int SEventConfig::Initialize() // static
1228 {
1229     LOG_IF(LEVEL, Initialize_COUNT > 0 )
1230         << "SEventConfig::Initialize() called more than once " << std::endl
1231         << " this is now done automatically at SEvt::SEvt usually from main "
1232         << " (IN SOME CASES ITS CONVENIENT TO HAVE MORE THAN ONE SEvt, THOUGH "
1233         << "  SO MAYBE SHOULD MOVE THIS TO OPTICKS_LOG/SLOG ? "
1234         ;
1235 
1236     if(Initialize_COUNT == 0)
1237     {
1238         Initialize_Meta() ;
1239         Initialize_EventName() ;
1240         Initialize_Comp() ;
1241     }
1242     Initialize_COUNT += 1 ;
1243     return 0 ;
1244 }
1245 
1246 
1247 
1248 /**
1249 SEventConfig::Initialize_EventName
1250 -----------------------------------
1251 
1252 Examples that would match some builds::
1253 
1254    export OPTICKS_EVENT_NAME="SomePrefix_Debug_Philox_SomeSuffix"
1255    export OPTICKS_EVENT_NAME="Debug_XORWOW"
1256 
1257 **/
1258 
1259 void SEventConfig::Initialize_EventName()
1260 {
1261     if(EventName()==nullptr) return ;
1262     bool require_match = false ;
1263     if(!require_match) return ;
1264 
1265     bool build_matches_EventName = sbuild::Matches(EventName()) ;
1266 
1267     LOG(LEVEL)
1268         << "\n"
1269         << " kEventName " << kEventName << "\n"
1270         << " SEventConfig::EventName() " << EventName() << "\n"
1271         << " build_matches_EventName " << ( build_matches_EventName ? "YES" : "NO " ) << "\n"
1272         << sbuild::Desc()
1273         ;
1274 
1275     LOG_IF( error, !build_matches_EventName)
1276         << "\n"
1277         << " kEventName " << kEventName << "\n"
1278         << " SEventConfig::EventName() " << EventName() << "\n"
1279         << " build_matches_EventName " << ( build_matches_EventName ? "YES" : "NO " ) << "\n"
1280         << sbuild::Desc()
1281         << " FIX by changing " << kEventName << " or rebuilding with suitable config "
1282         ;
1283 
1284     assert(build_matches_EventName);
1285     if(!build_matches_EventName) std::raise(SIGINT);
1286 }
1287 
1288 
1289 
1290 const char* SEventConfig::Nothing_NOTE       = "nothing enabled - technical debug : MACHINERY TEST ONLY" ;
1291 
1292 const char* SEventConfig::DebugHeavy_NOTE    = "record/prd/aux/seq/tag/flat/sup all enabled : VERY LOW STATS ONLY : FEW MILLION MAX" ;
1293 const char* SEventConfig::DebugLite_NOTE     = "record/seq enabled      : VERY LOW STATS ONLY : FEW MILLION MAX" ;
1294 
1295 const char* SEventConfig::HitPhotonSeq_NOTE  = "HIT/GENSTEP/PHOTON/SEQ  : MODERATE STATS ONLY : TENS OF MILLIONS " ;
1296 const char* SEventConfig::HitPhoton_NOTE     = "HIT/GENSTEP/PHOTON      : MODERATE STATS ONLY : TENS OF MILLIONS " ;
1297 const char* SEventConfig::HitSeq_NOTE        = "HIT/GENSTEP/SEQ         : MODERATE STATS ONLY : TENS OF MILLIONS " ;
1298 
1299 const char* SEventConfig::Hit_NOTE           = "HIT/GENSTEP ONLY        : HIGHEST STATS : BILLIONS" ;
1300 const char* SEventConfig::Minimal_NOTE       = "HIT ONLY                : HIGHEST STATS : BILLIONS" ;
1301 
1302 const char* SEventConfig::EventMode_NOTE()
1303 {
1304     const char* note = nullptr ;
1305     if(     IsNothing())      note = Nothing_NOTE ;
1306     else if(IsDebugHeavy())   note = DebugHeavy_NOTE ;
1307     else if(IsDebugLite())    note = DebugLite_NOTE ;
1308     else if(IsHitPhotonSeq()) note = HitPhotonSeq_NOTE ;
1309     else if(IsHitPhoton())    note = HitPhoton_NOTE ;
1310     else if(IsHitSeq())       note = HitSeq_NOTE ;
1311     else if(IsHit())          note = Hit_NOTE ;
1312     else if(IsMinimal())      note = Minimal_NOTE ;
1313     return note ;
1314 }
1315 
1316 
1317 
1318 
1319 
1320 /**
1321 SEventConfig::Initialize_Comp
1322 -----------------------------
1323 
1324 Invoked by SEventConfig::Initialize
1325 AND by SetRGMode when the RG mode is changed.
1326 That is not a normal thing to do, but can happen
1327 when doing EndOfRun simtracing.
1328 
1329 **/
1330 
1331 
1332 void SEventConfig::Initialize_Comp()
1333 {
1334     unsigned gather_mask = 0 ;
1335     unsigned save_mask = 0 ;
1336 
1337     if(     IsRGModeSimulate()) Initialize_Comp_Simulate_(gather_mask, save_mask);
1338     else if(IsRGModeSimtrace()) Initialize_Comp_Simtrace_(gather_mask, save_mask);
1339     else if(IsRGModeRender())   Initialize_Comp_Render_(gather_mask, save_mask);
1340 
1341     SetGatherComp_(gather_mask);
1342     SetSaveComp_(  save_mask);
1343 }
1344 
1345 
1346 
1347 
1348 
1349 
1350 unsigned SEventConfig::PhotonComp() // static
1351 {
1352     unsigned comp = 0 ;
1353     switch(ModeLite())
1354     {
1355         case 0: comp = SCOMP_PHOTON                                        ; break ;
1356         case 1: comp = SCOMP_PHOTONLITE                                    ; break ;
1357         case 2: comp = SCOMP_PHOTON | SCOMP_PHOTONLITE | SCOMP_PHOTONLOCAL ; break ;
1358     }
1359     return comp ;
1360 }
1361 
1362 unsigned SEventConfig::PhotonCompOne() // static
1363 {
1364     unsigned comp = 0 ;
1365     switch(ModeLite())
1366     {
1367         case 0: comp = SCOMP_PHOTON     ; break ;
1368         case 1: comp = SCOMP_PHOTONLITE ; break ;
1369         case 2: comp = SCOMP_PHOTONLITE ; break ;
1370     }
1371     return comp ;
1372 }
1373 
1374 const char* SEventConfig::PhotonCompOneName() // static
1375 {
1376     return SComp::Name(PhotonCompOne());
1377 }
1378 
1379 
1380 
1381 
1382 /**
1383 SEventConfig::HitComp
1384 -----------------------
1385 
1386 Use::
1387 
1388     export OPTICKS_MODE_LITE=0/1/2 # to control the variant of hit that is gathered+saved
1389 
1390 **/
1391 
1392 
1393 unsigned SEventConfig::HitComp() // static
1394 {
1395     int64_t lite = ModeLite();
1396     int64_t merge = ModeMerge();
1397     int64_t lite_merge =  lite*1000 + merge ;
1398 
1399     unsigned comp = 0 ;
1400     switch( lite_merge )
1401     {
1402        case    0: comp = SCOMP_HIT                                                                          ; break ;
1403        case    1: comp = SCOMP_HITMERGED                                                                    ; break ;
1404        case 1000: comp = SCOMP_HITLITE                                                                      ; break ;
1405        case 1001: comp = SCOMP_HITLITEMERGED                                                                ; break ;
1406        case 2000: comp = SCOMP_HIT | SCOMP_HITLITE | SCOMP_HITLOCAL                                         ; break ;
1407        case 2001: comp = SCOMP_HIT | SCOMP_HITLITE | SCOMP_HITLOCAL | SCOMP_HITLITEMERGED | SCOMP_HITMERGED ; break ;
1408     }
1409     return comp ;
1410 }
1411 
1412 
1413 
1414 /**
1415 SEventConfig::HitCompOne
1416 -------------------------
1417 
1418 Canonical usage from::
1419 
1420     SEvt::getHit
1421     SEvt::getNumHit
1422 
1423 
1424 +-----------------------------------------------+--------------------------+---------------------+------------------+
1425 |   Mode                                        |   HitCompOne             |   HitCompOneName    |  Note            |
1426 +===============================================+==========================+=====================+==================+
1427 |    OPTICKS_MODE_LITE=0 OPTICKS_MODE_MERGE=0   |  SCOMP_HIT               |   hit               |                  |
1428 +-----------------------------------------------+--------------------------+---------------------+------------------+
1429 |    OPTICKS_MODE_LITE=0 OPTICKS_MODE_MERGE=1   |  SCOMP_HITMERGED         |   hitmerged         |                  |
1430 +-----------------------------------------------+--------------------------+---------------------+------------------+
1431 |    OPTICKS_MODE_LITE=1 OPTICKS_MODE_MERGE=0   |  SCOMP_HITLITE           |   hitlite           |                  |
1432 +-----------------------------------------------+--------------------------+---------------------+------------------+
1433 |    OPTICKS_MODE_LITE=1 OPTICKS_MODE_MERGE=1   |  SCOMP_HITLITEMERGED     |   hitlitemerged     |                  |
1434 +-----------------------------------------------+--------------------------+---------------------+------------------+
1435 
1436 **/
1437 
1438 unsigned SEventConfig::HitCompOne() // static
1439 {
1440     unsigned comp = 0 ;
1441     int64_t lite = ModeLite();
1442     int64_t merge = ModeMerge();
1443     int64_t lite_merge = lite*10 + merge ;
1444 
1445     if( lite == 0 || lite == 1 )
1446     {
1447         switch(lite_merge)
1448         {
1449             case   0: comp = SCOMP_HIT            ; break ;
1450             case   1: comp = SCOMP_HITMERGED      ; break ;
1451             case  10: comp = SCOMP_HITLITE        ; break ;
1452             case  11: comp = SCOMP_HITLITEMERGED  ; break ;
1453         }
1454     }
1455     else if( lite == 2 )  // debug only
1456     {
1457         switch(lite_merge)
1458         {
1459             case  20: comp = SCOMP_HITLITE        ; break ;
1460             case  21: comp = SCOMP_HITLITEMERGED  ; break ;
1461         }
1462     }
1463 
1464     return comp ;
1465 }
1466 
1467 
1468 
1469 /**
1470 SEventConfig::HitCompOneName
1471 ----------------------------
1472 
1473 This returns the component name that is used by SEvt::getNumHit SEvt::getHit
1474 
1475 **/
1476 
1477 const char* SEventConfig::HitCompOneName() // static
1478 {
1479     return SComp::Name( HitCompOne() );
1480 }
1481 
1482 
1483 
1484 
1485 
1486 
1487 
1488 
1489 
1490 /**
1491 SEventConfig::Initialize_Comp_Simulate_
1492 ----------------------------------------
1493 
1494 Canonically invoked by SEventConfig::Initialize_Comp
1495 
1496 enum values like SCOMP_PHOTON are bitwise-ORed into the
1497 gather and save masks based on configured MAX values.
1498 
1499 +----------------------+--------------------------------------+--------------------------------------+------------------------+
1500 | OPTICKS_EVENT_MODE   |  gather : GPU -> CPU                 |   save : CPU -> file                 |   notes                |
1501 +======================+======================================+======================================+========================+
1502 |  Nothing             | -                                    | -                                    |                        |
1503 +----------------------+--------------------------------------+--------------------------------------+------------------------+
1504 | *Minimal*            | HitComp()                            | -                                    |  DEFAULT EventMode     |
1505 +----------------------+--------------------------------------+--------------------------------------+------------------------+
1506 |  Hit                 | HitComp(), genstep                   | HitComp(), genstep                   |                        |
1507 +----------------------+--------------------------------------+--------------------------------------+------------------------+
1508 |  HitPhoton           | HitComp(),PhotonComp(),genstep       | HitComp(),PhotonComp(),genstep       |                        |
1509 +----------------------+--------------------------------------+--------------------------------------+------------------------+
1510 |  HitPhotonSeq        | HitComp(),PhotonComp(),genstep,seq   | HitComp(),PhotonComp(),genstep,seq   |                        |
1511 +----------------------+--------------------------------------+--------------------------------------+------------------------+
1512 |  HitSeq              | HitComp(),genstep,seq                | HitComp(),genstep,seq                |                        |
1513 +----------------------+--------------------------------------+--------------------------------------+------------------------+
1514 |  DebugHeavy          |  SEE CODE                            |  SEE CODE                            |                        |
1515 +----------------------+--------------------------------------+--------------------------------------+------------------------+
1516 |  DebugLite           |  SEE CODE                            |  SEE CODE                            |                        |
1517 +----------------------+--------------------------------------+--------------------------------------+------------------------+
1518 
1519 **/
1520 
1521 
1522 void SEventConfig::Initialize_Comp_Simulate_(unsigned& gather_mask, unsigned& save_mask )
1523 {
1524     const char* mode = EventMode();
1525 
1526     int record_limit = RecordLimit();
1527     LOG(LEVEL)
1528         << " EventMode() " << mode     // eg Default, DebugHeavy
1529         << " RunningMode() " << RunningMode()
1530         << " RunningModeLabel() " << RunningModeLabel()
1531         << " record_limit " << record_limit
1532         ;
1533 
1534 
1535     if(IsNothing())
1536     {
1537         LOG(LEVEL) << "IsNothing()" ;
1538         gather_mask = 0 ;
1539         save_mask = 0 ;
1540     }
1541     else if(IsMinimal())
1542     {
1543         LOG(LEVEL) << "IsMinimal()" ;
1544 
1545         gather_mask = HitComp() ;
1546         save_mask = 0 ;
1547     }
1548     else if(IsHit())
1549     {
1550         LOG(LEVEL) << "IsHit()" ;
1551         gather_mask = HitComp() | SCOMP_GENSTEP ;
1552         save_mask = HitComp() | SCOMP_GENSTEP ;
1553     }
1554     else if(IsHitPhoton())
1555     {
1556         LOG(LEVEL) << "IsHitPhoton()" ;
1557         gather_mask = HitComp() | PhotonComp() | SCOMP_GENSTEP  ;
1558         save_mask = HitComp() | PhotonComp() | SCOMP_GENSTEP ;
1559     }
1560     else if(IsHitPhotonSeq())
1561     {
1562         LOG(LEVEL) << "IsHitPhotonSeq()" ;
1563         gather_mask = HitComp() | PhotonComp() | SCOMP_SEQ | SCOMP_GENSTEP  ;
1564         save_mask = HitComp() | PhotonComp() | SCOMP_SEQ | SCOMP_GENSTEP ;
1565         SetMaxSeq(1);
1566     }
1567     else if(IsHitSeq())
1568     {
1569         LOG(LEVEL) << "IsHitSeq()" ;
1570         gather_mask = HitComp() | SCOMP_SEQ | SCOMP_GENSTEP  ;
1571         save_mask = HitComp() | SCOMP_SEQ | SCOMP_GENSTEP ;
1572         SetMaxSeq(1);
1573     }
1574     else if(IsDebugHeavy() || IsDebugLite())
1575     {
1576         if(IsDebugHeavy())
1577         {
1578             SEventConfig::SetMaxRec(0);
1579             SEventConfig::SetMaxRecord(record_limit);
1580             SEventConfig::SetMaxPrd(record_limit);
1581             SEventConfig::SetMaxAux(record_limit);
1582 
1583             SEventConfig::SetMaxSeq(1);
1584             // since moved to compound sflat/stag so MaxFlat/MaxTag should now either be 0 or 1, nothing else
1585             SEventConfig::SetMaxTag(1);
1586             SEventConfig::SetMaxFlat(1);
1587             SEventConfig::SetMaxSup(1);
1588 
1589         }
1590         else if(IsDebugLite())
1591         {
1592             SEventConfig::SetMaxRec(0);
1593             SEventConfig::SetMaxRecord(record_limit);
1594             SEventConfig::SetMaxSeq(1);  // formerly incorrectly set to max_bounce+1
1595         }
1596 
1597 
1598         gather_mask |= SCOMP_DOMAIN ;  save_mask |= SCOMP_DOMAIN ;
1599 
1600         if(MaxGenstep()>0){  gather_mask |= SCOMP_GENSTEP ; save_mask |= SCOMP_GENSTEP ; }
1601         if(MaxPhoton()>0)
1602         {
1603             gather_mask |= SCOMP_INPHOTON ;  save_mask |= SCOMP_INPHOTON ;
1604             gather_mask |= PhotonComp()   ;  save_mask |= PhotonComp()   ;
1605             gather_mask |= HitComp()      ;  save_mask |= HitComp() ;
1606 
1607             //gather_mask |= SCOMP_SEED ;   save_mask |= SCOMP_SEED ;  // only needed for deep debugging
1608         }
1609 
1610 
1611 
1612         // HUH: meaning of the below Max very different from above, thats confusing
1613         // the below "Max" can be configured via envvar eg OPTICKS_MAX_LITE=1
1614         // most of the below "Max" are only allowed to be 0 OR  1
1615 
1616         if(MaxRecord()>0){   gather_mask |= SCOMP_RECORD     ;  save_mask |= SCOMP_RECORD ; }
1617         if(MaxAux()>0){      gather_mask |= SCOMP_AUX        ;  save_mask |= SCOMP_AUX    ; }
1618         if(MaxSup()>0){      gather_mask |= SCOMP_SUP        ;  save_mask |= SCOMP_SUP    ; }
1619         if(MaxPrd()>0){      gather_mask |= SCOMP_PRD        ;  save_mask |= SCOMP_PRD    ; }
1620 
1621         if(MaxSeq()==1){     gather_mask |= SCOMP_SEQ        ;  save_mask |= SCOMP_SEQ    ; }
1622         if(MaxTag()==1){     gather_mask |= SCOMP_TAG        ;  save_mask |= SCOMP_TAG    ; }
1623         if(MaxFlat()==1){    gather_mask |= SCOMP_FLAT       ;  save_mask |= SCOMP_FLAT   ; }
1624     }
1625 
1626 
1627     if(IsRunningModeG4StateSave() || IsRunningModeG4StateRerun())
1628     {
1629         LOG(LEVEL) << " adding SCOMP_G4STATE to comp list " ;
1630         gather_mask |= SCOMP_G4STATE ; save_mask |= SCOMP_G4STATE ;
1631     }
1632     else
1633     {
1634         LOG(LEVEL) << " NOT : adding SCOMP_G4STATE to comp list " ;
1635     }
1636 }
1637 
1638 void SEventConfig::Initialize_Comp_Simtrace_(unsigned& gather_mask, unsigned& save_mask )
1639 {
1640     assert(IsRGModeSimtrace());
1641     if(MaxGenstep()>0){   gather_mask |= SCOMP_GENSTEP  ;  save_mask |= SCOMP_GENSTEP ;  }
1642     if(MaxSimtrace()>0){  gather_mask |= SCOMP_SIMTRACE ;  save_mask |= SCOMP_SIMTRACE ; }
1643 
1644     LOG(info)
1645         << " MaxGenstep " << MaxGenstep()
1646         << " MaxSimtrace " << MaxSimtrace()
1647         << " gather_mask " << gather_mask
1648         << " save_mask " << save_mask
1649         ;
1650 
1651 }
1652 void SEventConfig::Initialize_Comp_Render_(unsigned& gather_mask, unsigned& save_mask )
1653 {
1654     assert(IsRGModeRender());
1655     gather_mask |= SCOMP_PIXEL ;  save_mask |=  SCOMP_PIXEL ;
1656 }
1657 
1658 /**
1659 SEventConfig::Serialize
1660 -----------------------
1661 
1662 Called for example from SEvt::addEventConfigArray
1663 
1664 **/
1665 
1666 
1667 NP* SEventConfig::Serialize() // static
1668 {
1669     NP* meta = NP::Make<int>(1) ;
1670 
1671     const char* em = EventMode();
1672     if(em)  meta->set_meta<std::string>("EventMode", em );
1673 
1674     meta->set_meta<int>("RunningMode", RunningMode() );
1675 
1676     const char* rml = RunningModeLabel();
1677     if(rml) meta->set_meta<std::string>("RunningModeLabel", rml );
1678 
1679     const char* g4s = G4StateSpec() ;
1680     if(g4s) meta->set_meta<std::string>("G4StateSpec", g4s );
1681 
1682     meta->set_meta<int>("G4StateRerun", G4StateRerun() );
1683     meta->set_meta<int>("MaxCurand", MaxCurand() );
1684     meta->set_meta<int>("MaxSlot", MaxSlot() );
1685     meta->set_meta<int>("MaxGenstep", MaxGenstep() );
1686     meta->set_meta<int>("MaxPhoton", MaxPhoton() );
1687     meta->set_meta<int>("MaxSimtrace", MaxSimtrace() );
1688 
1689     meta->set_meta<int>("MaxBounce", MaxBounce() );
1690     meta->set_meta<float>("MaxTime", MaxTime() );
1691 
1692     meta->set_meta<int>("MaxRecord", MaxRecord() );
1693     meta->set_meta<int>("MaxRec", MaxRec() );
1694     meta->set_meta<int>("MaxAux", MaxAux() );
1695     meta->set_meta<int>("MaxSup", MaxSup() );
1696     meta->set_meta<int>("MaxSeq", MaxSeq() );
1697     meta->set_meta<int>("MaxPrd", MaxPrd() );
1698     meta->set_meta<int>("MaxTag", MaxTag() );
1699     meta->set_meta<int>("MaxFlat", MaxFlat() );
1700 
1701     meta->set_meta<int>("ModeSave", ModeSave() );
1702     meta->set_meta<int>("ModeClient", ModeClient() );
1703     meta->set_meta<int>("ModeLite", ModeLite() );
1704     meta->set_meta<int>("ModeMerge", ModeMerge() );
1705     meta->set_meta<float>("MergeWindow", MergeWindow() );
1706 
1707     meta->set_meta<float>("MaxExtentDomain", MaxExtentDomain() );
1708     meta->set_meta<float>("MaxTimeDomain", MaxTimeDomain() );
1709 
1710     const char* of = OutFold() ;
1711     if(of) meta->set_meta<std::string>("OutFold", of );
1712 
1713     const char* on = OutName() ;
1714     if(on) meta->set_meta<std::string>("OutName", on );
1715 
1716     meta->set_meta<unsigned>("HitMask", HitMask() );
1717     meta->set_meta<std::string>("HitMaskLabel", HitMaskLabel() );
1718 
1719     meta->set_meta<unsigned>("GatherComp", GatherComp() );
1720     meta->set_meta<unsigned>("SaveComp", SaveComp() );
1721 
1722     meta->set_meta<std::string>("DescGatherComp", DescGatherComp());
1723     meta->set_meta<std::string>("DescSaveComp", DescSaveComp());
1724 
1725     meta->set_meta<float>("PropagateEpsilon", PropagateEpsilon() );
1726     meta->set_meta<float>("PropagateEpsilon0", PropagateEpsilon0() );
1727 
1728 
1729     const char* ig  = InputGenstep() ;
1730     if(ig)  meta->set_meta<std::string>("InputGenstep", ig );
1731 
1732     const char* igsel  = InputGenstepSelection() ;
1733     if(igsel)  meta->set_meta<std::string>("InputGenstepSelection", igsel );
1734 
1735 
1736     const char* ip  = InputPhoton() ;
1737     if(ip)  meta->set_meta<std::string>("InputPhoton", ip );
1738 
1739     const char* ipf = InputPhotonFrame() ;
1740     if(ipf) meta->set_meta<std::string>("InputPhotonFrame", ipf );
1741 
1742     meta->set_meta<float>("InputPhotonChangeTime", InputPhotonChangeTime() );
1743 
1744     const char* iprt = InputPhotonRecordTime();
1745     if(iprt) meta->set_meta<std::string>("InputPhotonRecordTime", iprt );
1746 
1747     const char* iprs = InputPhotonRecordSlice() ;
1748     if(iprs) meta->set_meta<std::string>("InputPhotonRecordSlice", iprs );
1749 
1750 
1751     meta->set_meta<int>("RGMode", RGMode() );
1752 
1753     const char* rgml = RGModeLabel() ;
1754     if(rgml) meta->set_meta<std::string>("RGModeLabel", rgml );
1755 
1756 
1757     return meta ;
1758 }
1759 
1760 void SEventConfig::Save(const char* dir ) // static
1761 {
1762     if(dir == nullptr) return ;
1763     NP* meta =Serialize();
1764     meta->save(dir, NAME );
1765 }
1766 
1767 /**
1768 SEventConfig::SetDevice
1769 -------------------------
1770 
1771 Invoked at first SEvt instanciation::
1772 
1773     SEventConfig::SetDevice
1774     scontext::initConfig
1775     scontext::init
1776     scontext::scontext
1777     SEventConfig::Initialize_Meta
1778     SEventConfig::Initialize
1779     SEvt::SEvt
1780     SEvt::Create
1781 
1782 Maximum number of photon slots that can be simulated in a single GPU
1783 launch depends on:
1784 
1785 1. VRAM, available from scontext.h invoked by CSGOptiX::Create
1786 
1787 2. sizeof(curandState)+photon 4x4x4 + plus optional enabled arrays
1788    configured in SEventConfig::
1789 
1790    sizeof(curandStateXORWOW) 48
1791    sizeof(sphoton)           64=4*4*4
1792    .                       -----
1793    .                        112 bytes per photon (absolute minimum)
1794 
1795 3. limited by available (chunked) curandState, see QRng.hh SCurandState.h
1796    (currently M200). BUT other than consuming disk it is perfectly possible
1797    to curand_init more chunks of curandState than could ever be used in
1798    currently available GPU VRAM (48GB, 80GB)
1799    because many launches are done due to curand_init taking lots of stack.
1800 
1801    * for now could just assert in QRng that maxphoton is less than
1802      the available curandState slots
1803 
1804 4. safety scaledown from theoretical maximum for reliability,
1805    as detector geometry will take a few GB plus other processes
1806    will use some too
1807 
1808    * HMM: could access current free VRAM also, but that could change
1809      between the check and the launch
1810 
1811 
1812 Experience with 48G GPU (48*1024*1024*1024 = 51539607552)::
1813 
1814     400M photons with 48*1024*1024*1024
1815 
1816     In [3]: 48*1024*1024*1024/112/1e6
1817     Out[3]: 460.1750674285714
1818 
1819     In [6]: 48*1024*1024*1024/112/1e6*0.9
1820     Out[6]: 414.1575606857143
1821 
1822     In [5]: 48*1024*1024*1024/112/1e6*0.87
1823     Out[5]: 400.3523086628571
1824 
1825 
1826 Assuming get to use 90% of total VRAM in ballpark of observed 400M limit
1827 
1828 TODO: measure total VRAM usage during large photon number scan to
1829 provide some parameters to use in a better heuristic and get idea
1830 of variability. Expect linear with some pedestal.
1831 
1832 **/
1833 
1834 void SEventConfig::SetDevice( size_t totalGlobalMem_bytes, std::string name )
1835 {
1836     SetDeviceName( name.empty() ? nullptr : name.c_str() ) ;
1837     LOG(info) << DescDevice(totalGlobalMem_bytes, name) ;
1838 
1839     size_t mxs0 = MaxSlot();
1840     int lite = ModeLite();
1841     int merge = ModeMerge();
1842 
1843     size_t hmxr = HeuristicMaxSlot_Rounded(totalGlobalMem_bytes, lite, merge );
1844 
1845     bool MaxSlot_is_zero = mxs0 == 0 ;
1846     if(MaxSlot_is_zero) SetMaxSlot(hmxr)
1847 ;
1848     size_t mxs1  = MaxSlot();
1849 
1850     bool changed = mxs1 != mxs0  ;
1851 
1852     LOG(info)
1853         << " Configured_MaxSlot/M " << mxs0/M
1854         << " Final_MaxSlot/M " << mxs1/M
1855         << " HeuristicMaxSlot_Rounded/M "  << hmxr/M
1856         << " changed " << ( changed ? "YES" : "NO " )
1857         << " DeviceName " << ( DeviceName() ? DeviceName() : "-" )
1858         << " HasDevice " << ( HasDevice() ? "YES" : "NO " )
1859         << "\n"
1860         << "(export OPTICKS_MAX_SLOT=0 # to use VRAM based HeuristicMaxPhoton) " ;
1861         ;
1862 }
1863 
1864 
1865 void SEventConfig::SetDeviceName( const char* name )
1866 {
1867     _DeviceName = name ? strdup(name) : nullptr ;
1868 }
1869 
1870 
1871 /**
1872 SEventConfig::HeuristicMaxSlot
1873 -------------------------------
1874 
1875 Currently no accounting for the configured debug arrays.
1876 Are assuming production type running.
1877 
1878 For example the record array will scale memory per photon
1879 by factor of ~32 from the 32 step points
1880 (not accounting for curandState).
1881 
1882 When debug arrays are configured the user currently
1883 needs to manually keep total photon count low (few millions)
1884 to stay within VRAM.  See::
1885 
1886     QSimTest::fake_propagate
1887     QSimTest::EventConfig
1888 
1889 
1890 **/
1891 size_t SEventConfig::HeuristicMaxSlot( size_t totalGlobalMem_bytes, int lite, int merge  )
1892 {
1893     float vram_ceiling = float(totalGlobalMem_bytes)*0.87f ; // AIM not to exceed 87% (Grok:80%) of total VRAM
1894     float bytes_per_photon = (lite == 0) ? 64.f : 16.f;
1895     float headroom = (merge == 0) ? 1.75f : 3.3f;  // 1.75 was OK before adding GPU hit merging and lite mode
1896     return size_t(vram_ceiling / (bytes_per_photon * headroom) * 0.98f);
1897 }
1898 
1899 
1900 /**
1901 SEventConfig::HeuristicMaxSlot_Rounded
1902 -----------------------------------------
1903 
1904 Rounded down to nearest million.
1905 
1906 **/
1907 
1908 size_t SEventConfig::HeuristicMaxSlot_Rounded( size_t totalGlobalMem_bytes, int lite, int merge  )
1909 {
1910     size_t hmx = HeuristicMaxSlot(totalGlobalMem_bytes, lite, merge );
1911     size_t hmx_M = hmx/M ;
1912     return hmx_M*M ;
1913 }
1914 
1915 std::string SEventConfig::DescDevice(size_t totalGlobalMem_bytes, std::string name )  // static
1916 {
1917     int lite = ModeLite();
1918     int merge = ModeMerge();
1919 
1920     size_t hmx = HeuristicMaxSlot(totalGlobalMem_bytes, lite, merge );
1921     size_t hmx_M = hmx/M ;
1922     size_t hmxr = HeuristicMaxSlot_Rounded(totalGlobalMem_bytes, lite, merge);
1923     size_t mxs  = MaxSlot();
1924 
1925     int wid = 35 ;
1926     std::stringstream ss ;
1927     ss << "SEventConfig::DescDevice"
1928        << "\n"
1929        << std::setw(wid) << "name                             : " << name
1930        << "\n"
1931        << std::setw(wid) << "totalGlobalMem_bytes             : " << totalGlobalMem_bytes
1932        << "\n"
1933        << std::setw(wid) << "totalGlobalMem_GB                : " << totalGlobalMem_bytes/(1024*1024*1024)
1934        << "\n"
1935        << std::setw(wid) << "HeuristicMaxSlot(VRAM)           : " << hmx
1936        << "\n"
1937        << std::setw(wid) << "HeuristicMaxSlot(VRAM)/M         : " << hmx_M
1938        << "\n"
1939        << std::setw(wid) << "HeuristicMaxSlot_Rounded(VRAM)   : " << hmxr
1940        << "\n"
1941        << std::setw(wid) << "MaxSlot/M                        : " << mxs/M
1942        << "\n"
1943        << std::setw(wid) << "ModeLite                         : " << lite
1944        << "\n"
1945        << std::setw(wid) << "ModeMerge                        : " << merge
1946        << "\n"
1947        ;
1948 
1949     std::string str = ss.str() ;
1950     return str ;
1951 }
1952 
1953 
1954 salloc* SEventConfig::AllocEstimate(int _max_slot)
1955 {
1956     uint64_t max_slot = _max_slot == 0 ? MaxSlot() : _max_slot ;
1957     uint64_t max_record = MaxRecord();
1958     uint64_t max_genstep = MaxGenstep();
1959 
1960     salloc* estimate = new salloc ;
1961     estimate->add("QEvt::setGenstep/device_alloc_genstep_and_seed:quad6/max_genstep", max_genstep, sizeof(quad6) ) ;
1962     estimate->add("QEvt::setGenstep/device_alloc_genstep_and_seed:int/max_slot", max_slot, sizeof(int));
1963     estimate->add("QEvt::device_alloc_photon/max_slot*sizeof(sphoton)", max_slot, sizeof(sphoton)) ;
1964     if(GatherRecord()) estimate->add("QEvt::device_alloc_photon/max_slot*max_record*sizeof(sphoton)", max_slot*max_record, sizeof(sphoton) );
1965 
1966     return estimate ;
1967 }
1968 
1969 uint64_t SEventConfig::AllocEstimateTotal(int _max_slot)
1970 {
1971     salloc* estimate = AllocEstimate(_max_slot);
1972     uint64_t total = estimate->get_total();
1973     delete estimate ;
1974     return total ;
1975 }
1976