37 #include <TTimeStamp.h>
38 #include <TGeoBoolNode.h>
41 #include <G4Version.hh>
42 #include <G4VisAttributes.hh>
43 #include <G4PVParameterised.hh>
44 #include <G4ProductionCuts.hh>
45 #include <G4VUserRegionInformation.hh>
49 #include <G4Ellipsoid.hh>
50 #include <G4UnionSolid.hh>
51 #include <G4ReflectedSolid.hh>
52 #include <G4SubtractionSolid.hh>
53 #include <G4IntersectionSolid.hh>
54 #include <G4VSensitiveDetector.hh>
56 #include <G4Region.hh>
57 #include <G4Element.hh>
58 #include <G4Isotope.hh>
59 #include <G4Material.hh>
60 #include <G4UserLimits.hh>
61 #include <G4RegionStore.hh>
62 #include <G4FieldManager.hh>
63 #include <G4LogicalVolume.hh>
64 #include <G4OpticalSurface.hh>
65 #include <G4ReflectionFactory.hh>
66 #include <G4LogicalSkinSurface.hh>
67 #include <G4ElectroMagneticField.hh>
68 #include <G4LogicalBorderSurface.hh>
69 #include <G4MaterialPropertiesTable.hh>
70 #if G4VERSION_NUMBER >= 1040
71 #include <G4MaterialPropertiesIndex.hh>
73 #include <G4ScaledSolid.hh>
74 #include <CLHEP/Units/SystemOfUnits.h>
88 static constexpr
const double CM_2_MM = (CLHEP::centimeter/dd4hep::centimeter);
89 static constexpr
const char* GEANT4_TAG_CUSTOM =
"Geant4-custom";
90 static constexpr
const char* GEANT4_TAG_IGNORE =
"Geant4-ignore";
91 static constexpr
const char* GEANT4_TAG_PLUGIN =
"Geant4-plugin";
92 static constexpr
const char* GEANT4_TAG_BIRKSCONSTANT =
"BirksConstant";
93 static constexpr
const char* GEANT4_TAG_MEE =
"MeanExcitationEnergy";
94 static constexpr
const char* GEANT4_TAG_ENE_PER_ION_PAIR =
"MeanEnergyPerIonPair";
96 static std::string indent =
"";
98 template <
typename O,
typename C,
typename F>
void handleRefs(
const O* o,
const C& c, F pmf) {
99 for (
typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
105 template <
typename O,
typename C,
typename F>
void handle(
const O* o,
const C& c, F pmf) {
106 for (
typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
107 (o->*pmf)((*i)->GetName(), *i);
111 template <
typename O,
typename F>
void handleArray(
const O* o,
const TObjArray* c, F pmf) {
112 TObjArrayIter arr(c);
113 for(
TObject* i = arr.Next(); i; i=arr.Next())
117 template <
typename O,
typename C,
typename F>
void handleMap(
const O* o,
const C& c, F pmf) {
118 for (
typename C::const_iterator i = c.begin(); i != c.end(); ++i)
119 (o->*pmf)((*i).first, (*i).second);
122 template <
typename O,
typename C,
typename F>
void handleRMap(
const O* o,
const C& c, F pmf) {
123 for (
typename C::const_reverse_iterator i = c.rbegin(); i != c.rend(); ++i) {
125 handle(o, i->second, pmf);
128 template <
typename O,
typename C,
typename F>
void handleRMap_(
const O* o,
const C& c, F pmf) {
129 for (
typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
130 const auto& cc = (*i).second;
131 for (
const auto& j : cc) {
137 std::string make_NCName(
const std::string& in) {
138 std::string res = detail::str_replace(in,
"/",
"_");
139 res = detail::str_replace(res,
"#",
"_");
143 bool is_left_handed(
const TGeoMatrix* m) {
144 const Double_t* r = m->GetRotationMatrix();
147 r[0]*r[4]*r[8] + r[3]*r[7]*r[2] + r[6]*r[1]*r[5] -
148 r[2]*r[4]*r[6] - r[5]*r[7]*r[0] - r[8]*r[1]*r[3];
154 class G4UserRegionInformation :
public G4VUserRegionInformation {
158 bool storeSecondaries;
159 G4UserRegionInformation()
160 : threshold(0.0), storeSecondaries(false) {
162 virtual ~G4UserRegionInformation() {
164 virtual void Print()
const {
166 printout(DEBUG,
"Region",
"Name:%s", region.
name());
170 std::pair<double,double> g4PropertyConversion(
int index) {
171 #if G4VERSION_NUMBER >= 1040
173 case kRINDEX:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
174 case kREFLECTIVITY:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
175 case kREALRINDEX:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
176 case kIMAGINARYRINDEX:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
177 case kEFFICIENCY:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
178 case kTRANSMITTANCE:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
179 case kSPECULARLOBECONSTANT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
180 case kSPECULARSPIKECONSTANT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
181 case kBACKSCATTERCONSTANT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
182 case kGROUPVEL:
return std::make_pair(CLHEP::keV/units::keV, (CLHEP::m/CLHEP::s)/(units::m/units::s));
183 case kMIEHG:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
184 case kRAYLEIGH:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
185 case kWLSCOMPONENT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
186 case kWLSABSLENGTH:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
187 case kABSLENGTH:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
188 #if G4VERSION_NUMBER >= 1100
189 case kWLSCOMPONENT2:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
190 case kWLSABSLENGTH2:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
191 case kSCINTILLATIONCOMPONENT1:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
192 case kSCINTILLATIONCOMPONENT2:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
193 case kSCINTILLATIONCOMPONENT3:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
195 case kFASTCOMPONENT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
196 case kSLOWCOMPONENT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
198 case kPROTONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
199 case kDEUTERONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
200 case kTRITONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
201 case kALPHASCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
202 case kIONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
203 case kELECTRONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
207 printout(FATAL,
"Geant4Converter",
"+++ Cannot convert material property with index: %d", index);
209 printout(FATAL,
"Geant4Converter",
"+++ Cannot convert material property with index: %d [Need Geant4 > 10.03]", index);
211 return std::make_pair(0e0,0e0);
214 double g4ConstPropertyConversion(
int index) {
215 #if G4VERSION_NUMBER >= 1040
217 case kSURFACEROUGHNESS:
return CLHEP::m/units::m;
218 case kISOTHERMAL_COMPRESSIBILITY:
return (CLHEP::m3/CLHEP::keV)/(units::m3/CLHEP::keV);
219 case kRS_SCALE_FACTOR:
return 1.0;
220 case kWLSMEANNUMBERPHOTONS:
return 1.0;
221 case kWLSTIMECONSTANT:
return CLHEP::second/units::second;
222 case kMIEHG_FORWARD:
return 1.0;
223 case kMIEHG_BACKWARD:
return 1.0;
224 case kMIEHG_FORWARD_RATIO:
return 1.0;
225 case kSCINTILLATIONYIELD:
return units::keV/CLHEP::keV;
226 case kRESOLUTIONSCALE:
return 1.0;
227 case kFERMIPOT:
return CLHEP::keV/units::keV;
228 case kDIFFUSION:
return 1.0;
229 case kSPINFLIP:
return 1.0;
230 case kLOSS:
return 1.0;
231 case kLOSSCS:
return CLHEP::barn/units::barn;
232 case kABSCS:
return CLHEP::barn/units::barn;
233 case kSCATCS:
return CLHEP::barn/units::barn;
234 case kMR_NBTHETA:
return 1.0;
235 case kMR_NBE:
return 1.0;
236 case kMR_RRMS:
return 1.0;
237 case kMR_CORRLEN:
return CLHEP::m/units::m;
238 case kMR_THETAMIN:
return 1.0;
239 case kMR_THETAMAX:
return 1.0;
240 case kMR_EMIN:
return CLHEP::keV/units::keV;
241 case kMR_EMAX:
return CLHEP::keV/units::keV;
242 case kMR_ANGNOTHETA:
return 1.0;
243 case kMR_ANGNOPHI:
return 1.0;
244 case kMR_ANGCUT:
return 1.0;
246 #if G4VERSION_NUMBER >= 1100
247 case kSCINTILLATIONTIMECONSTANT1:
return CLHEP::second/units::second;
248 case kSCINTILLATIONTIMECONSTANT2:
return CLHEP::second/units::second;
249 case kSCINTILLATIONTIMECONSTANT3:
return CLHEP::second/units::second;
250 case kSCINTILLATIONRISETIME1:
return CLHEP::second/units::second;
251 case kSCINTILLATIONRISETIME2:
return CLHEP::second/units::second;
252 case kSCINTILLATIONRISETIME3:
return CLHEP::second/units::second;
253 case kSCINTILLATIONYIELD1:
return 1.0;
254 case kSCINTILLATIONYIELD2:
return 1.0;
255 case kSCINTILLATIONYIELD3:
return 1.0;
256 case kPROTONSCINTILLATIONYIELD1:
return 1.0;
257 case kPROTONSCINTILLATIONYIELD2:
return 1.0;
258 case kPROTONSCINTILLATIONYIELD3:
return 1.0;
259 case kDEUTERONSCINTILLATIONYIELD1:
return 1.0;
260 case kDEUTERONSCINTILLATIONYIELD2:
return 1.0;
261 case kDEUTERONSCINTILLATIONYIELD3:
return 1.0;
262 case kALPHASCINTILLATIONYIELD1:
return 1.0;
263 case kALPHASCINTILLATIONYIELD2:
return 1.0;
264 case kALPHASCINTILLATIONYIELD3:
return 1.0;
265 case kIONSCINTILLATIONYIELD1:
return 1.0;
266 case kIONSCINTILLATIONYIELD2:
return 1.0;
267 case kIONSCINTILLATIONYIELD3:
return 1.0;
268 case kELECTRONSCINTILLATIONYIELD1:
return 1.0;
269 case kELECTRONSCINTILLATIONYIELD2:
return 1.0;
270 case kELECTRONSCINTILLATIONYIELD3:
return 1.0;
272 case kFASTTIMECONSTANT:
return CLHEP::second/units::second;
273 case kFASTSCINTILLATIONRISETIME:
return CLHEP::second/units::second;
274 case kSLOWTIMECONSTANT:
return CLHEP::second/units::second;
275 case kSLOWSCINTILLATIONRISETIME:
return CLHEP::second/units::second;
276 case kYIELDRATIO:
return 1.0;
281 printout(FATAL,
"Geant4Converter",
"+++ Cannot convert CONST material property with index: %d", index);
283 printout(FATAL,
"Geant4Converter",
"+++ Cannot convert material property with index: %d [Need Geant4 > 10.03]", index);
312 double a_conv = (CLHEP::g / CLHEP::mole);
313 g4i =
new G4Isotope(iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA()*a_conv);
315 "Geant4Converter",
"++ Created G4 Isotope %s from data: Z=%d N=%d A=%.3f [g/mole]",
316 iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA());
327 if (element->GetNisotopes() > 0) {
328 g4e =
new G4Element(name, element->GetTitle(), element->GetNisotopes());
329 for (
int i = 0, n = element->GetNisotopes(); i < n; ++i) {
330 TGeoIsotope* iso = element->GetIsotope(i);
331 G4Isotope* g4iso = (G4Isotope*)
handleIsotope(iso->GetName(), iso);
332 g4e->AddIsotope(g4iso, element->GetRelativeAbundance(i));
337 double a_conv = (CLHEP::g / CLHEP::mole);
338 g4e =
new G4Element(element->GetTitle(), name, element->Z(), element->A()*a_conv);
339 printout(lvl,
"Geant4Converter",
"++ Created G4 Isotope %s from data: Z=%d N=%d A=%.3f [g/mole]",
340 element->GetName(), element->Z(), element->N(), element->A());
342 std::stringstream str;
343 str << (*g4e) << std::endl;
344 printout(lvl,
"Geant4Converter",
"++ Created G4 element %s", str.str().c_str());
353 G4Material* mat =
info.g4Materials[medium];
356 TGeoMaterial* material = medium->GetMaterial();
357 G4State state = kStateUndefined;
358 double density = material->GetDensity() * (CLHEP::gram / CLHEP::cm3);
359 if ( density < 1e-25 )
361 switch ( material->GetState() ) {
362 case TGeoMaterial::kMatStateSolid:
365 case TGeoMaterial::kMatStateLiquid:
366 state = kStateLiquid;
368 case TGeoMaterial::kMatStateGas:
372 case TGeoMaterial::kMatStateUndefined:
373 state = kStateUndefined;
376 printout(lvl,
"Geant4Material",
"+++ Setting up material %s", name.c_str());
377 if ( material->IsMixture() ) {
378 double A_total = 0.0;
379 double W_total = 0.0;
380 TGeoMixture*
mix = (TGeoMixture*) material;
381 int nElements =
mix->GetNelements();
382 mat =
new G4Material(name, density, nElements, state,
383 material->GetTemperature(), material->GetPressure());
384 for (
int i = 0; i < nElements; ++i) {
385 A_total += (
mix->GetAmixt())[i];
386 W_total += (
mix->GetWmixt())[i];
388 for (
int i = 0; i < nElements; ++i) {
389 TGeoElement* e =
mix->GetElement(i);
392 printout(ERROR, name,
393 "Missing element component %s for material %s. A=%f W=%f",
394 e->GetName(),
mix->GetName(), A_total, W_total);
397 mat->AddElement(g4e, (
mix->GetWmixt())[i] / W_total);
401 double z = material->GetZ(), a = material->GetA();
402 if ( z < 1.0000001 ) z = 1.0;
403 if ( a < 0.5000001 ) a = 1.0;
404 mat =
new G4Material(name, z, a, density, state,
405 material->GetTemperature(), material->GetPressure());
408 std::string plugin_name { };
410 double ionisation_mee = -2e100;
411 double ionisation_birks_constant = -2e100;
412 double ionisation_ene_per_ion_pair = -2e100;
415 G4MaterialPropertiesTable* tab = 0;
416 TListIter propIt(&material->GetProperties());
417 for(
TObject* obj=propIt.Next(); obj; obj = propIt.Next()) {
419 bool custom_property =
false;
421 TGDMLMatrix* matrix =
info.manager->GetGDMLMatrix(named->GetTitle());
422 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
423 if(
nullptr != cptr ) {
424 printout(INFO,name,
"++ Ignore property %s [%s]. Not Suitable for Geant4.",
425 matrix->GetName(), matrix->GetTitle());
428 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
429 if(
nullptr != cptr ) {
430 printout(INFO,name,
"++ Ignore property %s [%s]. Not Suitable for Geant4.",
431 matrix->GetName(), matrix->GetTitle());
434 cptr = ::strstr(matrix->GetName(), GEANT4_TAG_CUSTOM);
435 if(
nullptr != cptr ) {
436 custom_property =
true;
438 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_CUSTOM);
439 if(
nullptr != cptr ) {
440 custom_property =
true;
446 except(
"Geant4Converter",
"++ FAILED to create G4 material %s [Cannot convert property:%s]",
447 material->GetName(), named->GetName());
449 if(
nullptr == tab ) {
450 tab =
new G4MaterialPropertiesTable();
451 mat->SetMaterialPropertiesTable(tab);
455 if( !custom_property ) {
456 const auto& pn = tab->GetMaterialPropertyNames();
457 if( std::find(std::begin(pn), std::end(pn), named->GetName()) != pn.end() ) {
458 idx = tab->GetPropertyIndex(named->GetName());
469 if ( idx < 0 && !custom_property ) {
470 printout(ERROR,
"Geant4Converter",
471 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
472 exc_str.c_str(), named->GetName());
476 std::vector<double> bins(
v->bins), vals(
v->values);
477 std::pair<double, double> conv = { 1e0, 1e0 };
478 if( !custom_property ) {
479 conv = g4PropertyConversion(idx);
480 for(std::size_t i=0, count=bins.size(); i<count; ++i)
481 bins[i] *= conv.first, vals[i] *= conv.second;
483 G4MaterialPropertyVector* vec =
484 new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
485 #if G4VERSION_NUMBER >= 1100
486 tab->AddProperty(named->GetName(), vec, custom_property);
488 tab->AddProperty(named->GetName(), vec);
490 printout(lvl, name,
"++ %sProperty: %-20s [%ld x %ld] -> %s ",
491 custom_property ?
"CUSTOM " :
"", named->GetName(),
492 matrix->GetRows(), matrix->GetCols(), named->GetTitle());
493 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
494 printout(lvl, name,
" Geant4: %s %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
495 named->GetName(), bins[i],
v->bins[i], conv.first);
499 TListIter cpropIt(&material->GetConstProperties());
500 for(
TObject* obj=cpropIt.Next(); obj; obj = cpropIt.Next()) {
504 bool custom_property =
false;
506 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
507 if(
nullptr != cptr ) {
508 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
509 named->GetName(), named->GetTitle());
512 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
513 if(
nullptr != cptr ) {
514 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
515 named->GetName(), named->GetTitle());
518 cptr = ::strstr(named->GetName(), GEANT4_TAG_PLUGIN);
519 if(
nullptr != cptr ) {
520 printout(INFO, name,
"++ Ignore CONST property %s [%s] --> Plugin.",
521 named->GetName(), named->GetTitle());
522 plugin_name = named->GetTitle();
525 cptr = ::strstr(named->GetName(), GEANT4_TAG_BIRKSCONSTANT);
526 if(
nullptr != cptr ) {
528 value = material->GetConstProperty(GEANT4_TAG_BIRKSCONSTANT,&err);
529 if ( err == kFALSE ) ionisation_birks_constant = value * (CLHEP::mm/CLHEP::MeV)/(units::mm/units::MeV);
532 cptr = ::strstr(named->GetName(), GEANT4_TAG_MEE);
533 if(
nullptr != cptr ) {
535 value = material->GetConstProperty(GEANT4_TAG_MEE, &err);
536 if ( err == kFALSE ) ionisation_mee = value * (CLHEP::MeV/units::MeV);
539 cptr = ::strstr(named->GetName(), GEANT4_TAG_ENE_PER_ION_PAIR);
540 if(
nullptr != cptr ) {
542 value = material->GetConstProperty(GEANT4_TAG_ENE_PER_ION_PAIR,&err);
543 if ( err == kFALSE ) ionisation_ene_per_ion_pair = value * (CLHEP::MeV/units::MeV);
546 cptr = ::strstr(named->GetName(), GEANT4_TAG_CUSTOM);
547 if (
nullptr != cptr ) {
548 custom_property =
true;
550 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_CUSTOM);
551 if (
nullptr != cptr ) {
552 custom_property =
true;
556 value =
info.manager->GetProperty(named->GetTitle(), &err);
557 if ( err != kFALSE ) {
559 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
560 material->GetName(), named->GetName());
562 if (
nullptr == tab ) {
563 tab =
new G4MaterialPropertiesTable();
564 mat->SetMaterialPropertiesTable(tab);
568 if( !custom_property ) {
569 const auto& pn = tab->GetMaterialConstPropertyNames();
570 if( std::find(std::begin(pn), std::end(pn), named->GetName()) != pn.end() ) {
571 idx = tab->GetConstPropertyIndex(named->GetName());
582 if ( idx < 0 && !custom_property ) {
583 printout(ERROR, name,
584 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
585 exc_str.c_str(), named->GetName());
589 if ( !custom_property ) {
590 double conv = g4ConstPropertyConversion(idx);
591 value = value * conv;
593 printout(lvl, name,
"++ %sCONST Property: %-20s %g ",
594 custom_property ?
"CUSTOM " :
"", named->GetName(), value);
595 tab->AddConstProperty(named->GetName(), value);
599 auto* ionisation = mat->GetIonisation();
600 std::stringstream str;
603 if ( ionisation_birks_constant > 0e0 ) {
604 ionisation->SetBirksConstant(ionisation_birks_constant);
606 if ( ionisation_mee > -1e100 ) {
607 ionisation->SetMeanExcitationEnergy(ionisation_mee);
609 if ( ionisation_ene_per_ion_pair > 0e0 ) {
610 ionisation->SetMeanEnergyPerIonPair(ionisation_ene_per_ion_pair);
612 str <<
" log(MEE): " << std::setprecision(4) << ionisation->GetLogMeanExcEnergy();
613 if ( ionisation_birks_constant > 0e0 )
614 str <<
" Birk's constant: " << std::setprecision(4) << ionisation->GetBirksConstant() <<
" [mm/MeV]";
615 if ( ionisation_ene_per_ion_pair > 0e0 )
616 str <<
" Mean Energy Per Ion Pair: " << std::setprecision(4) << ionisation->GetMeanEnergyPerIonPair()/CLHEP::eV <<
" [eV]";
619 str <<
" No ionisation parameters available.";
621 printout(lvl, name,
"++ Created G4 material %s", str.str().c_str());
623 if ( !plugin_name.empty() ) {
626 G4Material* extended_mat = PluginService::Create<G4Material*>(plugin_name,
det, medium, mat);
627 if ( !extended_mat ) {
628 except(
"G4Cnv::material["+name+
"]",
"++ FATAL Failed to call plugin to create material.");
632 info.g4Materials[medium] = mat;
639 G4VSolid* solid =
nullptr;
641 if (
nullptr != (solid =
data().g4Solids[shape]) ) {
644 TClass* isa = shape->IsA();
646 if (isa == TGeoShapeAssembly::Class()) {
652 else if (isa == TGeoBBox::Class())
654 else if (isa == TGeoTube::Class())
656 else if (isa == TGeoTubeSeg::Class())
658 else if (isa == TGeoCtub::Class())
660 else if (isa == TGeoEltu::Class())
662 else if (isa == TwistedTubeObject::Class())
664 else if (isa == TGeoTrd1::Class())
666 else if (isa == TGeoTrd2::Class())
668 else if (isa == TGeoHype::Class())
670 else if (isa == TGeoXtru::Class())
672 else if (isa == TGeoPgon::Class())
674 else if (isa == TGeoPcon::Class())
676 else if (isa == TGeoCone::Class())
678 else if (isa == TGeoConeSeg::Class())
680 else if (isa == TGeoParaboloid::Class())
682 else if (isa == TGeoSphere::Class())
684 else if (isa == TGeoTorus::Class())
686 else if (isa == TGeoTrap::Class())
688 else if (isa == TGeoArb8::Class())
690 else if (isa == TGeoPara::Class())
692 else if (isa == TGeoTessellated::Class())
694 else if (isa == TGeoScaledShape::Class()) {
695 TGeoScaledShape* sh = (TGeoScaledShape*) shape;
696 TGeoShape* sol = sh->GetShape();
697 if ( sol->IsA() == TGeoShapeAssembly::Class() ) {
700 const double* vals = sh->GetScale()->GetScale();
701 G4Scale3D scal(vals[0], vals[1], vals[2]);
702 G4VSolid* g4solid = (G4VSolid*)
handleSolid(sol->GetName(), sol);
703 if ( scal.xx()>0e0 && scal.yy()>0e0 && scal.zz()>0e0 )
704 solid =
new G4ScaledSolid(sh->GetName(), g4solid, scal);
706 solid =
new G4ReflectedSolid(g4solid->GetName()+
"_refl", g4solid, scal);
708 else if ( isa == TGeoCompositeShape::Class() ) {
709 const TGeoCompositeShape* sh = (
const TGeoCompositeShape*) shape;
710 const TGeoBoolNode*
boolean = sh->GetBoolNode();
711 TGeoBoolNode::EGeoBoolType oper =
boolean->GetBooleanOperator();
712 TGeoMatrix* matrix =
boolean->GetRightMatrix();
713 G4VSolid* left = (G4VSolid*)
handleSolid(name +
"_left", boolean->GetLeftShape());
714 G4VSolid* right = (G4VSolid*)
handleSolid(name +
"_right", boolean->GetRightShape());
717 except(
"Geant4Converter",
"++ No left Geant4 Solid present for composite shape: %s",name.c_str());
720 except(
"Geant4Converter",
"++ No right Geant4 Solid present for composite shape: %s",name.c_str());
723 TGeoShape* ls =
boolean->GetLeftShape();
724 TGeoShape* rs =
boolean->GetRightShape();
725 if (strcmp(ls->ClassName(),
"TGeoScaledShape") == 0 &&
726 strcmp(rs->ClassName(),
"TGeoBBox") == 0) {
727 if (strcmp(((TGeoScaledShape *)ls)->GetShape()->ClassName(),
"TGeoSphere") == 0) {
728 if (oper == TGeoBoolNode::kGeoIntersection) {
729 TGeoScaledShape* lls = (TGeoScaledShape *)ls;
730 TGeoBBox* rrs = (TGeoBBox*)rs;
731 double sx = lls->GetScale()->GetScale()[0];
732 double sy = lls->GetScale()->GetScale()[1];
733 double radius = ((TGeoSphere *)lls->GetShape())->GetRmax();
734 double dz = rrs->GetDZ();
735 double zorig = rrs->GetOrigin()[2];
736 double zcut2 = dz + zorig;
737 double zcut1 = 2 * zorig - zcut2;
738 solid =
new G4Ellipsoid(name,
750 if ( matrix->IsRotation() ) {
751 G4Transform3D transform;
753 if (oper == TGeoBoolNode::kGeoSubtraction)
754 solid =
new G4SubtractionSolid(name, left, right, transform);
755 else if (oper == TGeoBoolNode::kGeoUnion)
756 solid =
new G4UnionSolid(name, left, right, transform);
757 else if (oper == TGeoBoolNode::kGeoIntersection)
758 solid =
new G4IntersectionSolid(name, left, right, transform);
761 const Double_t *t = matrix->GetTranslation();
763 if (oper == TGeoBoolNode::kGeoSubtraction)
764 solid =
new G4SubtractionSolid(name, left, right, 0, transform);
765 else if (oper == TGeoBoolNode::kGeoUnion)
766 solid =
new G4UnionSolid(name, left, right, 0, transform);
767 else if (oper == TGeoBoolNode::kGeoIntersection)
768 solid =
new G4IntersectionSolid(name, left, right, 0, transform);
773 except(
"Geant4Converter",
"++ Failed to handle unknown solid shape: %s of type %s",
774 name.c_str(), isa->GetName());
775 printout(lvl,
"Geant4Converter",
"++ Successessfully converted shape [%p] of type:%s to %s.",
776 solid,isa->GetName(),typeName(
typeid(*solid)).c_str());
787 Geant4GeometryMaps::VolumeMap::const_iterator volIt =
info.g4Volumes.find(volume);
789 printout(lvl,
"Geant4Converter",
790 "++ Volume %s not converted [Veto'ed for simulation]",
794 else if (volIt ==
info.g4Volumes.end() ) {
795 const char* vnam = volume->GetName();
796 TGeoMedium* med = volume->GetMedium();
797 Solid sh = volume->GetShape();
798 bool is_assembly = sh->IsA() == TGeoShapeAssembly::Class() || volume->IsAssembly();
800 printout(lvl,
"Geant4Converter",
"++ Convert Volume %-32s: %p %s/%s assembly:%s",
801 vnam, volume, sh.
type(), _v.
type(), yes_no(is_assembly));
808 G4Region* g4region = reg.
isValid() ?
info.g4Regions[reg] :
nullptr;
810 G4VSolid* g4solid = (G4VSolid*)
handleSolid(sh->GetName(), sh);
814 except(
"G4Converter",
"++ No Geant4 Solid present for volume: %s", vnam);
816 else if ( !g4medium ) {
817 except(
"G4Converter",
"++ No Geant4 material present for volume: %s", vnam);
819 else if ( reg.
isValid() && !g4region ) {
820 except(
"G4Cnv::volume["+name+
"]",
" ++ Failed to access Geant4 region %s.", reg.
name());
822 else if ( lim.
isValid() && !g4limits ) {
823 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to access Geant4 user limits %s.", lim.
name());
825 else if ( g4limits ) {
826 printout(lvl,
"Geant4Converter",
"++ Volume + Apply LIMITS settings: %-24s to volume %s.",
830 G4LogicalVolume* g4vol =
nullptr;
833 std::string plugin = _v.
getProperty(GEANT4_TAG_PLUGIN,
"");
834 g4vol = PluginService::Create<G4LogicalVolume*>(plugin,
det, _v, g4solid, g4medium);
836 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to call plugin to create logical volume.");
840 g4vol =
new G4LogicalVolume(g4solid, g4medium, vnam,
nullptr,
nullptr,
nullptr);
846 printout(ALWAYS,
"Geant4Converter",
847 "++ Volume %s Set Smartless value to %d",
848 vnam,
int(smart_less_value));
849 g4vol->SetSmartless( smart_less_value );
853 g4vol->SetUserLimits(g4limits);
856 printout(plevel,
"Geant4Converter",
857 "++ Volume + Apply REGION settings: %-24s to volume %s.",
863 const char* wrd_nam =
"DefaultRegionForTheWorld";
864 const char* src_nam = g4region->GetName().c_str();
865 auto* world_region = G4RegionStore::GetInstance()->GetRegion(wrd_nam,
false);
866 if (
auto* cuts = g4region->GetProductionCuts() ) {
867 world_region->SetProductionCuts(cuts);
868 printout(plevel,
"Geant4Converter",
869 "++ Volume %s Region: %s. Apply production cuts from %s",
870 vnam, wrd_nam, src_nam);
872 if (
auto* lims = g4region->GetUserLimits() ) {
873 world_region->SetUserLimits(lims);
874 printout(plevel,
"Geant4Converter",
875 "++ Volume %s Region: %s. Apply user limits from %s",
876 vnam, wrd_nam, src_nam);
880 g4vol->SetRegion(g4region);
881 g4region->AddRootLogicalVolume(g4vol);
884 G4VisAttributes* g4vattr = vis.
isValid()
887 g4vol->SetVisAttributes(g4vattr);
889 info.g4Volumes[volume] = g4vol;
890 printout(lvl,
"Geant4Converter",
891 "++ Volume + %s converted: %p ---> G4: %p", vnam, volume, g4vol);
907 info.limits[lim].insert(volume);
909 info.regions[reg].insert(volume);
911 info.sensitives[
det].insert(volume);
913 return (
void*)volume;
918 TGeoVolume* mot_vol = node->GetVolume();
920 if ( mot_vol->IsA() != TGeoVolumeAssembly::Class() ) {
925 printout(lvl,
"Geant4Converter",
"++ AssemblyNode %s not converted [Veto'ed for simulation]",node->GetName());
931 printout(ALWAYS,
"Geant4Converter",
"+++ Assembly: **** : Re-using existing assembly: %s",node->GetName());
935 for(Int_t i=0; i < mot_vol->GetNdaughters(); ++i) {
936 TGeoNode* dau = mot_vol->GetNode(i);
937 TGeoVolume* dau_vol = dau->GetVolume();
938 TGeoMatrix* tr = dau->GetMatrix();
939 G4Transform3D transform;
942 if ( is_left_handed(tr) ) {
946 transform.getDecomposition(scale, rot, trans);
948 "++ Placing reflected ASSEMBLY. dau:%s to mother %s "
949 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
950 dau_vol->GetName(), mot_vol->GetName(),
951 transform.dx(), transform.dy(), transform.dz(),
952 scale.xx(), scale.yy(), scale.zz());
955 if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) {
956 Geant4GeometryMaps::AssemblyMap::iterator ia =
info.g4AssemblyVolumes.find(dau);
957 if ( ia ==
info.g4AssemblyVolumes.end() ) {
958 printout(FATAL,
"Geant4Converter",
"+++ Invalid child assembly at %s : %d parent: %s child:%s",
959 __FILE__, __LINE__, name.c_str(), dau->GetName());
964 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedAssembly %p: dau:%s "
965 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
966 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
967 transform.dx(), transform.dy(), transform.dz());
970 Geant4GeometryMaps::VolumeMap::iterator iv =
info.g4Volumes.find(dau_vol);
971 if ( iv ==
info.g4Volumes.end() ) {
972 printout(FATAL,
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
973 __FILE__, __LINE__, name.c_str(), dau->GetName());
974 except(
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
975 __FILE__, __LINE__, name.c_str(), dau->GetName());
978 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedVolume %p: dau:%s "
979 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
980 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
981 transform.dx(), transform.dy(), transform.dz());
984 info.g4AssemblyVolumes[node] = g4;
993 Geant4GeometryMaps::PlacementMap::const_iterator g4it =
info.g4Placements.find(node);
994 G4VPhysicalVolume* g4 = (g4it ==
info.g4Placements.end()) ? 0 : (*g4it).second;
995 TGeoVolume* vol = node->GetVolume();
999 printout(lvl,
"Geant4Converter",
"++ Placement %s not converted [Veto'ed for simulation]",node->GetName());
1004 TGeoVolume* mot_vol = node->GetMotherVolume();
1005 TGeoMatrix* tr = node->GetMatrix();
1007 except(
"Geant4Converter",
1008 "++ Attempt to handle placement without transformation:%p %s of type %s vol:%p",
1009 node, node->GetName(), node->IsA()->GetName(), vol);
1011 else if (
nullptr == vol) {
1012 except(
"Geant4Converter",
"++ Unknown G4 volume:%p %s of type %s ptr:%p",
1013 node, node->GetName(), node->IsA()->GetName(), vol);
1016 int copy = node->GetNumber();
1017 bool node_is_reflected = is_left_handed(tr);
1018 bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class();
1019 bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() :
false;
1021 if ( mother_is_assembly ) {
1028 printout(lvl,
"Geant4Converter",
"+++ Assembly: **** : daughter %s to mother %s",
1029 vol->GetName(), mot_vol ? mot_vol->GetName() :
"????");
1033 G4LogicalVolume* g4mot =
nullptr;
1034 auto volIt =
info.g4Volumes.find(mot_vol);
1035 if ( volIt !=
info.g4Volumes.end() ) {
1041 g4mot = (*volIt).second;
1043 else if ( node !=
info.manager->GetTopNode() ) {
1049 TGeoIterator iter(
info.manager->GetTopVolume());
1051 printout(ALWAYS,
"Geant4Converter",
"+++ (SHOULD NOT ENTER HERE) Assembly: no G4 mother: %s org mot: %p",
1052 node->GetName(), mot_vol);
1053 while ( (n1=iter.Next()) ) {
1055 TGeoNode* nmot = iter.GetNode(iter.GetLevel()-1);
1056 TGeoVolume* mmot = nmot->GetVolume();
1057 volIt =
info.g4Volumes.find(mmot);
1058 if ( volIt !=
info.g4Volumes.end() ) {
1061 g4mot = (*volIt).second;
1062 printout(ALWAYS,
"Geant4Converter",
"+++ Assembly: Realigned mother: %s org mot: %p aligned: %p",
1063 path.Data(), mot_vol, mmot);
1072 G4Translate3D trans;
1073 G4Transform3D transform;
1075 transform.getDecomposition(scale, rotate, trans);
1076 if ( node_is_assembly ) {
1081 printout(lvl,
"Geant4Converter",
"++ Assembly: makeImprint: dau:%-12s %s in mother %-12s "
1082 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1083 node->GetName(), node_is_reflected ?
"(REFLECTED)" :
"",
1084 mot_vol ? mot_vol->GetName() :
"<unknown>",
1085 transform.dx(), transform.dy(), transform.dz(),
1086 scale.xx(), scale.yy(), scale.zz());
1089 chain.emplace_back(node);
1091 except(
"Geant4Converter",
1092 "+++ Assembly: %s mother: %s Geant4AssemblyVolume not present!",
1093 node->GetName(), mot_vol ? mot_vol->GetName() :
"<unknown>");
1098 else if ( node !=
info.manager->GetTopNode() &&
nullptr == g4mot ) {
1102 const auto* pv_data = pv.
data();
1103 G4LogicalVolume* g4vol =
info.g4Volumes[vol];
1105 G4PhysicalVolumesPair pvPlaced {
nullptr,
nullptr };
1108 EAxis axis = kUndefined;
1109 double width = 0e0, offset = 0e0;
1110 auto flags = pv_data->params->flags;
1111 auto count = pv_data->params->trafo1D.second;
1112 auto start = pv_data->params->start.Translation().Vect();
1113 auto delta = pv_data->params->trafo1D.first.Translation().Vect();
1116 { axis = kXAxis; width =
delta.X(); offset = start.X(); }
1118 { axis = kYAxis; width =
delta.Y(); offset = start.Y(); }
1120 { axis = kZAxis; width =
delta.Z(); offset = start.Z(); }
1122 except(
"Geant4Converter",
1123 "++ Replication around unknown axis is not implemented. flags: %16X", flags);
1124 printout(INFO,
"Geant4Converter",
"++ Replicate: Axis: %ld Count: %ld offset: %f width: %f",
1125 axis, count, offset, width);
1126 auto* g4pv =
new G4PVReplica(name,
1133 pvPlaced = { g4pv,
nullptr };
1136 G4ReflectionFactory::Instance()->Replicate(name,
1144 auto* g4pv = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1146 for(
auto& handle : pv_data->params->placements )
1147 info.g4Placements[handle.ptr()] = g4pv;
1149 else if ( pv_data && pv_data->params ) {
1151 auto* g4pv =
new G4PVParameterised(name,
1157 pvPlaced = { g4pv,
nullptr };
1159 for(
auto& handle : pv_data->params->placements )
1160 info.g4Placements[handle.ptr()] = g4pv;
1164 G4ReflectionFactory::Instance()->Place(transform,
1173 "++ Place %svolume %-12s in mother %-12s "
1174 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1175 node_is_reflected ?
"REFLECTED " :
"", _v.
name(),
1176 mot_vol ? mot_vol->GetName() :
"<unknown>",
1177 transform.dx(), transform.dy(), transform.dz(),
1178 scale.xx(), scale.yy(), scale.zz());
1181 if ( node_is_reflected && !pvPlaced.second )
1182 return info.g4Placements[node] = pvPlaced.first;
1183 else if ( !node_is_reflected && !pvPlaced.second )
1184 return info.g4Placements[node] = pvPlaced.first;
1186 if ( node_is_reflected )
1187 return info.g4Placements[node] = pvPlaced.first;
1188 else if ( !node_is_reflected )
1189 return info.g4Placements[node] = pvPlaced.first;
1190 g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1192 info.g4Placements[node] = g4;
1193 printout(ERROR,
"Geant4Converter",
"++ DEAD code. Should not end up here!");
1204 g4 =
new G4Region(region.
name());
1208 throw std::runtime_error(
"G4Region: StoreSecondaries is True, but no explicit threshold set:");
1210 printout(lvl,
"Geant4Converter",
"++ Setting up region: %s", r.
name());
1211 G4UserRegionInformation*
info =
new G4UserRegionInformation();
1215 g4->SetUserInformation(
info);
1217 printout(lvl,
"Geant4Converter",
"++ Converted region settings of:%s.", r.
name());
1218 std::vector < std::string > &limits = r.
limits();
1219 G4ProductionCuts* cuts = 0;
1222 cuts =
new G4ProductionCuts();
1223 cuts->SetProductionCut(r.
cut()*CLHEP::mm/units::mm);
1224 printout(lvl,
"Geant4Converter",
"++ %s: Using default cut: %f [mm]",
1225 r.
name(), r.
cut()*CLHEP::mm/units::mm);
1227 for(
const auto& nam : limits ) {
1231 for (
const auto& c : cts ) {
1233 if ( c.particles ==
"*" ) pid = -1;
1234 else if ( c.particles ==
"e-" ) pid = idxG4ElectronCut;
1235 else if ( c.particles ==
"e+" ) pid = idxG4PositronCut;
1236 else if ( c.particles ==
"e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1237 else if ( c.particles ==
"e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1238 else if ( c.particles ==
"gamma" ) pid = idxG4GammaCut;
1239 else if ( c.particles ==
"proton" ) pid = idxG4ProtonCut;
1240 else throw std::runtime_error(
"G4Region: Invalid production cut particle-type:" + c.particles);
1241 if ( !cuts ) cuts =
new G4ProductionCuts();
1242 if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1243 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4PositronCut);
1244 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4ElectronCut);
1247 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, pid);
1249 printout(lvl,
"Geant4Converter",
"++ %s: Set cut [%s/%d] = %f [mm]",
1250 r.
name(), c.particles.c_str(), pid, c.value*CLHEP::mm/units::mm);
1254 for (
const auto& j : lm ) {
1255 if (nam == j.first->GetName()) {
1256 g4->SetUserLimits(j.second);
1257 printout(lvl,
"Geant4Converter",
"++ %s: Set limits %s to region type %s",
1258 r.
name(), nam.c_str(), j.second->GetType().c_str());
1267 except(
"Geant4Converter",
"++ G4Region: Failed to resolve limitset: " + nam);
1270 if ( cuts ) g4->SetProductionCuts(cuts);
1283 LimitPrint(
const LimitSet& lset) : ls(lset) {}
1286 printout(ALWAYS,
"Geant4Converter",
1287 "+++ LimitSet: Explicit Limit %s.%s applied for particles:",ls.
name(), pref.c_str());
1289 printout(ALWAYS,
"Geant4Converter",
"+++ LimitSet: Particle type: %-18s PDG: %-6d : %f",
1290 p.first->GetParticleName().c_str(), p.first->GetPDGEncoding(), p.second);
1293 printout(ALWAYS,
"Geant4Converter",
1294 "+++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f",
1302 printout(lvl,
"Geant4Converter",
1303 "++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]",
1304 limitset.
name(), limitset.
cuts().size(), limitset.
limits().size());
1306 LimitPrint print(limitset);
1307 print(
"maxTime", limits->
maxTime)
1321 G4VisAttributes* g4 =
info.g4Vis[attr];
1323 float red = 0, green = 0, blue = 0;
1325 attr.
rgb(red, green, blue);
1326 g4 =
new G4VisAttributes(attr.
visible(), G4Colour(red, green, blue, attr.
alpha()));
1330 g4->SetLineStyle(G4VisAttributes::unbroken);
1331 g4->SetForceWireframe(
false);
1332 g4->SetForceSolid(
true);
1335 g4->SetLineStyle(G4VisAttributes::dashed);
1336 g4->SetForceSolid(
false);
1337 g4->SetForceWireframe(
true);
1339 info.g4Vis[attr] = g4;
1346 std::map < std::string, std::string > processors;
1347 static int s_idd = 9999999;
1348 for(
const auto& [nam, vals] : prp ) {
1349 if ( nam.substr(0, 6) ==
"geant4" ) {
1350 auto id_it = vals.find(
"id");
1351 std::string
id = (id_it == vals.end()) ?
_toString(++s_idd,
"%d") : (*id_it).second;
1352 processors.emplace(
id, nam);
1355 for(
const auto& p : processors ) {
1358 auto iter = vals.find(
"type");
1359 if ( iter != vals.end() ) {
1360 std::string type = iter->second;
1361 std::string tag = type +
"_Geant4_action";
1363 long res = PluginService::Create<long>(tag,
det, hdlr, &vals);
1365 throw std::runtime_error(
"Failed to locate plugin to interprete files of type"
1366 " \"" + tag +
"\" - no factory:" + type);
1370 throw std::runtime_error(
"Failed to invoke the plugin " + tag +
" of type " + type);
1372 printout(
outputLevel,
"Geant4Converter",
"+++++ Executed Successfully Geant4 setup module *%s*.", type.c_str());
1375 printout(
outputLevel,
"Geant4Converter",
"+++++ FAILED to execute Geant4 setup module *%s*.", p.second.c_str());
1382 TGDMLMatrix* matrix = (TGDMLMatrix*)mtx;
1383 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1386 if (
nullptr != cptr ) {
1387 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1388 matrix->GetName(), matrix->GetTitle());
1391 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
1392 if (
nullptr != cptr ) {
1393 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1394 matrix->GetName(), matrix->GetTitle());
1401 std::size_t rows = matrix->GetRows();
1402 g4->
name = matrix->GetName();
1403 g4->
title = matrix->GetTitle();
1404 g4->
bins.reserve(rows);
1405 g4->
values.reserve(rows);
1406 for( std::size_t i=0; i<rows; ++i ) {
1407 g4->
bins.emplace_back(matrix->Get(i,0) );
1408 g4->
values.emplace_back(matrix->Get(i,1));
1410 printout(lvl,
"Geant4Converter",
1411 "++ Successfully converted material property:%s : %s [%ld rows]",
1412 matrix->GetName(), matrix->GetTitle(), rows);
1413 info.g4OpticalProperties[matrix] = g4;
1418 static G4OpticalSurfaceFinish geant4_surface_finish(TGeoOpticalSurface::ESurfaceFinish f) {
1419 #define TO_G4_FINISH(x) case TGeoOpticalSurface::kF##x : return x;
1467 printout(ERROR,
"Geant4Surfaces",
"++ Unknown finish style: %d [%s]. Assume polished!",
1468 int(f), TGeoOpticalSurface::FinishToString(f));
1474 static G4SurfaceType geant4_surface_type(TGeoOpticalSurface::ESurfaceType t) {
1475 #define TO_G4_TYPE(x) case TGeoOpticalSurface::kT##x : return x;
1485 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface type: %d [%s]. Assume dielectric_metal!",
1486 int(t), TGeoOpticalSurface::TypeToString(t));
1487 return dielectric_metal;
1492 static G4OpticalSurfaceModel geant4_surface_model(TGeoOpticalSurface::ESurfaceModel surfMod) {
1493 #define TO_G4_MODEL(x) case TGeoOpticalSurface::kM##x : return x;
1501 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface model: %d [%s]. Assume glisur!",
1502 int(surfMod), TGeoOpticalSurface::ModelToString(surfMod));
1510 TGeoOpticalSurface* optSurf = (TGeoOpticalSurface*)surface;
1512 G4OpticalSurface* g4 =
info.g4OpticalSurfaces[optSurf];
1514 G4SurfaceType type = geant4_surface_type(optSurf->GetType());
1515 G4OpticalSurfaceModel model = geant4_surface_model(optSurf->GetModel());
1516 G4OpticalSurfaceFinish finish = geant4_surface_finish(optSurf->GetFinish());
1517 std::string name = make_NCName(optSurf->GetName());
1519 g4 =
new G4OpticalSurface(name, model, finish, type, optSurf->GetValue());
1520 g4->SetSigmaAlpha(optSurf->GetSigmaAlpha());
1521 g4->SetPolish(optSurf->GetPolish());
1523 printout(lvl,
"Geant4Converter",
1524 "++ Created OpticalSurface: %-18s type:%s model:%s finish:%s SigmaAlphs: %.3e Polish: %.3e",
1526 TGeoOpticalSurface::TypeToString(optSurf->GetType()),
1527 TGeoOpticalSurface::ModelToString(optSurf->GetModel()),
1528 TGeoOpticalSurface::FinishToString(optSurf->GetFinish()),
1529 optSurf->GetSigmaAlpha(), optSurf->GetPolish());
1532 G4MaterialPropertiesTable* tab =
nullptr;
1533 TListIter itp(&optSurf->GetProperties());
1534 for(
TObject* obj = itp.Next(); obj; obj = itp.Next()) {
1535 std::string exc_str;
1537 TGDMLMatrix* matrix =
info.manager->GetGDMLMatrix(named->GetTitle());
1538 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1539 if (
nullptr != cptr )
1542 if (
nullptr == tab ) {
1543 tab =
new G4MaterialPropertiesTable();
1544 g4->SetMaterialPropertiesTable(tab);
1550 except(
"Geant4OpticalSurface",
"++ Failed to convert opt.surface %s. Property table %s is not defined!",
1551 optSurf->GetName(), named->GetTitle());
1555 idx = tab->GetPropertyIndex(named->GetName());
1563 printout(ERROR,
"Geant4Converter",
1564 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
1565 exc_str.c_str(), named->GetName());
1569 auto conv = g4PropertyConversion(idx);
1570 std::vector<double> bins(
v->bins), vals(
v->values);
1571 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1572 bins[i] *= conv.first, vals[i] *= conv.second;
1573 G4MaterialPropertyVector* vec =
new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
1574 tab->AddProperty(named->GetName(), vec);
1576 printout(lvl,
"Geant4Converter",
1577 "++ Property: %-20s [%ld x %ld] --> %s",
1578 named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
1579 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1580 printout(lvl, named->GetName(),
1581 " Geant4: %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
1582 bins[i],
v->bins[i], conv.first);
1586 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
1587 TListIter itc(&optSurf->GetConstProperties());
1588 for(
TObject* obj = itc.Next(); obj; obj = itc.Next()) {
1589 std::string exc_str;
1591 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
1592 if (
nullptr != cptr ) {
1593 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1594 named->GetName(), named->GetTitle());
1597 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
1598 if (
nullptr != cptr ) {
1599 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1600 named->GetName(), named->GetTitle());
1603 Bool_t err = kFALSE;
1604 Double_t value =
info.manager->GetProperty(named->GetTitle(),&err);
1605 if ( err != kFALSE ) {
1607 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
1608 optSurf->GetName(), named->GetName());
1610 if (
nullptr == tab ) {
1611 tab =
new G4MaterialPropertiesTable();
1612 g4->SetMaterialPropertiesTable(tab);
1616 idx = tab->GetConstPropertyIndex(named->GetName());
1624 printout(ERROR, name,
1625 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
1626 exc_str.c_str(), named->GetName());
1630 double conv = g4ConstPropertyConversion(idx);
1631 printout(lvl, name,
"++ CONST Property: %-20s %g * %g --> %g ",
1632 named->GetName(), value, conv, value * conv);
1633 tab->AddConstProperty(named->GetName(), value * conv);
1635 #endif // ROOT_VERSION >= 6.31.1
1636 info.g4OpticalSurfaces[optSurf] = g4;
1643 TGeoSkinSurface* surf = (TGeoSkinSurface*)surface;
1645 G4LogicalSkinSurface* g4 =
info.g4SkinSurfaces[surf];
1647 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1648 G4LogicalVolume*
v =
info.g4Volumes[surf->GetVolume()];
1649 std::string name = make_NCName(surf->GetName());
1650 g4 =
new G4LogicalSkinSurface(name,
v, optSurf);
1652 "++ Created SkinSurface: %-18s optical:%s",
1653 surf->GetName(), surf->GetSurface()->GetName());
1654 info.g4SkinSurfaces[surf] = g4;
1661 TGeoBorderSurface* surf = (TGeoBorderSurface*)surface;
1663 G4LogicalBorderSurface* g4 =
info.g4BorderSurfaces[surf];
1665 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1666 G4VPhysicalVolume* n1 =
info.g4Placements[surf->GetNode1()];
1667 G4VPhysicalVolume* n2 =
info.g4Placements[surf->GetNode2()];
1668 std::string name = make_NCName(surf->GetName());
1669 g4 =
new G4LogicalBorderSurface(name, n1, n2, optSurf);
1671 "++ Created BorderSurface: %-18s optical:%s",
1672 surf->GetName(), surf->GetSurface()->GetName());
1673 info.g4BorderSurfaces[surf] = g4;
1681 std::set<const TGeoVolume*>& volset =
info.sensitives[sens_det];
1683 std::stringstream str;
1685 printout(INFO,
"Geant4Converter",
"++ SensitiveDetector: %-18s %-20s Hits:%-16s", sd.
name(), (
"[" + sd.
type() +
"]").c_str(),
1687 str <<
" | " <<
"Cutoff:" << std::setw(6) << std::left
1688 << sd.
energyCutoff() << std::setw(5) << std::right << volset.size()
1691 str <<
" Region:" << std::setw(12) << std::left << sd.
region().
name();
1693 str <<
" Limits:" << std::setw(12) << std::left << sd.
limits().
name();
1695 printout(INFO,
"Geant4Converter", str.str().c_str());
1697 for (
const auto i : volset ) {
1698 std::map<Volume, G4LogicalVolume*>::iterator
v =
info.g4Volumes.find(i);
1699 if (
v !=
info.g4Volumes.end() ) {
1700 G4LogicalVolume* vol = (*v).second;
1702 str <<
" | " <<
"Volume:" << std::setw(24) << std::left << vol->GetName() <<
" "
1703 << vol->GetNoDaughters() <<
" daughters.";
1704 printout(INFO,
"Geant4Converter", str.str().c_str());
1710 std::stringstream str;
1711 if (
typeid(*sol) ==
typeid(G4Box)) {
1712 const G4Box* b = (G4Box*) sol;
1713 str <<
"++ Box: x=" << b->GetXHalfLength() <<
" y=" << b->GetYHalfLength() <<
" z=" << b->GetZHalfLength();
1715 else if (
typeid(*sol) ==
typeid(G4Tubs)) {
1716 const G4Tubs* t = (
const G4Tubs*) sol;
1717 str <<
" Tubs: Ri=" << t->GetInnerRadius() <<
" Ra=" << t->GetOuterRadius() <<
" z/2=" << t->GetZHalfLength() <<
" Phi="
1718 << t->GetStartPhiAngle() <<
"..." << t->GetDeltaPhiAngle();
1726 G4VPhysicalVolume* g4 =
info.g4Placements[node];
1727 G4LogicalVolume* vol =
info.g4Volumes[node->GetVolume()];
1728 G4LogicalVolume* mot =
info.g4Volumes[node->GetMotherVolume()];
1729 G4VSolid* sol = vol->GetSolid();
1730 G4ThreeVector tr = g4->GetObjectTranslation();
1735 std::stringstream str;
1736 str <<
"G4Cnv::placement: + " << name <<
" No:" << node->GetNumber() <<
" Vol:" << vol->GetName() <<
" Solid:"
1738 printout(
outputLevel,
"G4Placement", str.str().c_str());
1740 str <<
" |" <<
" Loc: x=" << tr.x() <<
" y=" << tr.y() <<
" z=" << tr.z();
1741 printout(
outputLevel,
"G4Placement", str.str().c_str());
1744 str <<
" |" <<
" Ndau:" << vol->GetNoDaughters()
1745 <<
" physvols." <<
" Mat:" << vol->GetMaterial()->GetName()
1746 <<
" Mother:" << (
char*) (mot ? mot->GetName().c_str() :
"---");
1747 printout(
outputLevel,
"G4Placement", str.str().c_str());
1749 str <<
" |" <<
" SD:" << sd->GetName();
1750 printout(
outputLevel,
"G4Placement", str.str().c_str());
1756 typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU;
1776 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld solids.", geo.
solids.size());
1778 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld visualization attributes.", geo.
vis.size());
1780 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld limit sets.", geo.
limits.size());
1782 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld regions.", geo.
regions.size());
1784 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld volumes.", geo.
volumes.size());
1788 std::map<int, std::vector<const TGeoNode*> >::const_reverse_iterator i =
m_data->rbegin();
1789 for ( ; i !=
m_data->rend(); ++i ) {
1790 for (
const TGeoNode* node : i->second ) {
1810 printout(INFO,
"Geant4Converter",
1811 "+++ Successfully converted geometry to Geant4. [%7.3f seconds]",
1812 stop.AsDouble()-start.AsDouble() );