File indexing completed on 2026-04-10 07:50:35
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <string>
0020 #include <cstring>
0021 #include <csignal>
0022 #include <sstream>
0023 #include <iomanip>
0024
0025 #include "G4VPhysicalVolume.hh"
0026 #include "G4LogicalVolume.hh"
0027 #include "G4TouchableHistory.hh"
0028 #include "G4VSolid.hh"
0029
0030 struct U4Touchable
0031 {
0032 enum { MATCH_ALL, MATCH_START, MATCH_END } ;
0033 static bool Match( const char* s, const char* q, int mode) ;
0034 static bool MatchAll( const char* s, const char* q) ;
0035 static bool MatchStart( const char* s, const char* q) ;
0036 static bool MatchEnd( const char* s, const char* q) ;
0037
0038 template<typename T>
0039 static const G4VPhysicalVolume* FindPV( const T* touch, const char* qname, int mode=MATCH_ALL );
0040
0041 template<typename T>
0042 static int ImmediateReplicaNumber(const T* touch );
0043
0044 template<typename T>
0045 static int AncestorReplicaNumber(const T* touch, int d=1 );
0046
0047
0048 template<typename T>
0049 static int ReplicaNumber(const T* touch, const char* replica_name_select ) ;
0050
0051 template<typename T>
0052 static int ReplicaDepth(const T* touch, const char* replica_name_select ) ;
0053
0054 template<typename T>
0055 static int TouchDepth(const T* touch );
0056
0057 static bool HasMoreThanOneDaughterWithName( const G4LogicalVolume* lv, const char* name);
0058
0059 template<typename T>
0060 static std::string Brief(const T* touch );
0061
0062 template<typename T>
0063 static std::string Desc(const T* touch, int so_wid=20, int pv_wid=20);
0064 };
0065
0066
0067 inline bool U4Touchable::Match( const char* s, const char* q, int mode )
0068 {
0069 bool ret = false ;
0070 switch(mode)
0071 {
0072 case MATCH_ALL: ret = MatchAll( s, q) ; break ;
0073 case MATCH_START: ret = MatchStart(s, q) ; break ;
0074 case MATCH_END: ret = MatchEnd( s, q) ; break ;
0075 }
0076 return ret ;
0077 }
0078
0079 inline bool U4Touchable::MatchAll( const char* s, const char* q)
0080 {
0081 return s && q && strcmp(s, q) == 0 ;
0082 }
0083 inline bool U4Touchable::MatchStart( const char* s, const char* q)
0084 {
0085 return s && q && strlen(q) <= strlen(s) && strncmp(s, q, strlen(q)) == 0 ;
0086 }
0087 inline bool U4Touchable::MatchEnd( const char* s, const char* q)
0088 {
0089 int pos = strlen(s) - strlen(q) ;
0090 return pos > 0 && strncmp(s + pos, q, strlen(q)) == 0 ;
0091 }
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 template<typename T>
0102 inline const G4VPhysicalVolume* U4Touchable::FindPV( const T* touch, const char* qname, int mode )
0103 {
0104 int nd = touch->GetHistoryDepth();
0105 int count = 0 ;
0106 const G4VPhysicalVolume* qpv = nullptr ;
0107 for (int d=0 ; d < nd ; ++d )
0108 {
0109 const G4VPhysicalVolume* dpv = touch->GetVolume(d);
0110 const char* dpv_name = dpv->GetName().c_str() ;
0111 if(Match(dpv_name, qname, mode))
0112 {
0113 qpv = dpv ;
0114 count += 1 ;
0115 }
0116 }
0117 return qpv ;
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 template<typename T>
0146 inline int U4Touchable::ImmediateReplicaNumber(const T* touch )
0147 {
0148 int copyNo = touch->GetReplicaNumber(1);
0149 if(copyNo <= 0) copyNo = touch->GetReplicaNumber(2);
0150 return copyNo ;
0151 }
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 template<typename T>
0166 inline int U4Touchable::AncestorReplicaNumber(const T* touch, int d )
0167 {
0168 int depth = touch->GetHistoryDepth();
0169 int copyNo = -1 ;
0170 while( copyNo <= 0 && d < depth )
0171 {
0172 copyNo = touch->GetReplicaNumber(d);
0173 d++ ;
0174 }
0175 return copyNo ;
0176 }
0177
0178
0179 template<typename T>
0180 inline int U4Touchable::ReplicaNumber(const T* touch, const char* replica_name_select )
0181 {
0182 int d = ReplicaDepth(touch, replica_name_select);
0183 bool found = d > -1 ;
0184 int repno = found ? touch->GetReplicaNumber(d) : d ;
0185
0186 #ifdef U4TOUCHABLE_DEBUG
0187 if(found) std::cerr
0188 << "U4Touchable::ReplicaNumber"
0189 << " found " << found
0190 << " repno " << repno
0191 << std::endl
0192 ;
0193 #endif
0194
0195 return repno ;
0196 }
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220 template<typename T>
0221 inline int U4Touchable::ReplicaDepth(const T* touch, const char* replica_name_select )
0222 {
0223 int nd = touch->GetHistoryDepth();
0224 int t = TouchDepth(touch);
0225 bool expected = t > -1 && t < nd ;
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239 if(!expected) return -2 ;
0240
0241 for (int d=t ; d < nd-1; ++d )
0242 {
0243 const G4VPhysicalVolume* dpv = touch->GetVolume(d);
0244 const G4VPhysicalVolume* mpv = touch->GetVolume(d+1);
0245
0246 const G4LogicalVolume* dlv = dpv->GetLogicalVolume();
0247 const G4LogicalVolume* mlv = mpv->GetLogicalVolume();
0248
0249
0250
0251
0252
0253 bool hierarchy = dpv->GetMotherLogical() == mlv ;
0254 assert(hierarchy);
0255 if(!hierarchy) std::raise(SIGINT);
0256
0257 const char* dlv_name = dlv->GetName().c_str() ;
0258 bool name_skip = replica_name_select && strstr(dlv_name, replica_name_select) == nullptr ;
0259
0260
0261 #ifdef U4TOUCHABLE_DEBUG
0262 std::cerr
0263 << "U4Touchable::ReplicaDepth"
0264 << " d " << d
0265 << " nd " << nd
0266 << " dlv_name " << dlv_name
0267 << " replica_name_select " << ( replica_name_select ? replica_name_select : "-" )
0268 << " name_skip " << name_skip
0269 << " skip " << skip
0270 << std::endl
0271 ;
0272 #endif
0273
0274
0275
0276 if(name_skip) continue ;
0277 bool found = HasMoreThanOneDaughterWithName(mlv, dlv_name) ;
0278
0279 #ifdef U4TOUCHABLE_DEBUG
0280 if(found)std::cerr
0281 << "U4Touchable::ReplicaDepth"
0282 << " d " << d
0283 << " dlv_name " << dlv_name
0284 << " found " << found
0285 << std::endl
0286 ;
0287 #endif
0288
0289 if(found) return d ;
0290 }
0291 return -1 ;
0292 }
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302 template<typename T>
0303 inline int U4Touchable::TouchDepth(const T* touch )
0304 {
0305 const G4VPhysicalVolume* tpv = touch->GetVolume() ;
0306 int t = -1 ;
0307 for(int i=0 ; i < touch->GetHistoryDepth() ; i++)
0308 {
0309 const G4VPhysicalVolume* ipv = touch->GetVolume(i) ;
0310 if(ipv == tpv)
0311 {
0312 t = i ;
0313 break ;
0314 }
0315 }
0316 return t ;
0317 }
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329 inline bool U4Touchable::HasMoreThanOneDaughterWithName( const G4LogicalVolume* lv, const char* name)
0330 {
0331 int num_dau = lv->GetNoDaughters();
0332 if(num_dau <= 1) return false ;
0333
0334 #ifdef U4TOUCHABLE_DEBUG
0335 bool heavy = num_dau > 45000 ;
0336 if(heavy) std::cerr
0337 << "U4Touchable::HasMoreThanOneDaughterWithName"
0338 << " num_dau " << num_dau
0339 << " name " << name
0340 << " lv.name " << lv->GetName()
0341 << std::endl
0342 ;
0343 #endif
0344
0345
0346 int count = 0;
0347 for (int k=0; k < num_dau ; ++k)
0348 {
0349 const G4VPhysicalVolume* kpv = lv->GetDaughter(k) ;
0350 const G4LogicalVolume* klv = kpv->GetLogicalVolume() ;
0351 const char* klv_name = klv->GetName().c_str() ;
0352
0353 #ifdef U4TOUCHABLE_DEBUG
0354 if(heavy) std::cerr
0355 << "U4Touchable::HasMoreThanOneDaughterWithName"
0356 << " k " << k
0357 << " kpv.name " << kpv->GetName()
0358 << " klv_name " << klv_name
0359 << " count " << count
0360 << std::endl
0361 ;
0362 #endif
0363
0364 if(strcmp(name, klv_name)==0) count += 1 ;
0365 if(count > 1) return true ;
0366 }
0367 return false ;
0368 }
0369
0370
0371
0372
0373 template<typename T>
0374 inline std::string U4Touchable::Brief(const T* touch )
0375 {
0376 std::stringstream ss ;
0377 ss << "U4Touchable::Brief"
0378 << " HistoryDepth " << std::setw(2) << touch->GetHistoryDepth()
0379 << " TouchDepth " << std::setw(2) << TouchDepth(touch)
0380 << " ReplicaDepth " << std::setw(2) << ReplicaDepth(touch, nullptr)
0381 << " ReplicaNumber " << std::setw(6) << ReplicaNumber(touch, nullptr)
0382 ;
0383 return ss.str();
0384 }
0385 template<typename T>
0386 inline std::string U4Touchable::Desc(const T* touch, int so_wid, int pv_wid )
0387 {
0388 int history_depth = touch->GetHistoryDepth();
0389 int touch_depth = TouchDepth(touch);
0390 int replica_depth = ReplicaDepth(touch, nullptr);
0391 int replica_number = ReplicaNumber(touch, nullptr);
0392 int immediate_replica_number = ImmediateReplicaNumber(touch);
0393 int ancestor_replica_number = AncestorReplicaNumber(touch);
0394
0395 std::stringstream ss ;
0396 ss << "U4Touchable::Desc"
0397 << " HistoryDepth " << std::setw(2) << history_depth
0398 << " TouchDepth " << std::setw(2) << touch_depth
0399 << " ReplicaDepth " << std::setw(2) << replica_depth
0400 << " ReplicaNumber " << std::setw(6) << replica_number
0401 << " ImmediateReplicaNumber " << std::setw(6) << immediate_replica_number
0402 << " AncestorReplicaNumber " << std::setw(6) << ancestor_replica_number
0403 << std::endl
0404 ;
0405
0406 for(int i=0 ; i< history_depth ; i++)
0407 {
0408 G4VPhysicalVolume* pv = touch->GetVolume(i);
0409 G4LogicalVolume* lv = pv->GetLogicalVolume();
0410 G4int nd = lv->GetNoDaughters();
0411 G4VSolid* so = touch->GetSolid(i);
0412 G4int cp = touch->GetReplicaNumber(i);
0413
0414 ss << " i " << std::setw(2) << i
0415 << " cp " << std::setw(6) << cp
0416 << " nd " << std::setw(6) << nd
0417 << " so " << std::setw(so_wid) << so->GetName()
0418 << " pv " << std::setw(pv_wid) << pv->GetName()
0419 << std::endl ;
0420 }
0421 std::string s = ss.str();
0422 return s ;
0423 }
0424
0425