55
55
#include < G4Isotope.hh>
56
56
#include < G4Material.hh>
57
57
#include < G4UserLimits.hh>
58
+ #include < G4RegionStore.hh>
58
59
#include < G4FieldManager.hh>
59
60
#include < G4LogicalVolume.hh>
60
- #include < G4ReflectionFactory.hh>
61
61
#include < G4OpticalSurface.hh>
62
+ #include < G4ReflectionFactory.hh>
62
63
#include < G4LogicalSkinSurface.hh>
63
64
#include < G4ElectroMagneticField.hh>
64
65
#include < G4LogicalBorderSurface.hh>
73
74
#include < iostream>
74
75
#include < iomanip>
75
76
#include < sstream>
77
+ #include < limits>
76
78
77
79
namespace units = dd4hep;
78
80
using namespace dd4hep ::detail;
@@ -711,70 +713,94 @@ void* Geant4Converter::handleVolume(const string& name, const TGeoVolume* volume
711
713
return nullptr ;
712
714
}
713
715
else if (volIt == info.g4Volumes .end () ) {
714
- string n = volume->GetName ();
715
- TGeoMedium* med = volume->GetMedium ();
716
- TGeoShape* sh = volume->GetShape ();
717
- G4VSolid* solid = (G4VSolid*) handleSolid (sh->GetName (), sh);
718
- bool is_assembly = sh->IsA () == TGeoShapeAssembly::Class () || volume->IsA () == TGeoVolumeAssembly::Class ();
716
+ const char * vnam = volume->GetName ();
717
+ TGeoMedium* med = volume->GetMedium ();
718
+ Solid sh = volume->GetShape ();
719
+ bool is_assembly = sh->IsA () == TGeoShapeAssembly::Class () || volume->IsAssembly ();
719
720
720
721
printout (lvl, " Geant4Converter" , " ++ Convert Volume %-32s: %p %s/%s assembly:%s" ,
721
- n.c_str (), volume, sh->IsA ()->GetName (), volume->IsA ()->GetName (), yes_no (is_assembly));
722
-
722
+ vnam, volume, sh.type (), _v.type (), yes_no (is_assembly));
723
723
if ( is_assembly ) {
724
724
return nullptr ;
725
725
}
726
- Region reg = _v.region ();
727
- LimitSet lim = _v.limitSet ();
728
- VisAttr vis = _v.visAttributes ();
729
- G4Region* region = reg.isValid () ? info.g4Regions [reg] : nullptr ;
730
- G4UserLimits* limits = lim.isValid () ? info.g4Limits [lim] : nullptr ;
731
- G4Material* medium = (G4Material*) handleMaterial (med->GetName (), Material (med));
726
+ Region reg = _v.region ();
727
+ LimitSet lim = _v.limitSet ();
728
+ VisAttr vis = _v.visAttributes ();
729
+ G4Region* g4region = reg.isValid () ? info.g4Regions [reg] : nullptr ;
730
+ G4UserLimits* g4limits = lim.isValid () ? info.g4Limits [lim] : nullptr ;
731
+ G4VSolid* g4solid = (G4VSolid*) handleSolid (sh->GetName (), sh);
732
+ G4Material* g4medium = (G4Material*) handleMaterial (med->GetName (), Material (med));
732
733
// / Check all pre-conditions
733
- if ( !solid ) {
734
- except (" G4Converter" ," ++ No Geant4 Solid present for volume:" + n );
734
+ if ( !g4solid ) {
735
+ except (" G4Converter" ," ++ No Geant4 Solid present for volume: %s " , vnam );
735
736
}
736
- else if ( !medium ) {
737
- except (" G4Converter" ," ++ No Geant4 material present for volume:" + n );
737
+ else if ( !g4medium ) {
738
+ except (" G4Converter" ," ++ No Geant4 material present for volume: %s " , vnam );
738
739
}
739
- else if ( reg.isValid () && !region ) {
740
- except (" G4Cnv::volume[" +name+" ]" ," ++ Failed to access Geant4 region %s." ,reg.name ());
740
+ else if ( reg.isValid () && !g4region ) {
741
+ except (" G4Cnv::volume[" +name+" ]" ," ++ Failed to access Geant4 region %s." , reg.name ());
741
742
}
742
- else if ( lim.isValid () && !limits ) {
743
- except (" G4Cnv::volume[" +name+" ]" ," ++ FATAL Failed to access Geant4 user limits %s." ,lim.name ());
743
+ else if ( lim.isValid () && !g4limits ) {
744
+ except (" G4Cnv::volume[" +name+" ]" ," ++ FATAL Failed to access Geant4 user limits %s." , lim.name ());
744
745
}
745
- else if ( limits ) {
746
- printout (lvl, " Geant4Converter" , " ++ Volume + Apply LIMITS settings:%-24s to volume %s." ,
747
- lim.name (), _v. name () );
746
+ else if ( g4limits ) {
747
+ printout (lvl, " Geant4Converter" , " ++ Volume + Apply LIMITS settings: %-24s to volume %s." ,
748
+ lim.name (), vnam );
748
749
}
749
750
750
751
G4LogicalVolume* g4vol = nullptr ;
751
752
if ( _v.hasProperties () && !_v.getProperty (GEANT4_TAG_PLUGIN," " ).empty () ) {
752
753
Detector* det = const_cast <Detector*>(&m_detDesc);
753
754
string plugin = _v.getProperty (GEANT4_TAG_PLUGIN," " );
754
- g4vol = PluginService::Create<G4LogicalVolume*>(plugin, det, _v, solid, medium );
755
+ g4vol = PluginService::Create<G4LogicalVolume*>(plugin, det, _v, g4solid, g4medium );
755
756
if ( !g4vol ) {
756
757
except (" G4Cnv::volume[" +name+" ]" ," ++ FATAL Failed to call plugin to create logical volume." );
757
758
}
758
759
}
759
760
else {
760
- g4vol = new G4LogicalVolume (solid, medium, n , nullptr , nullptr , nullptr );
761
+ g4vol = new G4LogicalVolume (g4solid, g4medium, vnam , nullptr , nullptr , nullptr );
761
762
}
762
763
763
- if ( limits ) {
764
- g4vol->SetUserLimits (limits );
764
+ if ( g4limits ) {
765
+ g4vol->SetUserLimits (g4limits );
765
766
}
766
- if ( region ) {
767
- printout (lvl, " Geant4Converter" , " ++ Volume + Apply REGION settings: %s to volume %s." ,
768
- reg.name (), _v.name ());
769
- g4vol->SetRegion (region);
770
- region->AddRootLogicalVolume (g4vol);
767
+ if ( g4region ) {
768
+ PrintLevel plevel = (debugVolumes||debugRegions||debugLimits) ? ALWAYS : outputLevel;
769
+ printout (plevel, " Geant4Converter" , " ++ Volume + Apply REGION settings: %-24s to volume %s." ,
770
+ reg.name (), vnam);
771
+ // Handle the region settings for the world volume seperately.
772
+ // Geant4 does NOT WANT any regions assigned to the workd volume.
773
+ // The world's region is created in the G4RunManagerKernel!
774
+ if ( _v == m_detDesc.worldVolume () ) {
775
+ const char * wrd_nam = " DefaultRegionForTheWorld" ;
776
+ const char * src_nam = g4region->GetName ().c_str ();
777
+ auto * world_region = G4RegionStore::GetInstance ()->GetRegion (wrd_nam, false );
778
+ if ( auto * cuts = g4region->GetProductionCuts () ) {
779
+ world_region->SetProductionCuts (cuts);
780
+ printout (plevel, " Geant4Converter" ,
781
+ " ++ Volume %s Region: %s. Apply production cuts from %s" ,
782
+ vnam, wrd_nam, src_nam);
783
+ }
784
+ if ( auto * lims = g4region->GetUserLimits () ) {
785
+ world_region->SetUserLimits (lims);
786
+ printout (plevel, " Geant4Converter" ,
787
+ " ++ Volume %s Region: %s. Apply user limits from %s" ,
788
+ vnam, wrd_nam, src_nam);
789
+ }
790
+ }
791
+ else {
792
+ g4vol->SetRegion (g4region);
793
+ g4region->AddRootLogicalVolume (g4vol);
794
+ }
771
795
}
772
- G4VisAttributes* vattr = vis.isValid () ? (G4VisAttributes*)handleVis (vis.name (), vis) : nullptr ;
773
- if ( vattr ) {
774
- g4vol->SetVisAttributes (vattr);
796
+ G4VisAttributes* g4vattr = vis.isValid ()
797
+ ? (G4VisAttributes*)handleVis (vis.name (), vis) : nullptr ;
798
+ if ( g4vattr ) {
799
+ g4vol->SetVisAttributes (g4vattr);
775
800
}
776
801
info.g4Volumes [volume] = g4vol;
777
- printout (lvl, " Geant4Converter" , " ++ Volume + %s converted: %p ---> G4: %p" , n.c_str (), volume, g4vol);
802
+ printout (lvl, " Geant4Converter" ,
803
+ " ++ Volume + %s converted: %p ---> G4: %p" , vnam, volume, g4vol);
778
804
}
779
805
return nullptr ;
780
806
}
@@ -786,13 +812,16 @@ void* Geant4Converter::collectVolume(const string& /* name */, const TGeoVolume*
786
812
Region reg = _v.region ();
787
813
LimitSet lim = _v.limitSet ();
788
814
SensitiveDetector det = _v.sensitiveDetector ();
789
-
790
- if ( lim.isValid () )
791
- info.limits [lim].insert (volume);
792
- if ( reg.isValid () )
793
- info.regions [reg].insert (volume);
794
- if ( det.isValid () )
795
- info.sensitives [det].insert (volume);
815
+ bool world = (volume == m_detDesc.worldVolume ().ptr ());
816
+
817
+ if ( !world ) {
818
+ if ( lim.isValid () )
819
+ info.limits [lim].insert (volume);
820
+ if ( reg.isValid () )
821
+ info.regions [reg].insert (volume);
822
+ if ( det.isValid () )
823
+ info.sensitives [det].insert (volume);
824
+ }
796
825
return (void *)volume;
797
826
}
798
827
@@ -1043,8 +1072,8 @@ void* Geant4Converter::handleRegion(Region region, const set<const TGeoVolume*>&
1043
1072
G4Region* g4 = data ().g4Regions [region];
1044
1073
if ( !g4 ) {
1045
1074
PrintLevel lvl = debugRegions ? ALWAYS : outputLevel;
1046
- Region r = region;
1047
- g4 = new G4Region (r .name ());
1075
+ Region r = region;
1076
+ g4 = new G4Region (region .name ());
1048
1077
1049
1078
// create region info with storeSecondaries flag
1050
1079
if ( not r.wasThresholdSet () and r.storeSecondaries () ) {
@@ -1065,49 +1094,49 @@ void* Geant4Converter::handleRegion(Region region, const set<const TGeoVolume*>&
1065
1094
cuts = new G4ProductionCuts ();
1066
1095
cuts->SetProductionCut (r.cut ()*CLHEP::mm/units::mm);
1067
1096
printout (lvl, " Geant4Converter" , " ++ %s: Using default cut: %f [mm]" ,
1068
- r.name (), r.cut ()*CLHEP::mm/units::mm);
1097
+ r.name (), r.cut ()*CLHEP::mm/units::mm);
1069
1098
}
1070
1099
for ( const auto & nam : limits ) {
1071
1100
LimitSet ls = m_detDesc.limitSet (nam);
1072
- if (ls.isValid ()) {
1073
- const LimitSet::Set& cts = ls.cuts ();
1074
- for (const auto & c : cts ) {
1075
- int pid = 0 ;
1076
- if ( c.particles == " *" ) pid = -1 ;
1077
- else if ( c.particles == " e-" ) pid = idxG4ElectronCut;
1078
- else if ( c.particles == " e+" ) pid = idxG4PositronCut;
1079
- else if ( c.particles == " e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1080
- else if ( c.particles == " e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1081
- else if ( c.particles == " gamma" ) pid = idxG4GammaCut;
1082
- else if ( c.particles == " proton" ) pid = idxG4ProtonCut;
1083
- else throw runtime_error (" G4Region: Invalid production cut particle-type:" + c.particles );
1084
- if ( !cuts ) cuts = new G4ProductionCuts ();
1085
- if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1086
- cuts->SetProductionCut (c.value *CLHEP::mm/units::mm, idxG4PositronCut);
1087
- cuts->SetProductionCut (c.value *CLHEP::mm/units::mm, idxG4ElectronCut);
1088
- }
1089
- else {
1090
- cuts->SetProductionCut (c.value *CLHEP::mm/units::mm, pid);
1091
- }
1092
- printout (lvl, " Geant4Converter" , " ++ %s: Set cut [%s/%d] = %f [mm]" ,
1093
- r.name (), c.particles .c_str (), pid, c.value *CLHEP::mm/units::mm);
1094
- }
1095
- bool found = false ;
1096
- const auto & lm = data ().g4Limits ;
1097
- for (const auto & j : lm ) {
1098
- if (nam == j.first ->GetName ()) {
1099
- g4->SetUserLimits (j.second );
1100
- printout (lvl, " Geant4Converter" , " ++ %s: Set limits %s to region type %s" ,
1101
- r.name (), nam.c_str (), j.second ->GetType ().c_str ());
1102
- found = true ;
1103
- break ;
1104
- }
1105
- }
1106
- if ( found ) {
1107
- continue ;
1108
- }
1101
+ if ( ls.isValid () ) {
1102
+ const LimitSet::Set& cts = ls.cuts ();
1103
+ for (const auto & c : cts ) {
1104
+ int pid = 0 ;
1105
+ if ( c.particles == " *" ) pid = -1 ;
1106
+ else if ( c.particles == " e-" ) pid = idxG4ElectronCut;
1107
+ else if ( c.particles == " e+" ) pid = idxG4PositronCut;
1108
+ else if ( c.particles == " e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1109
+ else if ( c.particles == " e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1110
+ else if ( c.particles == " gamma" ) pid = idxG4GammaCut;
1111
+ else if ( c.particles == " proton" ) pid = idxG4ProtonCut;
1112
+ else throw runtime_error (" G4Region: Invalid production cut particle-type:" + c.particles );
1113
+ if ( !cuts ) cuts = new G4ProductionCuts ();
1114
+ if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1115
+ cuts->SetProductionCut (c.value *CLHEP::mm/units::mm, idxG4PositronCut);
1116
+ cuts->SetProductionCut (c.value *CLHEP::mm/units::mm, idxG4ElectronCut);
1117
+ }
1118
+ else {
1119
+ cuts->SetProductionCut (c.value *CLHEP::mm/units::mm, pid);
1120
+ }
1121
+ printout (lvl, " Geant4Converter" , " ++ %s: Set cut [%s/%d] = %f [mm]" ,
1122
+ r.name (), c.particles .c_str (), pid, c.value *CLHEP::mm/units::mm);
1123
+ }
1124
+ bool found = false ;
1125
+ const auto & lm = data ().g4Limits ;
1126
+ for (const auto & j : lm ) {
1127
+ if (nam == j.first ->GetName ()) {
1128
+ g4->SetUserLimits (j.second );
1129
+ printout (lvl, " Geant4Converter" , " ++ %s: Set limits %s to region type %s" ,
1130
+ r.name (), nam.c_str (), j.second ->GetType ().c_str ());
1131
+ found = true ;
1132
+ break ;
1133
+ }
1134
+ }
1135
+ if ( found ) {
1136
+ continue ;
1137
+ }
1109
1138
}
1110
- throw runtime_error ( " G4Region: Failed to resolve user limitset:" + nam);
1139
+ except ( " Geant4Converter " , " ++ G4Region: Failed to resolve limitset: " + nam);
1111
1140
}
1112
1141
// / Assign cuts to region if they were created
1113
1142
if ( cuts ) g4->SetProductionCuts (cuts);
@@ -1120,27 +1149,32 @@ void* Geant4Converter::handleRegion(Region region, const set<const TGeoVolume*>&
1120
1149
void * Geant4Converter::handleLimitSet (LimitSet limitset, const set<const TGeoVolume*>& /* volumes */ ) const {
1121
1150
G4UserLimits* g4 = data ().g4Limits [limitset];
1122
1151
if ( !g4 ) {
1152
+ PrintLevel lvl = debugLimits || debugRegions ? ALWAYS : outputLevel;
1123
1153
struct LimitPrint {
1124
1154
const LimitSet& ls;
1125
1155
LimitPrint (const LimitSet& lset) : ls(lset) {}
1126
1156
const LimitPrint& operator ()(const std::string& pref, const Geant4UserLimits::Handler& h) const {
1127
1157
if ( !h.particleLimits .empty () ) {
1128
1158
printout (ALWAYS," Geant4Converter" ,
1129
- " +++ LimitSet: Limit %s.%s applied for particles:" ,ls.name (), pref.c_str ());
1159
+ " +++ LimitSet: Explicit Limit %s.%s applied for particles:" ,ls.name (), pref.c_str ());
1130
1160
for (const auto & p : h.particleLimits )
1131
1161
printout (ALWAYS," Geant4Converter" ," +++ LimitSet: Particle type: %-18s PDG: %-6d : %f" ,
1132
1162
p.first ->GetParticleName ().c_str (), p.first ->GetPDGEncoding (), p.second );
1133
1163
}
1134
- else {
1164
+ else if ( h. defaultValue > std::numeric_limits< double >:: epsilon () ) {
1135
1165
printout (ALWAYS," Geant4Converter" ,
1136
- " +++ LimitSet: Limit %s.%s NOT APPLIED." ,ls.name (), pref.c_str ());
1166
+ " +++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f" ,
1167
+ ls.name (), pref.c_str (), float (h.defaultValue ));
1137
1168
}
1138
1169
return *this ;
1139
1170
}
1140
1171
};
1141
1172
Geant4UserLimits* limits = new Geant4UserLimits (limitset);
1142
1173
g4 = limits;
1143
- if ( debugRegions ) {
1174
+ printout (lvl, " Geant4Converter" ,
1175
+ " ++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]" ,
1176
+ limitset.name (), limitset.cuts ().size (), limitset.limits ().size ());
1177
+ if ( debugRegions || debugLimits ) {
1144
1178
LimitPrint print (limitset);
1145
1179
print (" maxTime" , limits->maxTime )
1146
1180
(" minEKine" , limits->minEKine )
0 commit comments