File indexing completed on 2026-09-12 08:24:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include "DDRec/MaterialManager.h"
0014 #include "DD4hep/Exceptions.h"
0015 #include "DD4hep/Detector.h"
0016
0017 #include "TGeoVolume.h"
0018 #include "TGeoManager.h"
0019 #include "TGeoNode.h"
0020 #include "TVirtualGeoTrack.h"
0021
0022 #define MINSTEP 1.e-5
0023
0024 namespace dd4hep {
0025 namespace rec {
0026
0027 MaterialManager::MaterialManager(Volume world) : _mV(0), _m( Material() ), _p0(),_p1(),_pos() {
0028 _tgeoMgr = world->GetGeoManager();
0029 }
0030
0031 MaterialManager::~MaterialManager(){
0032
0033 }
0034
0035 const PlacementVec& MaterialManager::placementsBetween(const Vector3D& p0, const Vector3D& p1 , double eps) {
0036 materialsBetween(p0,p1,eps);
0037 return _placeV;
0038 }
0039
0040 const MaterialManager::ScanData MaterialManager::entriesBetween(const Vector3D& p0,
0041 const Vector3D& p1,
0042 double eps) {
0043 const auto& materials = this->materialsBetween(p0, p1, eps);
0044 return { materials, this->_placeV };
0045 }
0046
0047 const MaterialVec& MaterialManager::materialsBetween(const Vector3D& p0, const Vector3D& p1 , double eps) {
0048 if( ( p0 != _p0 ) || ( p1 != _p1 ) ) {
0049
0050
0051 _tgeoMgr->DoBackupState();
0052
0053 _mV.clear() ;
0054 _placeV.clear();
0055
0056
0057
0058
0059 double startpoint[3], endpoint[3], direction[3];
0060 double L=0;
0061 for(unsigned int i=0; i<3; i++) {
0062 startpoint[i] = p0[i];
0063 endpoint[i] = p1[i];
0064 direction[i] = endpoint[i] - startpoint[i];
0065 L+=direction[i]*direction[i];
0066 }
0067 double totDist = sqrt( L ) ;
0068
0069
0070 for(unsigned int i=0; i<3; i++)
0071 direction[i]=direction[i]/totDist;
0072
0073 _tgeoMgr->AddTrack(0, 12 ) ;
0074
0075 TGeoNode *node1 = _tgeoMgr->InitTrack(startpoint, direction);
0076
0077
0078 if(!node1)
0079 throw std::runtime_error("No geometry node found at given location. Either there is no node placed here or position is outside of top volume.");
0080
0081 while ( !_tgeoMgr->IsOutside() ) {
0082
0083
0084
0085
0086
0087 TGeoNode * node2 = _tgeoMgr->FindNextBoundaryAndStep( 500, 1) ;
0088
0089 if( !node2 || _tgeoMgr->IsOutside() )
0090 break;
0091
0092 const double *position = _tgeoMgr->GetCurrentPoint();
0093 const double *previouspos = _tgeoMgr->GetLastPoint();
0094
0095 double length = _tgeoMgr->GetStep();
0096
0097 TVirtualGeoTrack *track = _tgeoMgr->GetLastTrack();
0098
0099
0100
0101
0102
0103 #if 1
0104 if( length < MINSTEP ) {
0105
0106 _tgeoMgr->SetCurrentPoint( position[0] + MINSTEP * direction[0],
0107 position[1] + MINSTEP * direction[1],
0108 position[2] + MINSTEP * direction[2] );
0109
0110 length = _tgeoMgr->GetStep();
0111 node2 = _tgeoMgr->FindNextBoundaryAndStep(500, 1) ;
0112
0113 position = _tgeoMgr->GetCurrentPoint();
0114 previouspos = _tgeoMgr->GetLastPoint();
0115 }
0116 #endif
0117
0118
0119
0120 Vector3D posV( position ) ;
0121
0122 double currDistance = ( posV - p0 ).r() ;
0123
0124
0125
0126
0127
0128
0129 if( currDistance > totDist ) {
0130
0131 length = sqrt( pow(endpoint[0]-previouspos[0],2) +
0132 pow(endpoint[1]-previouspos[1],2) +
0133 pow(endpoint[2]-previouspos[2],2) );
0134
0135 track->AddPoint( endpoint[0], endpoint[1], endpoint[2], 0. );
0136
0137
0138 if( length > eps ) {
0139 _mV.emplace_back(node1->GetMedium(), length );
0140 _placeV.emplace_back(node1,length);
0141 }
0142 break;
0143 }
0144
0145 track->AddPoint( position[0], position[1], position[2], 0.);
0146
0147 if( length > eps ) {
0148 _mV.emplace_back(node1->GetMedium(), length);
0149 _placeV.emplace_back(node1,length);
0150 }
0151 node1 = node2;
0152 }
0153
0154
0155
0156 if( _mV.empty() ){
0157 _mV.emplace_back(node1->GetMedium(), totDist);
0158 _placeV.emplace_back(node1,totDist);
0159 }
0160
0161
0162 _tgeoMgr->ClearTracks();
0163
0164 _tgeoMgr->CleanGarbage();
0165
0166 _tgeoMgr->DoRestoreState();
0167
0168
0169
0170 _p0 = p0 ;
0171 _p1 = p1 ;
0172 }
0173
0174 return _mV ;
0175 }
0176
0177
0178 const Material& MaterialManager::materialAt(const Vector3D& pos ) {
0179 if( pos != _pos ) {
0180 TGeoNode *node = _tgeoMgr->FindNode( pos[0], pos[1], pos[2] ) ;
0181 if( ! node ) {
0182 std::stringstream err ;
0183 err << " MaterialManager::material: No geometry node found at location: " << pos ;
0184 throw std::runtime_error( err.str() );
0185 }
0186 _m = Material( node->GetMedium() );
0187 _pv = node;
0188 _pos = pos ;
0189 }
0190 return _m ;
0191 }
0192
0193 PlacedVolume MaterialManager::placementAt(const Vector3D& pos ) {
0194 if( pos != _pos ) {
0195 TGeoNode *node = _tgeoMgr->FindNode( pos[0], pos[1], pos[2] ) ;
0196 if( ! node ) {
0197 std::stringstream err ;
0198 err << " MaterialManager::material: No geometry node found at location: " << pos ;
0199 throw std::runtime_error( err.str() );
0200 }
0201 _m = Material( node->GetMedium() );
0202 _pv = node;
0203 _pos = pos;
0204 }
0205 return _pv;
0206 }
0207
0208 MaterialData MaterialManager::createAveragedMaterial( const MaterialVec& materials ) {
0209
0210 std::stringstream sstr ;
0211
0212 double sum_l = 0 ;
0213 double sum_rho_l = 0 ;
0214 double sum_rho_l_over_A = 0 ;
0215 double sum_rho_l_Z_over_A = 0 ;
0216
0217 double sum_l_over_x = 0 ;
0218
0219 double sum_l_over_lambda = 0 ;
0220
0221 for(unsigned i=0,n=materials.size(); i<n ; ++i){
0222
0223 Material mat = materials[i].first ;
0224 double l = materials[i].second ;
0225
0226 if( i != 0 ) sstr << "_" ;
0227 sstr << mat.name() << "_" << l ;
0228
0229 double rho = mat.density() ;
0230 double A = mat.A() ;
0231 double Z = mat.Z() ;
0232 double x = mat.radLength() ;
0233 double lambda = mat.intLength() ;
0234
0235 sum_l += l ;
0236 sum_rho_l += rho * l ;
0237 sum_rho_l_over_A += rho * l / A ;
0238 sum_rho_l_Z_over_A += rho * l * Z / A ;
0239 sum_l_over_x += l / x ;
0240 sum_l_over_lambda += l / lambda ;
0241
0242
0243 }
0244
0245 double rho = sum_rho_l / sum_l ;
0246
0247 double A = sum_rho_l / sum_rho_l_over_A ;
0248 double Z = sum_rho_l_Z_over_A / sum_rho_l_over_A ;
0249
0250
0251
0252
0253 double x = sum_l / sum_l_over_x ;
0254
0255
0256 double lambda = sum_l / sum_l_over_lambda ;
0257
0258
0259 return MaterialData( sstr.str() , Z, A, rho, x, lambda ) ;
0260
0261 }
0262
0263 }
0264 }