File indexing completed on 2025-01-18 09:14:35
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 epsilon) {
0036 materialsBetween(p0,p1,epsilon);
0037 return _placeV;
0038 }
0039
0040 const MaterialVec& MaterialManager::materialsBetween(const Vector3D& p0, const Vector3D& p1 , double epsilon) {
0041 if( ( p0 != _p0 ) || ( p1 != _p1 ) ) {
0042
0043 _mV.clear() ;
0044 _placeV.clear();
0045
0046
0047
0048
0049 double startpoint[3], endpoint[3], direction[3];
0050 double L=0;
0051 for(unsigned int i=0; i<3; i++) {
0052 startpoint[i] = p0[i];
0053 endpoint[i] = p1[i];
0054 direction[i] = endpoint[i] - startpoint[i];
0055 L+=direction[i]*direction[i];
0056 }
0057 double totDist = sqrt( L ) ;
0058
0059
0060 for(unsigned int i=0; i<3; i++)
0061 direction[i]=direction[i]/totDist;
0062
0063 _tgeoMgr->AddTrack(0, 12 ) ;
0064
0065 TGeoNode *node1 = _tgeoMgr->InitTrack(startpoint, direction);
0066
0067
0068 if(!node1)
0069 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.");
0070
0071 while ( !_tgeoMgr->IsOutside() ) {
0072
0073
0074
0075
0076
0077 TGeoNode * node2 = _tgeoMgr->FindNextBoundaryAndStep( 500, 1) ;
0078
0079 if( !node2 || _tgeoMgr->IsOutside() )
0080 break;
0081
0082 const double *position = _tgeoMgr->GetCurrentPoint();
0083 const double *previouspos = _tgeoMgr->GetLastPoint();
0084
0085 double length = _tgeoMgr->GetStep();
0086
0087 TVirtualGeoTrack *track = _tgeoMgr->GetLastTrack();
0088
0089
0090
0091
0092
0093 #if 1
0094 if( length < MINSTEP ) {
0095
0096 _tgeoMgr->SetCurrentPoint( position[0] + MINSTEP * direction[0],
0097 position[1] + MINSTEP * direction[1],
0098 position[2] + MINSTEP * direction[2] );
0099
0100 length = _tgeoMgr->GetStep();
0101 node2 = _tgeoMgr->FindNextBoundaryAndStep(500, 1) ;
0102
0103 position = _tgeoMgr->GetCurrentPoint();
0104 previouspos = _tgeoMgr->GetLastPoint();
0105 }
0106 #endif
0107
0108
0109
0110 Vector3D posV( position ) ;
0111
0112 double currDistance = ( posV - p0 ).r() ;
0113
0114
0115
0116
0117
0118
0119 if( currDistance > totDist ) {
0120
0121 length = sqrt( pow(endpoint[0]-previouspos[0],2) +
0122 pow(endpoint[1]-previouspos[1],2) +
0123 pow(endpoint[2]-previouspos[2],2) );
0124
0125 track->AddPoint( endpoint[0], endpoint[1], endpoint[2], 0. );
0126
0127
0128 if( length > epsilon ) {
0129 _mV.emplace_back(node1->GetMedium(), length );
0130 _placeV.emplace_back(node1,length);
0131 }
0132 break;
0133 }
0134
0135 track->AddPoint( position[0], position[1], position[2], 0.);
0136
0137 if( length > epsilon ) {
0138 _mV.emplace_back(node1->GetMedium(), length);
0139 _placeV.emplace_back(node1,length);
0140 }
0141 node1 = node2;
0142 }
0143
0144
0145
0146 if( _mV.empty() ){
0147 _mV.emplace_back(node1->GetMedium(), totDist);
0148 _placeV.emplace_back(node1,totDist);
0149 }
0150
0151
0152 _tgeoMgr->ClearTracks();
0153
0154 _tgeoMgr->CleanGarbage();
0155
0156
0157
0158 _p0 = p0 ;
0159 _p1 = p1 ;
0160 }
0161
0162 return _mV ;
0163 }
0164
0165
0166 const Material& MaterialManager::materialAt(const Vector3D& pos ) {
0167 if( pos != _pos ) {
0168 TGeoNode *node = _tgeoMgr->FindNode( pos[0], pos[1], pos[2] ) ;
0169 if( ! node ) {
0170 std::stringstream err ;
0171 err << " MaterialManager::material: No geometry node found at location: " << pos ;
0172 throw std::runtime_error( err.str() );
0173 }
0174 _m = Material( node->GetMedium() );
0175 _pv = node;
0176 _pos = pos ;
0177 }
0178 return _m ;
0179 }
0180
0181 PlacedVolume MaterialManager::placementAt(const Vector3D& pos ) {
0182 if( pos != _pos ) {
0183 TGeoNode *node = _tgeoMgr->FindNode( pos[0], pos[1], pos[2] ) ;
0184 if( ! node ) {
0185 std::stringstream err ;
0186 err << " MaterialManager::material: No geometry node found at location: " << pos ;
0187 throw std::runtime_error( err.str() );
0188 }
0189 _m = Material( node->GetMedium() );
0190 _pv = node;
0191 _pos = pos;
0192 }
0193 return _pv;
0194 }
0195
0196 MaterialData MaterialManager::createAveragedMaterial( const MaterialVec& materials ) {
0197
0198 std::stringstream sstr ;
0199
0200 double sum_l = 0 ;
0201 double sum_rho_l = 0 ;
0202 double sum_rho_l_over_A = 0 ;
0203 double sum_rho_l_Z_over_A = 0 ;
0204
0205 double sum_l_over_x = 0 ;
0206
0207 double sum_l_over_lambda = 0 ;
0208
0209 for(unsigned i=0,n=materials.size(); i<n ; ++i){
0210
0211 Material mat = materials[i].first ;
0212 double l = materials[i].second ;
0213
0214 if( i != 0 ) sstr << "_" ;
0215 sstr << mat.name() << "_" << l ;
0216
0217 double rho = mat.density() ;
0218 double A = mat.A() ;
0219 double Z = mat.Z() ;
0220 double x = mat.radLength() ;
0221 double lambda = mat.intLength() ;
0222
0223 sum_l += l ;
0224 sum_rho_l += rho * l ;
0225 sum_rho_l_over_A += rho * l / A ;
0226 sum_rho_l_Z_over_A += rho * l * Z / A ;
0227 sum_l_over_x += l / x ;
0228 sum_l_over_lambda += l / lambda ;
0229
0230
0231 }
0232
0233 double rho = sum_rho_l / sum_l ;
0234
0235 double A = sum_rho_l / sum_rho_l_over_A ;
0236 double Z = sum_rho_l_Z_over_A / sum_rho_l_over_A ;
0237
0238
0239
0240
0241 double x = sum_l / sum_l_over_x ;
0242
0243
0244 double lambda = sum_l / sum_l_over_lambda ;
0245
0246
0247 return MaterialData( sstr.str() , Z, A, rho, x, lambda ) ;
0248
0249 }
0250
0251 }
0252 }