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 tab->AddProperty(named->GetName(), vec, custom_property);
486 printout(lvl, name,
"++ %sProperty: %-20s [%ld x %ld] -> %s ",
487 custom_property ?
"CUSTOM " :
"", named->GetName(),
488 matrix->GetRows(), matrix->GetCols(), named->GetTitle());
489 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
490 printout(lvl, name,
" Geant4: %s %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
491 named->GetName(), bins[i],
v->bins[i], conv.first);
495 TListIter cpropIt(&material->GetConstProperties());
496 for(
TObject* obj=cpropIt.Next(); obj; obj = cpropIt.Next()) {
500 bool custom_property =
false;
502 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
503 if(
nullptr != cptr ) {
504 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
505 named->GetName(), named->GetTitle());
508 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
509 if(
nullptr != cptr ) {
510 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
511 named->GetName(), named->GetTitle());
514 cptr = ::strstr(named->GetName(), GEANT4_TAG_PLUGIN);
515 if(
nullptr != cptr ) {
516 printout(INFO, name,
"++ Ignore CONST property %s [%s] --> Plugin.",
517 named->GetName(), named->GetTitle());
518 plugin_name = named->GetTitle();
521 cptr = ::strstr(named->GetName(), GEANT4_TAG_BIRKSCONSTANT);
522 if(
nullptr != cptr ) {
524 value = material->GetConstProperty(GEANT4_TAG_BIRKSCONSTANT,&err);
525 if ( err == kFALSE ) ionisation_birks_constant = value * (CLHEP::mm/CLHEP::MeV)/(units::mm/units::MeV);
528 cptr = ::strstr(named->GetName(), GEANT4_TAG_MEE);
529 if(
nullptr != cptr ) {
531 value = material->GetConstProperty(GEANT4_TAG_MEE, &err);
532 if ( err == kFALSE ) ionisation_mee = value * (CLHEP::MeV/units::MeV);
535 cptr = ::strstr(named->GetName(), GEANT4_TAG_ENE_PER_ION_PAIR);
536 if(
nullptr != cptr ) {
538 value = material->GetConstProperty(GEANT4_TAG_ENE_PER_ION_PAIR,&err);
539 if ( err == kFALSE ) ionisation_ene_per_ion_pair = value * (CLHEP::MeV/units::MeV);
542 cptr = ::strstr(named->GetName(), GEANT4_TAG_CUSTOM);
543 if (
nullptr != cptr ) {
544 custom_property =
true;
546 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_CUSTOM);
547 if (
nullptr != cptr ) {
548 custom_property =
true;
552 value =
info.manager->GetProperty(named->GetTitle(), &err);
553 if ( err != kFALSE ) {
555 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
556 material->GetName(), named->GetName());
558 if (
nullptr == tab ) {
559 tab =
new G4MaterialPropertiesTable();
560 mat->SetMaterialPropertiesTable(tab);
564 if( !custom_property ) {
565 const auto& pn = tab->GetMaterialConstPropertyNames();
566 if( std::find(std::begin(pn), std::end(pn), named->GetName()) != pn.end() ) {
567 idx = tab->GetConstPropertyIndex(named->GetName());
578 if ( idx < 0 && !custom_property ) {
579 printout(ERROR, name,
580 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
581 exc_str.c_str(), named->GetName());
585 if ( !custom_property ) {
586 double conv = g4ConstPropertyConversion(idx);
587 value = value * conv;
589 printout(lvl, name,
"++ %sCONST Property: %-20s %g ",
590 custom_property ?
"CUSTOM " :
"", named->GetName(), value);
591 tab->AddConstProperty(named->GetName(), value);
595 auto* ionisation = mat->GetIonisation();
596 std::stringstream str;
599 if ( ionisation_birks_constant > 0e0 ) {
600 ionisation->SetBirksConstant(ionisation_birks_constant);
602 if ( ionisation_mee > -1e100 ) {
603 ionisation->SetMeanExcitationEnergy(ionisation_mee);
605 if ( ionisation_ene_per_ion_pair > 0e0 ) {
606 ionisation->SetMeanEnergyPerIonPair(ionisation_ene_per_ion_pair);
608 str <<
" log(MEE): " << std::setprecision(4) << ionisation->GetLogMeanExcEnergy();
609 if ( ionisation_birks_constant > 0e0 )
610 str <<
" Birk's constant: " << std::setprecision(4) << ionisation->GetBirksConstant() <<
" [mm/MeV]";
611 if ( ionisation_ene_per_ion_pair > 0e0 )
612 str <<
" Mean Energy Per Ion Pair: " << std::setprecision(4) << ionisation->GetMeanEnergyPerIonPair()/CLHEP::eV <<
" [eV]";
615 str <<
" No ionisation parameters available.";
617 printout(lvl, name,
"++ Created G4 material %s", str.str().c_str());
619 if ( !plugin_name.empty() ) {
622 G4Material* extended_mat = PluginService::Create<G4Material*>(plugin_name,
det, medium, mat);
623 if ( !extended_mat ) {
624 except(
"G4Cnv::material["+name+
"]",
"++ FATAL Failed to call plugin to create material.");
628 info.g4Materials[medium] = mat;
635 G4VSolid* solid =
nullptr;
637 if (
nullptr != (solid =
data().g4Solids[shape]) ) {
640 TClass* isa = shape->IsA();
642 if (isa == TGeoShapeAssembly::Class()) {
648 else if (isa == TGeoBBox::Class())
650 else if (isa == TGeoTube::Class())
652 else if (isa == TGeoTubeSeg::Class())
654 else if (isa == TGeoCtub::Class())
656 else if (isa == TGeoEltu::Class())
658 else if (isa == TwistedTubeObject::Class())
660 else if (isa == TGeoTrd1::Class())
662 else if (isa == TGeoTrd2::Class())
664 else if (isa == TGeoHype::Class())
666 else if (isa == TGeoXtru::Class())
668 else if (isa == TGeoPgon::Class())
670 else if (isa == TGeoPcon::Class())
672 else if (isa == TGeoCone::Class())
674 else if (isa == TGeoConeSeg::Class())
676 else if (isa == TGeoParaboloid::Class())
678 else if (isa == TGeoSphere::Class())
680 else if (isa == TGeoTorus::Class())
682 else if (isa == TGeoTrap::Class())
684 else if (isa == TGeoArb8::Class())
686 else if (isa == TGeoPara::Class())
688 else if (isa == TGeoTessellated::Class())
690 else if (isa == TGeoScaledShape::Class()) {
691 TGeoScaledShape* sh = (TGeoScaledShape*) shape;
692 TGeoShape* sol = sh->GetShape();
693 if ( sol->IsA() == TGeoShapeAssembly::Class() ) {
696 const double* vals = sh->GetScale()->GetScale();
697 G4Scale3D scal(vals[0], vals[1], vals[2]);
698 G4VSolid* g4solid = (G4VSolid*)
handleSolid(sol->GetName(), sol);
699 if ( scal.xx()>0e0 && scal.yy()>0e0 && scal.zz()>0e0 )
700 solid =
new G4ScaledSolid(sh->GetName(), g4solid, scal);
702 solid =
new G4ReflectedSolid(g4solid->GetName()+
"_refl", g4solid, scal);
704 else if ( isa == TGeoCompositeShape::Class() ) {
705 const TGeoCompositeShape* sh = (
const TGeoCompositeShape*) shape;
706 const TGeoBoolNode*
boolean = sh->GetBoolNode();
707 TGeoBoolNode::EGeoBoolType oper =
boolean->GetBooleanOperator();
708 TGeoMatrix* matrix =
boolean->GetRightMatrix();
709 G4VSolid* left = (G4VSolid*)
handleSolid(name +
"_left", boolean->GetLeftShape());
710 G4VSolid* right = (G4VSolid*)
handleSolid(name +
"_right", boolean->GetRightShape());
713 except(
"Geant4Converter",
"++ No left Geant4 Solid present for composite shape: %s",name.c_str());
716 except(
"Geant4Converter",
"++ No right Geant4 Solid present for composite shape: %s",name.c_str());
719 TGeoShape* ls =
boolean->GetLeftShape();
720 TGeoShape* rs =
boolean->GetRightShape();
721 if (strcmp(ls->ClassName(),
"TGeoScaledShape") == 0 &&
722 strcmp(rs->ClassName(),
"TGeoBBox") == 0) {
723 if (strcmp(((TGeoScaledShape *)ls)->GetShape()->ClassName(),
"TGeoSphere") == 0) {
724 if (oper == TGeoBoolNode::kGeoIntersection) {
725 TGeoScaledShape* lls = (TGeoScaledShape *)ls;
726 TGeoBBox* rrs = (TGeoBBox*)rs;
727 double sx = lls->GetScale()->GetScale()[0];
728 double sy = lls->GetScale()->GetScale()[1];
729 double radius = ((TGeoSphere *)lls->GetShape())->GetRmax();
730 double dz = rrs->GetDZ();
731 double zorig = rrs->GetOrigin()[2];
732 double zcut2 = dz + zorig;
733 double zcut1 = 2 * zorig - zcut2;
734 solid =
new G4Ellipsoid(name,
746 if ( matrix->IsRotation() ) {
747 G4Transform3D transform;
749 if (oper == TGeoBoolNode::kGeoSubtraction)
750 solid =
new G4SubtractionSolid(name, left, right, transform);
751 else if (oper == TGeoBoolNode::kGeoUnion)
752 solid =
new G4UnionSolid(name, left, right, transform);
753 else if (oper == TGeoBoolNode::kGeoIntersection)
754 solid =
new G4IntersectionSolid(name, left, right, transform);
757 const Double_t *t = matrix->GetTranslation();
759 if (oper == TGeoBoolNode::kGeoSubtraction)
760 solid =
new G4SubtractionSolid(name, left, right, 0, transform);
761 else if (oper == TGeoBoolNode::kGeoUnion)
762 solid =
new G4UnionSolid(name, left, right, 0, transform);
763 else if (oper == TGeoBoolNode::kGeoIntersection)
764 solid =
new G4IntersectionSolid(name, left, right, 0, transform);
769 except(
"Geant4Converter",
"++ Failed to handle unknown solid shape: %s of type %s",
770 name.c_str(), isa->GetName());
771 printout(lvl,
"Geant4Converter",
"++ Successessfully converted shape [%p] of type:%s to %s.",
772 solid,isa->GetName(),typeName(
typeid(*solid)).c_str());
783 Geant4GeometryMaps::VolumeMap::const_iterator volIt =
info.g4Volumes.find(volume);
785 printout(lvl,
"Geant4Converter",
786 "++ Volume %s not converted [Veto'ed for simulation]",
790 else if (volIt ==
info.g4Volumes.end() ) {
791 const char* vnam = volume->GetName();
792 TGeoMedium* med = volume->GetMedium();
793 Solid sh = volume->GetShape();
794 bool is_assembly = sh->IsA() == TGeoShapeAssembly::Class() || volume->IsAssembly();
796 printout(lvl,
"Geant4Converter",
"++ Convert Volume %-32s: %p %s/%s assembly:%s",
797 vnam, volume, sh.
type(), _v.
type(), yes_no(is_assembly));
804 G4Region* g4region = reg.
isValid() ?
info.g4Regions[reg] :
nullptr;
806 G4VSolid* g4solid = (G4VSolid*)
handleSolid(sh->GetName(), sh);
810 except(
"G4Converter",
"++ No Geant4 Solid present for volume: %s", vnam);
812 else if ( !g4medium ) {
813 except(
"G4Converter",
"++ No Geant4 material present for volume: %s", vnam);
815 else if ( reg.
isValid() && !g4region ) {
816 except(
"G4Cnv::volume["+name+
"]",
" ++ Failed to access Geant4 region %s.", reg.
name());
818 else if ( lim.
isValid() && !g4limits ) {
819 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to access Geant4 user limits %s.", lim.
name());
821 else if ( g4limits ) {
822 printout(lvl,
"Geant4Converter",
"++ Volume + Apply LIMITS settings: %-24s to volume %s.",
826 G4LogicalVolume* g4vol =
nullptr;
829 std::string plugin = _v.
getProperty(GEANT4_TAG_PLUGIN,
"");
830 g4vol = PluginService::Create<G4LogicalVolume*>(plugin,
det, _v, g4solid, g4medium);
832 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to call plugin to create logical volume.");
836 g4vol =
new G4LogicalVolume(g4solid, g4medium, vnam,
nullptr,
nullptr,
nullptr);
842 printout(ALWAYS,
"Geant4Converter",
843 "++ Volume %s Set Smartless value to %d",
844 vnam,
int(smart_less_value));
845 g4vol->SetSmartless( smart_less_value );
849 g4vol->SetUserLimits(g4limits);
852 printout(plevel,
"Geant4Converter",
853 "++ Volume + Apply REGION settings: %-24s to volume %s.",
859 const char* wrd_nam =
"DefaultRegionForTheWorld";
860 const char* src_nam = g4region->GetName().c_str();
861 auto* world_region = G4RegionStore::GetInstance()->GetRegion(wrd_nam,
false);
862 if (
auto* cuts = g4region->GetProductionCuts() ) {
863 world_region->SetProductionCuts(cuts);
864 printout(plevel,
"Geant4Converter",
865 "++ Volume %s Region: %s. Apply production cuts from %s",
866 vnam, wrd_nam, src_nam);
868 if (
auto* lims = g4region->GetUserLimits() ) {
869 world_region->SetUserLimits(lims);
870 printout(plevel,
"Geant4Converter",
871 "++ Volume %s Region: %s. Apply user limits from %s",
872 vnam, wrd_nam, src_nam);
876 g4vol->SetRegion(g4region);
877 g4region->AddRootLogicalVolume(g4vol);
880 G4VisAttributes* g4vattr = vis.
isValid()
883 g4vol->SetVisAttributes(g4vattr);
885 info.g4Volumes[volume] = g4vol;
886 printout(lvl,
"Geant4Converter",
887 "++ Volume + %s converted: %p ---> G4: %p", vnam, volume, g4vol);
903 info.limits[lim].insert(volume);
905 info.regions[reg].insert(volume);
907 info.sensitives[
det].insert(volume);
909 return (
void*)volume;
914 TGeoVolume* mot_vol = node->GetVolume();
916 if ( mot_vol->IsA() != TGeoVolumeAssembly::Class() ) {
921 printout(lvl,
"Geant4Converter",
"++ AssemblyNode %s not converted [Veto'ed for simulation]",node->GetName());
927 printout(ALWAYS,
"Geant4Converter",
"+++ Assembly: **** : Re-using existing assembly: %s",node->GetName());
931 for(Int_t i=0; i < mot_vol->GetNdaughters(); ++i) {
932 TGeoNode* dau = mot_vol->GetNode(i);
933 TGeoVolume* dau_vol = dau->GetVolume();
934 TGeoMatrix* tr = dau->GetMatrix();
935 G4Transform3D transform;
938 if ( is_left_handed(tr) ) {
942 transform.getDecomposition(scale, rot, trans);
944 "++ Placing reflected ASSEMBLY. dau:%s to mother %s "
945 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
946 dau_vol->GetName(), mot_vol->GetName(),
947 transform.dx(), transform.dy(), transform.dz(),
948 scale.xx(), scale.yy(), scale.zz());
951 if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) {
952 Geant4GeometryMaps::AssemblyMap::iterator ia =
info.g4AssemblyVolumes.find(dau);
953 if ( ia ==
info.g4AssemblyVolumes.end() ) {
954 printout(FATAL,
"Geant4Converter",
"+++ Invalid child assembly at %s : %d parent: %s child:%s",
955 __FILE__, __LINE__, name.c_str(), dau->GetName());
960 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedAssembly %p: dau:%s "
961 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
962 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
963 transform.dx(), transform.dy(), transform.dz());
966 Geant4GeometryMaps::VolumeMap::iterator iv =
info.g4Volumes.find(dau_vol);
967 if ( iv ==
info.g4Volumes.end() ) {
968 printout(FATAL,
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
969 __FILE__, __LINE__, name.c_str(), dau->GetName());
970 except(
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
971 __FILE__, __LINE__, name.c_str(), dau->GetName());
974 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedVolume %p: dau:%s "
975 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
976 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
977 transform.dx(), transform.dy(), transform.dz());
980 info.g4AssemblyVolumes[node] = g4;
989 Geant4GeometryMaps::PlacementMap::const_iterator g4it =
info.g4Placements.find(node);
990 G4VPhysicalVolume* g4 = (g4it ==
info.g4Placements.end()) ? 0 : (*g4it).second;
991 TGeoVolume* vol = node->GetVolume();
995 printout(lvl,
"Geant4Converter",
"++ Placement %s not converted [Veto'ed for simulation]",node->GetName());
1000 TGeoVolume* mot_vol = node->GetMotherVolume();
1001 TGeoMatrix* tr = node->GetMatrix();
1003 except(
"Geant4Converter",
1004 "++ Attempt to handle placement without transformation:%p %s of type %s vol:%p",
1005 node, node->GetName(), node->IsA()->GetName(), vol);
1007 else if (
nullptr == vol) {
1008 except(
"Geant4Converter",
"++ Unknown G4 volume:%p %s of type %s ptr:%p",
1009 node, node->GetName(), node->IsA()->GetName(), vol);
1012 int copy = node->GetNumber();
1013 bool node_is_reflected = is_left_handed(tr);
1014 bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class();
1015 bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() :
false;
1017 if ( mother_is_assembly ) {
1024 printout(lvl,
"Geant4Converter",
"+++ Assembly: **** : daughter %s to mother %s",
1025 vol->GetName(), mot_vol ? mot_vol->GetName() :
"????");
1029 G4LogicalVolume* g4mot =
nullptr;
1030 auto volIt =
info.g4Volumes.find(mot_vol);
1031 if ( volIt !=
info.g4Volumes.end() ) {
1037 g4mot = (*volIt).second;
1039 else if ( node !=
info.manager->GetTopNode() ) {
1045 TGeoIterator iter(
info.manager->GetTopVolume());
1047 printout(ALWAYS,
"Geant4Converter",
"+++ (SHOULD NOT ENTER HERE) Assembly: no G4 mother: %s org mot: %p",
1048 node->GetName(), mot_vol);
1049 while ( (n1=iter.Next()) ) {
1051 TGeoNode* nmot = iter.GetNode(iter.GetLevel()-1);
1052 TGeoVolume* mmot = nmot->GetVolume();
1053 volIt =
info.g4Volumes.find(mmot);
1054 if ( volIt !=
info.g4Volumes.end() ) {
1057 g4mot = (*volIt).second;
1058 printout(ALWAYS,
"Geant4Converter",
"+++ Assembly: Realigned mother: %s org mot: %p aligned: %p",
1059 path.Data(), mot_vol, mmot);
1068 G4Translate3D trans;
1069 G4Transform3D transform;
1071 transform.getDecomposition(scale, rotate, trans);
1072 if ( node_is_assembly ) {
1077 printout(lvl,
"Geant4Converter",
"++ Assembly: makeImprint: dau:%-12s %s in mother %-12s "
1078 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1079 node->GetName(), node_is_reflected ?
"(REFLECTED)" :
"",
1080 mot_vol ? mot_vol->GetName() :
"<unknown>",
1081 transform.dx(), transform.dy(), transform.dz(),
1082 scale.xx(), scale.yy(), scale.zz());
1085 chain.emplace_back(node);
1087 except(
"Geant4Converter",
1088 "+++ Assembly: %s mother: %s Geant4AssemblyVolume not present!",
1089 node->GetName(), mot_vol ? mot_vol->GetName() :
"<unknown>");
1094 else if ( node !=
info.manager->GetTopNode() &&
nullptr == g4mot ) {
1098 const auto* pv_data = pv.
data();
1099 G4LogicalVolume* g4vol =
info.g4Volumes[vol];
1101 G4PhysicalVolumesPair pvPlaced {
nullptr,
nullptr };
1104 EAxis axis = kUndefined;
1105 double width = 0e0, offset = 0e0;
1106 auto flags = pv_data->params->flags;
1107 auto count = pv_data->params->trafo1D.second;
1108 auto start = pv_data->params->start.Translation().Vect();
1109 auto delta = pv_data->params->trafo1D.first.Translation().Vect();
1112 { axis = kXAxis; width =
delta.X(); offset = start.X(); }
1114 { axis = kYAxis; width =
delta.Y(); offset = start.Y(); }
1116 { axis = kZAxis; width =
delta.Z(); offset = start.Z(); }
1118 except(
"Geant4Converter",
1119 "++ Replication around unknown axis is not implemented. flags: %16X", flags);
1120 printout(INFO,
"Geant4Converter",
"++ Replicate: Axis: %ld Count: %ld offset: %f width: %f",
1121 axis, count, offset, width);
1122 auto* g4pv =
new G4PVReplica(name,
1129 pvPlaced = { g4pv,
nullptr };
1132 G4ReflectionFactory::Instance()->Replicate(name,
1140 auto* g4pv = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1142 for(
auto& handle : pv_data->params->placements )
1143 info.g4Placements[handle.ptr()] = g4pv;
1145 else if ( pv_data && pv_data->params ) {
1147 auto* g4pv =
new G4PVParameterised(name,
1153 pvPlaced = { g4pv,
nullptr };
1155 for(
auto& handle : pv_data->params->placements )
1156 info.g4Placements[handle.ptr()] = g4pv;
1160 G4ReflectionFactory::Instance()->Place(transform,
1169 "++ Place %svolume %-12s in mother %-12s "
1170 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1171 node_is_reflected ?
"REFLECTED " :
"", _v.
name(),
1172 mot_vol ? mot_vol->GetName() :
"<unknown>",
1173 transform.dx(), transform.dy(), transform.dz(),
1174 scale.xx(), scale.yy(), scale.zz());
1177 if ( node_is_reflected && !pvPlaced.second )
1178 return info.g4Placements[node] = pvPlaced.first;
1179 else if ( !node_is_reflected && !pvPlaced.second )
1180 return info.g4Placements[node] = pvPlaced.first;
1182 if ( node_is_reflected )
1183 return info.g4Placements[node] = pvPlaced.first;
1184 else if ( !node_is_reflected )
1185 return info.g4Placements[node] = pvPlaced.first;
1186 g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1188 info.g4Placements[node] = g4;
1189 printout(ERROR,
"Geant4Converter",
"++ DEAD code. Should not end up here!");
1200 g4 =
new G4Region(region.
name());
1204 throw std::runtime_error(
"G4Region: StoreSecondaries is True, but no explicit threshold set:");
1206 printout(lvl,
"Geant4Converter",
"++ Setting up region: %s", r.
name());
1207 G4UserRegionInformation*
info =
new G4UserRegionInformation();
1211 g4->SetUserInformation(
info);
1213 printout(lvl,
"Geant4Converter",
"++ Converted region settings of:%s.", r.
name());
1214 std::vector < std::string > &limits = r.
limits();
1215 G4ProductionCuts* cuts = 0;
1218 cuts =
new G4ProductionCuts();
1219 cuts->SetProductionCut(r.
cut()*CLHEP::mm/units::mm);
1220 printout(lvl,
"Geant4Converter",
"++ %s: Using default cut: %f [mm]",
1221 r.
name(), r.
cut()*CLHEP::mm/units::mm);
1223 for(
const auto& nam : limits ) {
1227 for (
const auto& c : cts ) {
1229 if ( c.particles ==
"*" ) pid = -1;
1230 else if ( c.particles ==
"e-" ) pid = idxG4ElectronCut;
1231 else if ( c.particles ==
"e+" ) pid = idxG4PositronCut;
1232 else if ( c.particles ==
"e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1233 else if ( c.particles ==
"e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1234 else if ( c.particles ==
"gamma" ) pid = idxG4GammaCut;
1235 else if ( c.particles ==
"proton" ) pid = idxG4ProtonCut;
1236 else throw std::runtime_error(
"G4Region: Invalid production cut particle-type:" + c.particles);
1237 if ( !cuts ) cuts =
new G4ProductionCuts();
1238 if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1239 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4PositronCut);
1240 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4ElectronCut);
1243 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, pid);
1245 printout(lvl,
"Geant4Converter",
"++ %s: Set cut [%s/%d] = %f [mm]",
1246 r.
name(), c.particles.c_str(), pid, c.value*CLHEP::mm/units::mm);
1250 for (
const auto& j : lm ) {
1251 if (nam == j.first->GetName()) {
1252 g4->SetUserLimits(j.second);
1253 printout(lvl,
"Geant4Converter",
"++ %s: Set limits %s to region type %s",
1254 r.
name(), nam.c_str(), j.second->GetType().c_str());
1263 except(
"Geant4Converter",
"++ G4Region: Failed to resolve limitset: " + nam);
1266 if ( cuts ) g4->SetProductionCuts(cuts);
1279 LimitPrint(
const LimitSet& lset) : ls(lset) {}
1282 printout(ALWAYS,
"Geant4Converter",
1283 "+++ LimitSet: Explicit Limit %s.%s applied for particles:",ls.
name(), pref.c_str());
1285 printout(ALWAYS,
"Geant4Converter",
"+++ LimitSet: Particle type: %-18s PDG: %-6d : %f",
1286 p.first->GetParticleName().c_str(), p.first->GetPDGEncoding(), p.second);
1289 printout(ALWAYS,
"Geant4Converter",
1290 "+++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f",
1298 printout(lvl,
"Geant4Converter",
1299 "++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]",
1300 limitset.
name(), limitset.
cuts().size(), limitset.
limits().size());
1302 LimitPrint print(limitset);
1303 print(
"maxTime", limits->
maxTime)
1317 G4VisAttributes* g4 =
info.g4Vis[attr];
1319 float red = 0, green = 0, blue = 0;
1321 attr.
rgb(red, green, blue);
1322 g4 =
new G4VisAttributes(attr.
visible(), G4Colour(red, green, blue, attr.
alpha()));
1326 g4->SetLineStyle(G4VisAttributes::unbroken);
1327 g4->SetForceWireframe(
false);
1328 g4->SetForceSolid(
true);
1331 g4->SetLineStyle(G4VisAttributes::dashed);
1332 g4->SetForceSolid(
false);
1333 g4->SetForceWireframe(
true);
1335 info.g4Vis[attr] = g4;
1342 std::map < std::string, std::string > processors;
1343 static int s_idd = 9999999;
1344 for(
const auto& [nam, vals] : prp ) {
1345 if ( nam.substr(0, 6) ==
"geant4" ) {
1346 auto id_it = vals.find(
"id");
1347 std::string
id = (id_it == vals.end()) ?
_toString(++s_idd,
"%d") : (*id_it).second;
1348 processors.emplace(
id, nam);
1351 for(
const auto& p : processors ) {
1354 auto iter = vals.find(
"type");
1355 if ( iter != vals.end() ) {
1356 std::string type = iter->second;
1357 std::string tag = type +
"_Geant4_action";
1359 long res = PluginService::Create<long>(tag,
det, hdlr, &vals);
1361 throw std::runtime_error(
"Failed to locate plugin to interprete files of type"
1362 " \"" + tag +
"\" - no factory:" + type);
1366 throw std::runtime_error(
"Failed to invoke the plugin " + tag +
" of type " + type);
1368 printout(
outputLevel,
"Geant4Converter",
"+++++ Executed Successfully Geant4 setup module *%s*.", type.c_str());
1371 printout(
outputLevel,
"Geant4Converter",
"+++++ FAILED to execute Geant4 setup module *%s*.", p.second.c_str());
1378 TGDMLMatrix* matrix = (TGDMLMatrix*)mtx;
1379 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1382 if (
nullptr != cptr ) {
1383 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1384 matrix->GetName(), matrix->GetTitle());
1387 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
1388 if (
nullptr != cptr ) {
1389 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1390 matrix->GetName(), matrix->GetTitle());
1397 std::size_t rows = matrix->GetRows();
1398 g4->
name = matrix->GetName();
1399 g4->
title = matrix->GetTitle();
1400 g4->
bins.reserve(rows);
1401 g4->
values.reserve(rows);
1402 for( std::size_t i=0; i<rows; ++i ) {
1403 g4->
bins.emplace_back(matrix->Get(i,0) );
1404 g4->
values.emplace_back(matrix->Get(i,1));
1406 printout(lvl,
"Geant4Converter",
1407 "++ Successfully converted material property:%s : %s [%ld rows]",
1408 matrix->GetName(), matrix->GetTitle(), rows);
1409 info.g4OpticalProperties[matrix] = g4;
1414 static G4OpticalSurfaceFinish geant4_surface_finish(TGeoOpticalSurface::ESurfaceFinish f) {
1415 #define TO_G4_FINISH(x) case TGeoOpticalSurface::kF##x : return x;
1463 printout(ERROR,
"Geant4Surfaces",
"++ Unknown finish style: %d [%s]. Assume polished!",
1464 int(f), TGeoOpticalSurface::FinishToString(f));
1470 static G4SurfaceType geant4_surface_type(TGeoOpticalSurface::ESurfaceType t) {
1471 #define TO_G4_TYPE(x) case TGeoOpticalSurface::kT##x : return x;
1481 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface type: %d [%s]. Assume dielectric_metal!",
1482 int(t), TGeoOpticalSurface::TypeToString(t));
1483 return dielectric_metal;
1488 static G4OpticalSurfaceModel geant4_surface_model(TGeoOpticalSurface::ESurfaceModel surfMod) {
1489 #define TO_G4_MODEL(x) case TGeoOpticalSurface::kM##x : return x;
1497 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface model: %d [%s]. Assume glisur!",
1498 int(surfMod), TGeoOpticalSurface::ModelToString(surfMod));
1506 TGeoOpticalSurface* optSurf = (TGeoOpticalSurface*)surface;
1508 G4OpticalSurface* g4 =
info.g4OpticalSurfaces[optSurf];
1510 G4SurfaceType type = geant4_surface_type(optSurf->GetType());
1511 G4OpticalSurfaceModel model = geant4_surface_model(optSurf->GetModel());
1512 G4OpticalSurfaceFinish finish = geant4_surface_finish(optSurf->GetFinish());
1513 std::string name = make_NCName(optSurf->GetName());
1515 g4 =
new G4OpticalSurface(name, model, finish, type, optSurf->GetValue());
1516 g4->SetSigmaAlpha(optSurf->GetSigmaAlpha());
1517 g4->SetPolish(optSurf->GetPolish());
1519 printout(lvl,
"Geant4Converter",
1520 "++ Created OpticalSurface: %-18s type:%s model:%s finish:%s SigmaAlphs: %.3e Polish: %.3e",
1522 TGeoOpticalSurface::TypeToString(optSurf->GetType()),
1523 TGeoOpticalSurface::ModelToString(optSurf->GetModel()),
1524 TGeoOpticalSurface::FinishToString(optSurf->GetFinish()),
1525 optSurf->GetSigmaAlpha(), optSurf->GetPolish());
1528 G4MaterialPropertiesTable* tab =
nullptr;
1529 TListIter itp(&optSurf->GetProperties());
1530 for(
TObject* obj = itp.Next(); obj; obj = itp.Next()) {
1531 std::string exc_str;
1533 TGDMLMatrix* matrix =
info.manager->GetGDMLMatrix(named->GetTitle());
1534 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1535 if (
nullptr != cptr )
1538 if (
nullptr == tab ) {
1539 tab =
new G4MaterialPropertiesTable();
1540 g4->SetMaterialPropertiesTable(tab);
1546 except(
"Geant4OpticalSurface",
"++ Failed to convert opt.surface %s. Property table %s is not defined!",
1547 optSurf->GetName(), named->GetTitle());
1551 idx = tab->GetPropertyIndex(named->GetName());
1559 printout(ERROR,
"Geant4Converter",
1560 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
1561 exc_str.c_str(), named->GetName());
1565 auto conv = g4PropertyConversion(idx);
1566 std::vector<double> bins(
v->bins), vals(
v->values);
1567 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1568 bins[i] *= conv.first, vals[i] *= conv.second;
1569 G4MaterialPropertyVector* vec =
new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
1570 tab->AddProperty(named->GetName(), vec);
1572 printout(lvl,
"Geant4Converter",
1573 "++ Property: %-20s [%ld x %ld] --> %s",
1574 named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
1575 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1576 printout(lvl, named->GetName(),
1577 " Geant4: %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
1578 bins[i],
v->bins[i], conv.first);
1582 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
1583 TListIter itc(&optSurf->GetConstProperties());
1584 for(
TObject* obj = itc.Next(); obj; obj = itc.Next()) {
1585 std::string exc_str;
1587 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
1588 if (
nullptr != cptr ) {
1589 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1590 named->GetName(), named->GetTitle());
1593 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
1594 if (
nullptr != cptr ) {
1595 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1596 named->GetName(), named->GetTitle());
1599 Bool_t err = kFALSE;
1600 Double_t value =
info.manager->GetProperty(named->GetTitle(),&err);
1601 if ( err != kFALSE ) {
1603 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
1604 optSurf->GetName(), named->GetName());
1606 if (
nullptr == tab ) {
1607 tab =
new G4MaterialPropertiesTable();
1608 g4->SetMaterialPropertiesTable(tab);
1612 idx = tab->GetConstPropertyIndex(named->GetName());
1620 printout(ERROR, name,
1621 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
1622 exc_str.c_str(), named->GetName());
1626 double conv = g4ConstPropertyConversion(idx);
1627 printout(lvl, name,
"++ CONST Property: %-20s %g * %g --> %g ",
1628 named->GetName(), value, conv, value * conv);
1629 tab->AddConstProperty(named->GetName(), value * conv);
1631 #endif // ROOT_VERSION >= 6.31.1
1632 info.g4OpticalSurfaces[optSurf] = g4;
1639 TGeoSkinSurface* surf = (TGeoSkinSurface*)surface;
1641 G4LogicalSkinSurface* g4 =
info.g4SkinSurfaces[surf];
1643 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1644 G4LogicalVolume*
v =
info.g4Volumes[surf->GetVolume()];
1645 std::string name = make_NCName(surf->GetName());
1646 g4 =
new G4LogicalSkinSurface(name,
v, optSurf);
1648 "++ Created SkinSurface: %-18s optical:%s",
1649 surf->GetName(), surf->GetSurface()->GetName());
1650 info.g4SkinSurfaces[surf] = g4;
1657 TGeoBorderSurface* surf = (TGeoBorderSurface*)surface;
1659 G4LogicalBorderSurface* g4 =
info.g4BorderSurfaces[surf];
1661 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1662 G4VPhysicalVolume* n1 =
info.g4Placements[surf->GetNode1()];
1663 G4VPhysicalVolume* n2 =
info.g4Placements[surf->GetNode2()];
1664 std::string name = make_NCName(surf->GetName());
1665 g4 =
new G4LogicalBorderSurface(name, n1, n2, optSurf);
1667 "++ Created BorderSurface: %-18s optical:%s",
1668 surf->GetName(), surf->GetSurface()->GetName());
1669 info.g4BorderSurfaces[surf] = g4;
1677 std::set<const TGeoVolume*>& volset =
info.sensitives[sens_det];
1679 std::stringstream str;
1681 printout(INFO,
"Geant4Converter",
"++ SensitiveDetector: %-18s %-20s Hits:%-16s", sd.
name(), (
"[" + sd.
type() +
"]").c_str(),
1683 str <<
" | " <<
"Cutoff:" << std::setw(6) << std::left
1684 << sd.
energyCutoff() << std::setw(5) << std::right << volset.size()
1687 str <<
" Region:" << std::setw(12) << std::left << sd.
region().
name();
1689 str <<
" Limits:" << std::setw(12) << std::left << sd.
limits().
name();
1691 printout(INFO,
"Geant4Converter", str.str().c_str());
1693 for (
const auto i : volset ) {
1694 std::map<Volume, G4LogicalVolume*>::iterator
v =
info.g4Volumes.find(i);
1695 if (
v !=
info.g4Volumes.end() ) {
1696 G4LogicalVolume* vol = (*v).second;
1698 str <<
" | " <<
"Volume:" << std::setw(24) << std::left << vol->GetName() <<
" "
1699 << vol->GetNoDaughters() <<
" daughters.";
1700 printout(INFO,
"Geant4Converter", str.str().c_str());
1706 std::stringstream str;
1707 if (
typeid(*sol) ==
typeid(G4Box)) {
1708 const G4Box* b = (G4Box*) sol;
1709 str <<
"++ Box: x=" << b->GetXHalfLength() <<
" y=" << b->GetYHalfLength() <<
" z=" << b->GetZHalfLength();
1711 else if (
typeid(*sol) ==
typeid(G4Tubs)) {
1712 const G4Tubs* t = (
const G4Tubs*) sol;
1713 str <<
" Tubs: Ri=" << t->GetInnerRadius() <<
" Ra=" << t->GetOuterRadius() <<
" z/2=" << t->GetZHalfLength() <<
" Phi="
1714 << t->GetStartPhiAngle() <<
"..." << t->GetDeltaPhiAngle();
1722 G4VPhysicalVolume* g4 =
info.g4Placements[node];
1723 G4LogicalVolume* vol =
info.g4Volumes[node->GetVolume()];
1724 G4LogicalVolume* mot =
info.g4Volumes[node->GetMotherVolume()];
1725 G4VSolid* sol = vol->GetSolid();
1726 G4ThreeVector tr = g4->GetObjectTranslation();
1731 std::stringstream str;
1732 str <<
"G4Cnv::placement: + " << name <<
" No:" << node->GetNumber() <<
" Vol:" << vol->GetName() <<
" Solid:"
1734 printout(
outputLevel,
"G4Placement", str.str().c_str());
1736 str <<
" |" <<
" Loc: x=" << tr.x() <<
" y=" << tr.y() <<
" z=" << tr.z();
1737 printout(
outputLevel,
"G4Placement", str.str().c_str());
1740 str <<
" |" <<
" Ndau:" << vol->GetNoDaughters()
1741 <<
" physvols." <<
" Mat:" << vol->GetMaterial()->GetName()
1742 <<
" Mother:" << (
char*) (mot ? mot->GetName().c_str() :
"---");
1743 printout(
outputLevel,
"G4Placement", str.str().c_str());
1745 str <<
" |" <<
" SD:" << sd->GetName();
1746 printout(
outputLevel,
"G4Placement", str.str().c_str());
1752 typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU;
1772 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld solids.", geo.
solids.size());
1774 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld visualization attributes.", geo.
vis.size());
1776 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld limit sets.", geo.
limits.size());
1778 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld regions.", geo.
regions.size());
1780 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld volumes.", geo.
volumes.size());
1784 std::map<int, std::vector<const TGeoNode*> >::const_reverse_iterator i =
m_data->rbegin();
1785 for ( ; i !=
m_data->rend(); ++i ) {
1786 for (
const TGeoNode* node : i->second ) {
1806 printout(INFO,
"Geant4Converter",
1807 "+++ Successfully converted geometry to Geant4. [%7.3f seconds]",
1808 stop.AsDouble()-start.AsDouble() );