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_IGNORE =
"Geant4-ignore";
90 static constexpr
const char* GEANT4_TAG_PLUGIN =
"Geant4-plugin";
91 static constexpr
const char* GEANT4_TAG_BIRKSCONSTANT =
"BirksConstant";
92 static constexpr
const char* GEANT4_TAG_MEE =
"MeanExcitationEnergy";
93 static constexpr
const char* GEANT4_TAG_ENE_PER_ION_PAIR =
"MeanEnergyPerIonPair";
95 static std::string indent =
"";
97 template <
typename O,
typename C,
typename F>
void handleRefs(
const O* o,
const C& c, F pmf) {
98 for (
typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
104 template <
typename O,
typename C,
typename F>
void handle(
const O* o,
const C& c, F pmf) {
105 for (
typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
106 (o->*pmf)((*i)->GetName(), *i);
110 template <
typename O,
typename F>
void handleArray(
const O* o,
const TObjArray* c, F pmf) {
111 TObjArrayIter arr(c);
112 for(
TObject* i = arr.Next(); i; i=arr.Next())
116 template <
typename O,
typename C,
typename F>
void handleMap(
const O* o,
const C& c, F pmf) {
117 for (
typename C::const_iterator i = c.begin(); i != c.end(); ++i)
118 (o->*pmf)((*i).first, (*i).second);
121 template <
typename O,
typename C,
typename F>
void handleRMap(
const O* o,
const C& c, F pmf) {
122 for (
typename C::const_reverse_iterator i = c.rbegin(); i != c.rend(); ++i) {
124 handle(o, i->second, pmf);
127 template <
typename O,
typename C,
typename F>
void handleRMap_(
const O* o,
const C& c, F pmf) {
128 for (
typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
129 const auto& cc = (*i).second;
130 for (
const auto& j : cc) {
136 std::string make_NCName(
const std::string& in) {
137 std::string res = detail::str_replace(in,
"/",
"_");
138 res = detail::str_replace(res,
"#",
"_");
142 bool is_left_handed(
const TGeoMatrix* m) {
143 const Double_t* r = m->GetRotationMatrix();
146 r[0]*r[4]*r[8] + r[3]*r[7]*r[2] + r[6]*r[1]*r[5] -
147 r[2]*r[4]*r[6] - r[5]*r[7]*r[0] - r[8]*r[1]*r[3];
153 class G4UserRegionInformation :
public G4VUserRegionInformation {
157 bool storeSecondaries;
158 G4UserRegionInformation()
159 : threshold(0.0), storeSecondaries(false) {
161 virtual ~G4UserRegionInformation() {
163 virtual void Print()
const {
165 printout(DEBUG,
"Region",
"Name:%s", region.
name());
169 std::pair<double,double> g4PropertyConversion(
int index) {
170 #if G4VERSION_NUMBER >= 1040
172 case kRINDEX:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
173 case kREFLECTIVITY:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
174 case kREALRINDEX:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
175 case kIMAGINARYRINDEX:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
176 case kEFFICIENCY:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
177 case kTRANSMITTANCE:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
178 case kSPECULARLOBECONSTANT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
179 case kSPECULARSPIKECONSTANT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
180 case kBACKSCATTERCONSTANT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
181 case kGROUPVEL:
return std::make_pair(CLHEP::keV/units::keV, (CLHEP::m/CLHEP::s)/(units::m/units::s));
182 case kMIEHG:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
183 case kRAYLEIGH:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
184 case kWLSCOMPONENT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
185 case kWLSABSLENGTH:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
186 case kABSLENGTH:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
187 #if G4VERSION_NUMBER >= 1100
188 case kWLSCOMPONENT2:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
189 case kWLSABSLENGTH2:
return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
190 case kSCINTILLATIONCOMPONENT1:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
191 case kSCINTILLATIONCOMPONENT2:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
192 case kSCINTILLATIONCOMPONENT3:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
194 case kFASTCOMPONENT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
195 case kSLOWCOMPONENT:
return std::make_pair(CLHEP::keV/units::keV, 1.0);
197 case kPROTONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
198 case kDEUTERONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
199 case kTRITONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
200 case kALPHASCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
201 case kIONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
202 case kELECTRONSCINTILLATIONYIELD:
return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
206 printout(FATAL,
"Geant4Converter",
"+++ Cannot convert material property with index: %d", index);
208 printout(FATAL,
"Geant4Converter",
"+++ Cannot convert material property with index: %d [Need Geant4 > 10.03]", index);
210 return std::make_pair(0e0,0e0);
213 double g4ConstPropertyConversion(
int index) {
214 #if G4VERSION_NUMBER >= 1040
216 case kSURFACEROUGHNESS:
return CLHEP::m/units::m;
217 case kISOTHERMAL_COMPRESSIBILITY:
return (CLHEP::m3/CLHEP::keV)/(units::m3/CLHEP::keV);
218 case kRS_SCALE_FACTOR:
return 1.0;
219 case kWLSMEANNUMBERPHOTONS:
return 1.0;
220 case kWLSTIMECONSTANT:
return CLHEP::second/units::second;
221 case kMIEHG_FORWARD:
return 1.0;
222 case kMIEHG_BACKWARD:
return 1.0;
223 case kMIEHG_FORWARD_RATIO:
return 1.0;
224 case kSCINTILLATIONYIELD:
return units::keV/CLHEP::keV;
225 case kRESOLUTIONSCALE:
return 1.0;
226 case kFERMIPOT:
return CLHEP::keV/units::keV;
227 case kDIFFUSION:
return 1.0;
228 case kSPINFLIP:
return 1.0;
229 case kLOSS:
return 1.0;
230 case kLOSSCS:
return CLHEP::barn/units::barn;
231 case kABSCS:
return CLHEP::barn/units::barn;
232 case kSCATCS:
return CLHEP::barn/units::barn;
233 case kMR_NBTHETA:
return 1.0;
234 case kMR_NBE:
return 1.0;
235 case kMR_RRMS:
return 1.0;
236 case kMR_CORRLEN:
return CLHEP::m/units::m;
237 case kMR_THETAMIN:
return 1.0;
238 case kMR_THETAMAX:
return 1.0;
239 case kMR_EMIN:
return CLHEP::keV/units::keV;
240 case kMR_EMAX:
return CLHEP::keV/units::keV;
241 case kMR_ANGNOTHETA:
return 1.0;
242 case kMR_ANGNOPHI:
return 1.0;
243 case kMR_ANGCUT:
return 1.0;
245 #if G4VERSION_NUMBER >= 1100
246 case kSCINTILLATIONTIMECONSTANT1:
return CLHEP::second/units::second;
247 case kSCINTILLATIONTIMECONSTANT2:
return CLHEP::second/units::second;
248 case kSCINTILLATIONTIMECONSTANT3:
return CLHEP::second/units::second;
249 case kSCINTILLATIONRISETIME1:
return CLHEP::second/units::second;
250 case kSCINTILLATIONRISETIME2:
return CLHEP::second/units::second;
251 case kSCINTILLATIONRISETIME3:
return CLHEP::second/units::second;
252 case kSCINTILLATIONYIELD1:
return 1.0;
253 case kSCINTILLATIONYIELD2:
return 1.0;
254 case kSCINTILLATIONYIELD3:
return 1.0;
255 case kPROTONSCINTILLATIONYIELD1:
return 1.0;
256 case kPROTONSCINTILLATIONYIELD2:
return 1.0;
257 case kPROTONSCINTILLATIONYIELD3:
return 1.0;
258 case kDEUTERONSCINTILLATIONYIELD1:
return 1.0;
259 case kDEUTERONSCINTILLATIONYIELD2:
return 1.0;
260 case kDEUTERONSCINTILLATIONYIELD3:
return 1.0;
261 case kALPHASCINTILLATIONYIELD1:
return 1.0;
262 case kALPHASCINTILLATIONYIELD2:
return 1.0;
263 case kALPHASCINTILLATIONYIELD3:
return 1.0;
264 case kIONSCINTILLATIONYIELD1:
return 1.0;
265 case kIONSCINTILLATIONYIELD2:
return 1.0;
266 case kIONSCINTILLATIONYIELD3:
return 1.0;
267 case kELECTRONSCINTILLATIONYIELD1:
return 1.0;
268 case kELECTRONSCINTILLATIONYIELD2:
return 1.0;
269 case kELECTRONSCINTILLATIONYIELD3:
return 1.0;
271 case kFASTTIMECONSTANT:
return CLHEP::second/units::second;
272 case kFASTSCINTILLATIONRISETIME:
return CLHEP::second/units::second;
273 case kSLOWTIMECONSTANT:
return CLHEP::second/units::second;
274 case kSLOWSCINTILLATIONRISETIME:
return CLHEP::second/units::second;
275 case kYIELDRATIO:
return 1.0;
280 printout(FATAL,
"Geant4Converter",
"+++ Cannot convert CONST material property with index: %d", index);
282 printout(FATAL,
"Geant4Converter",
"+++ Cannot convert material property with index: %d [Need Geant4 > 10.03]", index);
311 double a_conv = (CLHEP::g / CLHEP::mole);
312 g4i =
new G4Isotope(iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA()*a_conv);
314 "Geant4Converter",
"++ Created G4 Isotope %s from data: Z=%d N=%d A=%.3f [g/mole]",
315 iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA());
326 if (element->GetNisotopes() > 0) {
327 g4e =
new G4Element(name, element->GetTitle(), element->GetNisotopes());
328 for (
int i = 0, n = element->GetNisotopes(); i < n; ++i) {
329 TGeoIsotope* iso = element->GetIsotope(i);
330 G4Isotope* g4iso = (G4Isotope*)
handleIsotope(iso->GetName(), iso);
331 g4e->AddIsotope(g4iso, element->GetRelativeAbundance(i));
336 double a_conv = (CLHEP::g / CLHEP::mole);
337 g4e =
new G4Element(element->GetTitle(), name, element->Z(), element->A()*a_conv);
338 printout(lvl,
"Geant4Converter",
"++ Created G4 Isotope %s from data: Z=%d N=%d A=%.3f [g/mole]",
339 element->GetName(), element->Z(), element->N(), element->A());
341 std::stringstream str;
342 str << (*g4e) << std::endl;
343 printout(lvl,
"Geant4Converter",
"++ Created G4 element %s", str.str().c_str());
352 G4Material* mat =
info.g4Materials[medium];
355 TGeoMaterial* material = medium->GetMaterial();
356 G4State state = kStateUndefined;
357 double density = material->GetDensity() * (CLHEP::gram / CLHEP::cm3);
358 if ( density < 1e-25 )
360 switch ( material->GetState() ) {
361 case TGeoMaterial::kMatStateSolid:
364 case TGeoMaterial::kMatStateLiquid:
365 state = kStateLiquid;
367 case TGeoMaterial::kMatStateGas:
371 case TGeoMaterial::kMatStateUndefined:
372 state = kStateUndefined;
375 printout(lvl,
"Geant4Material",
"+++ Setting up material %s", name.c_str());
376 if ( material->IsMixture() ) {
377 double A_total = 0.0;
378 double W_total = 0.0;
379 TGeoMixture*
mix = (TGeoMixture*) material;
380 int nElements =
mix->GetNelements();
381 mat =
new G4Material(name, density, nElements, state,
382 material->GetTemperature(), material->GetPressure());
383 for (
int i = 0; i < nElements; ++i) {
384 A_total += (
mix->GetAmixt())[i];
385 W_total += (
mix->GetWmixt())[i];
387 for (
int i = 0; i < nElements; ++i) {
388 TGeoElement* e =
mix->GetElement(i);
391 printout(ERROR, name,
392 "Missing element component %s for material %s. A=%f W=%f",
393 e->GetName(),
mix->GetName(), A_total, W_total);
396 mat->AddElement(g4e, (
mix->GetWmixt())[i] / W_total);
400 double z = material->GetZ(), a = material->GetA();
401 if ( z < 1.0000001 ) z = 1.0;
402 if ( a < 0.5000001 ) a = 1.0;
403 mat =
new G4Material(name, z, a, density, state,
404 material->GetTemperature(), material->GetPressure());
407 std::string plugin_name { };
409 double ionisation_mee = -2e100;
410 double ionisation_birks_constant = -2e100;
411 double ionisation_ene_per_ion_pair = -2e100;
414 G4MaterialPropertiesTable* tab = 0;
415 TListIter propIt(&material->GetProperties());
416 for(
TObject* obj=propIt.Next(); obj; obj = propIt.Next()) {
419 TGDMLMatrix* matrix =
info.manager->GetGDMLMatrix(named->GetTitle());
420 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
421 if (
nullptr != cptr ) {
422 printout(INFO,name,
"++ Ignore property %s [%s]. Not Suitable for Geant4.",
423 matrix->GetName(), matrix->GetTitle());
426 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
427 if (
nullptr != cptr ) {
428 printout(INFO,name,
"++ Ignore property %s [%s]. Not Suitable for Geant4.",
429 matrix->GetName(), matrix->GetTitle());
434 if (
nullptr ==
v ) {
435 except(
"Geant4Converter",
"++ FAILED to create G4 material %s [Cannot convert property:%s]",
436 material->GetName(), named->GetName());
438 if (
nullptr == tab ) {
439 tab =
new G4MaterialPropertiesTable();
440 mat->SetMaterialPropertiesTable(tab);
444 idx = tab->GetPropertyIndex(named->GetName());
454 printout(ERROR,
"Geant4Converter",
455 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
456 exc_str.c_str(), named->GetName());
460 auto conv = g4PropertyConversion(idx);
461 std::vector<double> bins(
v->bins), vals(
v->values);
462 for(std::size_t i=0, count=bins.size(); i<count; ++i)
463 bins[i] *= conv.first, vals[i] *= conv.second;
465 G4MaterialPropertyVector* vec =
466 new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
467 tab->AddProperty(named->GetName(), vec);
468 printout(lvl, name,
"++ Property: %-20s [%ld x %ld] -> %s ",
469 named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
470 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
471 printout(lvl, name,
" Geant4: %s %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
472 named->GetName(), bins[i],
v->bins[i], conv.first);
476 TListIter cpropIt(&material->GetConstProperties());
477 for(
TObject* obj=cpropIt.Next(); obj; obj = cpropIt.Next()) {
482 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
483 if (
nullptr != cptr ) {
484 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
485 named->GetName(), named->GetTitle());
488 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
489 if (
nullptr != cptr ) {
490 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
491 named->GetName(), named->GetTitle());
494 cptr = ::strstr(named->GetName(), GEANT4_TAG_PLUGIN);
495 if (
nullptr != cptr ) {
496 printout(INFO, name,
"++ Ignore CONST property %s [%s] --> Plugin.",
497 named->GetName(), named->GetTitle());
498 plugin_name = named->GetTitle();
501 cptr = ::strstr(named->GetName(), GEANT4_TAG_BIRKSCONSTANT);
502 if (
nullptr != cptr ) {
504 value = material->GetConstProperty(GEANT4_TAG_BIRKSCONSTANT,&err);
505 if ( err == kFALSE ) ionisation_birks_constant = value * (CLHEP::mm/CLHEP::MeV)/(units::mm/units::MeV);
508 cptr = ::strstr(named->GetName(), GEANT4_TAG_MEE);
509 if (
nullptr != cptr ) {
511 value = material->GetConstProperty(GEANT4_TAG_MEE, &err);
512 if ( err == kFALSE ) ionisation_mee = value * (CLHEP::MeV/units::MeV);
515 cptr = ::strstr(named->GetName(), GEANT4_TAG_ENE_PER_ION_PAIR);
516 if (
nullptr != cptr ) {
518 value = material->GetConstProperty(GEANT4_TAG_ENE_PER_ION_PAIR,&err);
519 if ( err == kFALSE ) ionisation_ene_per_ion_pair = value * (CLHEP::MeV/units::MeV);
524 value =
info.manager->GetProperty(named->GetTitle(), &err);
525 if ( err != kFALSE ) {
527 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
528 material->GetName(), named->GetName());
530 if (
nullptr == tab ) {
531 tab =
new G4MaterialPropertiesTable();
532 mat->SetMaterialPropertiesTable(tab);
536 idx = tab->GetConstPropertyIndex(named->GetName());
546 printout(ERROR, name,
547 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
548 exc_str.c_str(), named->GetName());
552 double conv = g4ConstPropertyConversion(idx);
553 printout(lvl, name,
"++ CONST Property: %-20s %g ", named->GetName(), value);
554 tab->AddConstProperty(named->GetName(), value * conv);
558 auto* ionisation = mat->GetIonisation();
559 std::stringstream str;
562 if ( ionisation_birks_constant > 0e0 ) {
563 ionisation->SetBirksConstant(ionisation_birks_constant);
565 if ( ionisation_mee > -1e100 ) {
566 ionisation->SetMeanExcitationEnergy(ionisation_mee);
568 if ( ionisation_ene_per_ion_pair > 0e0 ) {
569 ionisation->SetMeanEnergyPerIonPair(ionisation_ene_per_ion_pair);
571 str <<
" log(MEE): " << std::setprecision(4) << ionisation->GetLogMeanExcEnergy();
572 if ( ionisation_birks_constant > 0e0 )
573 str <<
" Birk's constant: " << std::setprecision(4) << ionisation->GetBirksConstant() <<
" [mm/MeV]";
574 if ( ionisation_ene_per_ion_pair > 0e0 )
575 str <<
" Mean Energy Per Ion Pair: " << std::setprecision(4) << ionisation->GetMeanEnergyPerIonPair()/CLHEP::eV <<
" [eV]";
578 str <<
" No ionisation parameters availible.";
580 printout(lvl, name,
"++ Created G4 material %s", str.str().c_str());
582 if ( !plugin_name.empty() ) {
585 G4Material* extended_mat = PluginService::Create<G4Material*>(plugin_name,
det, medium, mat);
586 if ( !extended_mat ) {
587 except(
"G4Cnv::material["+name+
"]",
"++ FATAL Failed to call plugin to create material.");
591 info.g4Materials[medium] = mat;
598 G4VSolid* solid =
nullptr;
600 if (
nullptr != (solid =
data().g4Solids[shape]) ) {
603 TClass* isa = shape->IsA();
605 if (isa == TGeoShapeAssembly::Class()) {
611 else if (isa == TGeoBBox::Class())
613 else if (isa == TGeoTube::Class())
615 else if (isa == TGeoTubeSeg::Class())
617 else if (isa == TGeoCtub::Class())
619 else if (isa == TGeoEltu::Class())
621 else if (isa == TwistedTubeObject::Class())
623 else if (isa == TGeoTrd1::Class())
625 else if (isa == TGeoTrd2::Class())
627 else if (isa == TGeoHype::Class())
629 else if (isa == TGeoXtru::Class())
631 else if (isa == TGeoPgon::Class())
633 else if (isa == TGeoPcon::Class())
635 else if (isa == TGeoCone::Class())
637 else if (isa == TGeoConeSeg::Class())
639 else if (isa == TGeoParaboloid::Class())
641 else if (isa == TGeoSphere::Class())
643 else if (isa == TGeoTorus::Class())
645 else if (isa == TGeoTrap::Class())
647 else if (isa == TGeoArb8::Class())
649 else if (isa == TGeoPara::Class())
651 else if (isa == TGeoTessellated::Class())
653 else if (isa == TGeoScaledShape::Class()) {
654 TGeoScaledShape* sh = (TGeoScaledShape*) shape;
655 TGeoShape* sol = sh->GetShape();
656 if ( sol->IsA() == TGeoShapeAssembly::Class() ) {
659 const double* vals = sh->GetScale()->GetScale();
660 G4Scale3D scal(vals[0], vals[1], vals[2]);
661 G4VSolid* g4solid = (G4VSolid*)
handleSolid(sol->GetName(), sol);
662 if ( scal.xx()>0e0 && scal.yy()>0e0 && scal.zz()>0e0 )
663 solid =
new G4ScaledSolid(sh->GetName(), g4solid, scal);
665 solid =
new G4ReflectedSolid(g4solid->GetName()+
"_refl", g4solid, scal);
667 else if ( isa == TGeoCompositeShape::Class() ) {
668 const TGeoCompositeShape* sh = (
const TGeoCompositeShape*) shape;
669 const TGeoBoolNode*
boolean = sh->GetBoolNode();
670 TGeoBoolNode::EGeoBoolType oper =
boolean->GetBooleanOperator();
671 TGeoMatrix* matrix =
boolean->GetRightMatrix();
672 G4VSolid* left = (G4VSolid*)
handleSolid(name +
"_left", boolean->GetLeftShape());
673 G4VSolid* right = (G4VSolid*)
handleSolid(name +
"_right", boolean->GetRightShape());
676 except(
"Geant4Converter",
"++ No left Geant4 Solid present for composite shape: %s",name.c_str());
679 except(
"Geant4Converter",
"++ No right Geant4 Solid present for composite shape: %s",name.c_str());
682 TGeoShape* ls =
boolean->GetLeftShape();
683 TGeoShape* rs =
boolean->GetRightShape();
684 if (strcmp(ls->ClassName(),
"TGeoScaledShape") == 0 &&
685 strcmp(rs->ClassName(),
"TGeoBBox") == 0) {
686 if (strcmp(((TGeoScaledShape *)ls)->GetShape()->ClassName(),
"TGeoSphere") == 0) {
687 if (oper == TGeoBoolNode::kGeoIntersection) {
688 TGeoScaledShape* lls = (TGeoScaledShape *)ls;
689 TGeoBBox* rrs = (TGeoBBox*)rs;
690 double sx = lls->GetScale()->GetScale()[0];
691 double sy = lls->GetScale()->GetScale()[1];
692 double radius = ((TGeoSphere *)lls->GetShape())->GetRmax();
693 double dz = rrs->GetDZ();
694 double zorig = rrs->GetOrigin()[2];
695 double zcut2 = dz + zorig;
696 double zcut1 = 2 * zorig - zcut2;
697 solid =
new G4Ellipsoid(name,
709 if ( matrix->IsRotation() ) {
710 G4Transform3D transform;
712 if (oper == TGeoBoolNode::kGeoSubtraction)
713 solid =
new G4SubtractionSolid(name, left, right, transform);
714 else if (oper == TGeoBoolNode::kGeoUnion)
715 solid =
new G4UnionSolid(name, left, right, transform);
716 else if (oper == TGeoBoolNode::kGeoIntersection)
717 solid =
new G4IntersectionSolid(name, left, right, transform);
720 const Double_t *t = matrix->GetTranslation();
722 if (oper == TGeoBoolNode::kGeoSubtraction)
723 solid =
new G4SubtractionSolid(name, left, right, 0, transform);
724 else if (oper == TGeoBoolNode::kGeoUnion)
725 solid =
new G4UnionSolid(name, left, right, 0, transform);
726 else if (oper == TGeoBoolNode::kGeoIntersection)
727 solid =
new G4IntersectionSolid(name, left, right, 0, transform);
732 except(
"Geant4Converter",
"++ Failed to handle unknown solid shape: %s of type %s",
733 name.c_str(), isa->GetName());
734 printout(lvl,
"Geant4Converter",
"++ Successessfully converted shape [%p] of type:%s to %s.",
735 solid,isa->GetName(),typeName(
typeid(*solid)).c_str());
746 Geant4GeometryMaps::VolumeMap::const_iterator volIt =
info.g4Volumes.find(volume);
748 printout(lvl,
"Geant4Converter",
"++ Volume %s not converted [Veto'ed for simulation]",volume->GetName());
751 else if (volIt ==
info.g4Volumes.end() ) {
752 const char* vnam = volume->GetName();
753 TGeoMedium* med = volume->GetMedium();
754 Solid sh = volume->GetShape();
755 bool is_assembly = sh->IsA() == TGeoShapeAssembly::Class() || volume->IsAssembly();
757 printout(lvl,
"Geant4Converter",
"++ Convert Volume %-32s: %p %s/%s assembly:%s",
758 vnam, volume, sh.
type(), _v.
type(), yes_no(is_assembly));
765 G4Region* g4region = reg.
isValid() ?
info.g4Regions[reg] :
nullptr;
767 G4VSolid* g4solid = (G4VSolid*)
handleSolid(sh->GetName(), sh);
771 except(
"G4Converter",
"++ No Geant4 Solid present for volume: %s", vnam);
773 else if ( !g4medium ) {
774 except(
"G4Converter",
"++ No Geant4 material present for volume: %s", vnam);
776 else if ( reg.
isValid() && !g4region ) {
777 except(
"G4Cnv::volume["+name+
"]",
" ++ Failed to access Geant4 region %s.", reg.
name());
779 else if ( lim.
isValid() && !g4limits ) {
780 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to access Geant4 user limits %s.", lim.
name());
782 else if ( g4limits ) {
783 printout(lvl,
"Geant4Converter",
"++ Volume + Apply LIMITS settings: %-24s to volume %s.",
787 G4LogicalVolume* g4vol =
nullptr;
790 std::string plugin = _v.
getProperty(GEANT4_TAG_PLUGIN,
"");
791 g4vol = PluginService::Create<G4LogicalVolume*>(plugin,
det, _v, g4solid, g4medium);
793 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to call plugin to create logical volume.");
797 g4vol =
new G4LogicalVolume(g4solid, g4medium, vnam,
nullptr,
nullptr,
nullptr);
803 printout(ALWAYS,
"Geant4Converter",
"++ Volume %s Set Smartless value to %d",
804 vnam,
int(smart_less_value));
805 g4vol->SetSmartless( smart_less_value );
809 g4vol->SetUserLimits(g4limits);
812 printout(plevel,
"Geant4Converter",
"++ Volume + Apply REGION settings: %-24s to volume %s.",
818 const char* wrd_nam =
"DefaultRegionForTheWorld";
819 const char* src_nam = g4region->GetName().c_str();
820 auto* world_region = G4RegionStore::GetInstance()->GetRegion(wrd_nam,
false);
821 if (
auto* cuts = g4region->GetProductionCuts() ) {
822 world_region->SetProductionCuts(cuts);
823 printout(plevel,
"Geant4Converter",
824 "++ Volume %s Region: %s. Apply production cuts from %s",
825 vnam, wrd_nam, src_nam);
827 if (
auto* lims = g4region->GetUserLimits() ) {
828 world_region->SetUserLimits(lims);
829 printout(plevel,
"Geant4Converter",
830 "++ Volume %s Region: %s. Apply user limits from %s",
831 vnam, wrd_nam, src_nam);
835 g4vol->SetRegion(g4region);
836 g4region->AddRootLogicalVolume(g4vol);
839 G4VisAttributes* g4vattr = vis.
isValid()
842 g4vol->SetVisAttributes(g4vattr);
844 info.g4Volumes[volume] = g4vol;
845 printout(lvl,
"Geant4Converter",
846 "++ Volume + %s converted: %p ---> G4: %p", vnam, volume, g4vol);
862 info.limits[lim].insert(volume);
864 info.regions[reg].insert(volume);
866 info.sensitives[
det].insert(volume);
868 return (
void*)volume;
873 TGeoVolume* mot_vol = node->GetVolume();
875 if ( mot_vol->IsA() != TGeoVolumeAssembly::Class() ) {
880 printout(lvl,
"Geant4Converter",
"++ AssemblyNode %s not converted [Veto'ed for simulation]",node->GetName());
886 printout(ALWAYS,
"Geant4Converter",
"+++ Assembly: **** : Re-using existing assembly: %s",node->GetName());
890 for(Int_t i=0; i < mot_vol->GetNdaughters(); ++i) {
891 TGeoNode* dau = mot_vol->GetNode(i);
892 TGeoVolume* dau_vol = dau->GetVolume();
893 TGeoMatrix* tr = dau->GetMatrix();
894 G4Transform3D transform;
897 if ( is_left_handed(tr) ) {
901 transform.getDecomposition(scale, rot, trans);
903 "++ Placing reflected ASSEMBLY. dau:%s to mother %s "
904 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
905 dau_vol->GetName(), mot_vol->GetName(),
906 transform.dx(), transform.dy(), transform.dz(),
907 scale.xx(), scale.yy(), scale.zz());
910 if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) {
911 Geant4GeometryMaps::AssemblyMap::iterator ia =
info.g4AssemblyVolumes.find(dau);
912 if ( ia ==
info.g4AssemblyVolumes.end() ) {
913 printout(FATAL,
"Geant4Converter",
"+++ Invalid child assembly at %s : %d parent: %s child:%s",
914 __FILE__, __LINE__, name.c_str(), dau->GetName());
919 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedAssembly %p: dau:%s "
920 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
921 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
922 transform.dx(), transform.dy(), transform.dz());
925 Geant4GeometryMaps::VolumeMap::iterator iv =
info.g4Volumes.find(dau_vol);
926 if ( iv ==
info.g4Volumes.end() ) {
927 printout(FATAL,
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
928 __FILE__, __LINE__, name.c_str(), dau->GetName());
929 except(
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
930 __FILE__, __LINE__, name.c_str(), dau->GetName());
933 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedVolume %p: dau:%s "
934 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
935 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
936 transform.dx(), transform.dy(), transform.dz());
939 info.g4AssemblyVolumes[node] = g4;
948 Geant4GeometryMaps::PlacementMap::const_iterator g4it =
info.g4Placements.find(node);
949 G4VPhysicalVolume* g4 = (g4it ==
info.g4Placements.end()) ? 0 : (*g4it).second;
950 TGeoVolume* vol = node->GetVolume();
954 printout(lvl,
"Geant4Converter",
"++ Placement %s not converted [Veto'ed for simulation]",node->GetName());
959 TGeoVolume* mot_vol = node->GetMotherVolume();
960 TGeoMatrix* tr = node->GetMatrix();
962 except(
"Geant4Converter",
963 "++ Attempt to handle placement without transformation:%p %s of type %s vol:%p",
964 node, node->GetName(), node->IsA()->GetName(), vol);
966 else if (
nullptr == vol) {
967 except(
"Geant4Converter",
"++ Unknown G4 volume:%p %s of type %s ptr:%p",
968 node, node->GetName(), node->IsA()->GetName(), vol);
971 int copy = node->GetNumber();
972 bool node_is_reflected = is_left_handed(tr);
973 bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class();
974 bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() :
false;
975 G4Transform3D transform;
976 Geant4GeometryMaps::VolumeMap::const_iterator volIt =
info.g4Volumes.find(mot_vol);
979 if ( mother_is_assembly ) {
986 printout(lvl,
"Geant4Converter",
"+++ Assembly: **** : dau:%s "
987 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
988 vol->GetName(), mot_vol->GetName(),
989 transform.dx(), transform.dy(), transform.dz());
995 transform.getDecomposition(scale, rot, trans);
996 if ( node_is_assembly ) {
1001 printout(lvl,
"Geant4Converter",
"++ Assembly: makeImprint: dau:%-12s %s in mother %-12s "
1002 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1003 node->GetName(), node_is_reflected ?
"(REFLECTED)" :
"",
1004 mot_vol ? mot_vol->GetName() :
"<unknown>",
1005 transform.dx(), transform.dy(), transform.dz(),
1006 scale.xx(), scale.yy(), scale.zz());
1009 chain.emplace_back(node);
1013 else if ( node !=
info.manager->GetTopNode() && volIt ==
info.g4Volumes.end() ) {
1017 const auto* pv_data = pv.
data();
1018 G4LogicalVolume* g4vol =
info.g4Volumes[vol];
1019 G4LogicalVolume* g4mot =
info.g4Volumes[mot_vol];
1020 G4PhysicalVolumesPair pvPlaced {
nullptr,
nullptr };
1023 EAxis axis = kUndefined;
1024 double width = 0e0, offset = 0e0;
1025 auto flags = pv_data->params->flags;
1026 auto count = pv_data->params->trafo1D.second;
1027 auto start = pv_data->params->start.Translation().Vect();
1028 auto delta = pv_data->params->trafo1D.first.Translation().Vect();
1031 { axis = kXAxis; width =
delta.X(); offset = start.X(); }
1033 { axis = kYAxis; width =
delta.Y(); offset = start.Y(); }
1035 { axis = kZAxis; width =
delta.Z(); offset = start.Z(); }
1037 except(
"Geant4Converter",
1038 "++ Replication around unknown axis is not implemented. flags: %16X", flags);
1039 printout(INFO,
"Geant4Converter",
"++ Replicate: Axis: %ld Count: %ld offset: %f width: %f",
1040 axis, count, offset, width);
1041 auto* g4pv =
new G4PVReplica(name,
1048 pvPlaced = { g4pv,
nullptr };
1051 G4ReflectionFactory::Instance()->Replicate(name,
1059 auto* g4pv = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1061 for(
auto&
handle : pv_data->params->placements )
1064 else if ( pv_data && pv_data->params ) {
1066 auto* g4pv =
new G4PVParameterised(name,
1072 pvPlaced = { g4pv,
nullptr };
1074 for(
auto&
handle : pv_data->params->placements )
1079 G4ReflectionFactory::Instance()->Place(transform,
1088 "++ Place %svolume %-12s in mother %-12s "
1089 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1090 node_is_reflected ?
"REFLECTED " :
"", _v.
name(),
1091 mot_vol ? mot_vol->GetName() :
"<unknown>",
1092 transform.dx(), transform.dy(), transform.dz(),
1093 scale.xx(), scale.yy(), scale.zz());
1096 if ( node_is_reflected && !pvPlaced.second )
1097 return info.g4Placements[node] = pvPlaced.first;
1098 else if ( !node_is_reflected && !pvPlaced.second )
1099 return info.g4Placements[node] = pvPlaced.first;
1101 if ( node_is_reflected )
1102 return info.g4Placements[node] = pvPlaced.first;
1103 else if ( !node_is_reflected )
1104 return info.g4Placements[node] = pvPlaced.first;
1105 g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1107 info.g4Placements[node] = g4;
1108 printout(ERROR,
"Geant4Converter",
"++ DEAD code. Should not end up here!");
1119 g4 =
new G4Region(region.
name());
1123 throw std::runtime_error(
"G4Region: StoreSecondaries is True, but no explicit threshold set:");
1125 printout(lvl,
"Geant4Converter",
"++ Setting up region: %s", r.
name());
1126 G4UserRegionInformation*
info =
new G4UserRegionInformation();
1130 g4->SetUserInformation(
info);
1132 printout(lvl,
"Geant4Converter",
"++ Converted region settings of:%s.", r.
name());
1133 std::vector < std::string > &limits = r.
limits();
1134 G4ProductionCuts* cuts = 0;
1137 cuts =
new G4ProductionCuts();
1138 cuts->SetProductionCut(r.
cut()*CLHEP::mm/units::mm);
1139 printout(lvl,
"Geant4Converter",
"++ %s: Using default cut: %f [mm]",
1140 r.
name(), r.
cut()*CLHEP::mm/units::mm);
1142 for(
const auto& nam : limits ) {
1146 for (
const auto& c : cts ) {
1148 if ( c.particles ==
"*" ) pid = -1;
1149 else if ( c.particles ==
"e-" ) pid = idxG4ElectronCut;
1150 else if ( c.particles ==
"e+" ) pid = idxG4PositronCut;
1151 else if ( c.particles ==
"e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1152 else if ( c.particles ==
"e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1153 else if ( c.particles ==
"gamma" ) pid = idxG4GammaCut;
1154 else if ( c.particles ==
"proton" ) pid = idxG4ProtonCut;
1155 else throw std::runtime_error(
"G4Region: Invalid production cut particle-type:" + c.particles);
1156 if ( !cuts ) cuts =
new G4ProductionCuts();
1157 if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1158 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4PositronCut);
1159 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4ElectronCut);
1162 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, pid);
1164 printout(lvl,
"Geant4Converter",
"++ %s: Set cut [%s/%d] = %f [mm]",
1165 r.
name(), c.particles.c_str(), pid, c.value*CLHEP::mm/units::mm);
1169 for (
const auto& j : lm ) {
1170 if (nam == j.first->GetName()) {
1171 g4->SetUserLimits(j.second);
1172 printout(lvl,
"Geant4Converter",
"++ %s: Set limits %s to region type %s",
1173 r.
name(), nam.c_str(), j.second->GetType().c_str());
1182 except(
"Geant4Converter",
"++ G4Region: Failed to resolve limitset: " + nam);
1185 if ( cuts ) g4->SetProductionCuts(cuts);
1198 LimitPrint(
const LimitSet& lset) : ls(lset) {}
1201 printout(ALWAYS,
"Geant4Converter",
1202 "+++ LimitSet: Explicit Limit %s.%s applied for particles:",ls.
name(), pref.c_str());
1204 printout(ALWAYS,
"Geant4Converter",
"+++ LimitSet: Particle type: %-18s PDG: %-6d : %f",
1205 p.first->GetParticleName().c_str(), p.first->GetPDGEncoding(), p.second);
1208 printout(ALWAYS,
"Geant4Converter",
1209 "+++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f",
1217 printout(lvl,
"Geant4Converter",
1218 "++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]",
1219 limitset.
name(), limitset.
cuts().size(), limitset.
limits().size());
1221 LimitPrint print(limitset);
1222 print(
"maxTime", limits->
maxTime)
1236 G4VisAttributes* g4 =
info.g4Vis[attr];
1238 float red = 0, green = 0, blue = 0;
1240 attr.
rgb(red, green, blue);
1241 g4 =
new G4VisAttributes(attr.
visible(), G4Colour(red, green, blue, attr.
alpha()));
1245 g4->SetLineStyle(G4VisAttributes::unbroken);
1246 g4->SetForceWireframe(
false);
1247 g4->SetForceSolid(
true);
1250 g4->SetLineStyle(G4VisAttributes::dashed);
1251 g4->SetForceSolid(
false);
1252 g4->SetForceWireframe(
true);
1254 info.g4Vis[attr] = g4;
1261 std::map < std::string, std::string > processors;
1262 static int s_idd = 9999999;
1263 for(
const auto& [nam, vals] : prp ) {
1264 if ( nam.substr(0, 6) ==
"geant4" ) {
1265 auto id_it = vals.find(
"id");
1266 std::string
id = (id_it == vals.end()) ?
_toString(++s_idd,
"%d") : (*id_it).second;
1267 processors.emplace(
id, nam);
1270 for(
const auto& p : processors ) {
1273 auto iter = vals.find(
"type");
1274 if ( iter != vals.end() ) {
1275 std::string type = iter->second;
1276 std::string tag = type +
"_Geant4_action";
1278 long res = PluginService::Create<long>(tag,
det, hdlr, &vals);
1280 throw std::runtime_error(
"Failed to locate plugin to interprete files of type"
1281 " \"" + tag +
"\" - no factory:" + type);
1285 throw std::runtime_error(
"Failed to invoke the plugin " + tag +
" of type " + type);
1287 printout(
outputLevel,
"Geant4Converter",
"+++++ Executed Successfully Geant4 setup module *%s*.", type.c_str());
1290 printout(
outputLevel,
"Geant4Converter",
"+++++ FAILED to execute Geant4 setup module *%s*.", p.second.c_str());
1297 TGDMLMatrix* matrix = (TGDMLMatrix*)mtx;
1298 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1301 if (
nullptr != cptr ) {
1302 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1303 matrix->GetName(), matrix->GetTitle());
1306 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
1307 if (
nullptr != cptr ) {
1308 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1309 matrix->GetName(), matrix->GetTitle());
1316 std::size_t rows = matrix->GetRows();
1317 g4->
name = matrix->GetName();
1318 g4->
title = matrix->GetTitle();
1319 g4->
bins.reserve(rows);
1320 g4->
values.reserve(rows);
1321 for( std::size_t i=0; i<rows; ++i ) {
1322 g4->
bins.emplace_back(matrix->Get(i,0) );
1323 g4->
values.emplace_back(matrix->Get(i,1));
1325 printout(lvl,
"Geant4Converter",
1326 "++ Successfully converted material property:%s : %s [%ld rows]",
1327 matrix->GetName(), matrix->GetTitle(), rows);
1328 info.g4OpticalProperties[matrix] = g4;
1333 static G4OpticalSurfaceFinish geant4_surface_finish(TGeoOpticalSurface::ESurfaceFinish f) {
1334 #define TO_G4_FINISH(x) case TGeoOpticalSurface::kF##x : return x;
1382 printout(ERROR,
"Geant4Surfaces",
"++ Unknown finish style: %d [%s]. Assume polished!",
1383 int(f), TGeoOpticalSurface::FinishToString(f));
1389 static G4SurfaceType geant4_surface_type(TGeoOpticalSurface::ESurfaceType t) {
1390 #define TO_G4_TYPE(x) case TGeoOpticalSurface::kT##x : return x;
1400 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface type: %d [%s]. Assume dielectric_metal!",
1401 int(t), TGeoOpticalSurface::TypeToString(t));
1402 return dielectric_metal;
1407 static G4OpticalSurfaceModel geant4_surface_model(TGeoOpticalSurface::ESurfaceModel surfMod) {
1408 #define TO_G4_MODEL(x) case TGeoOpticalSurface::kM##x : return x;
1416 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface model: %d [%s]. Assume glisur!",
1417 int(surfMod), TGeoOpticalSurface::ModelToString(surfMod));
1425 TGeoOpticalSurface* optSurf = (TGeoOpticalSurface*)surface;
1427 G4OpticalSurface* g4 =
info.g4OpticalSurfaces[optSurf];
1429 G4SurfaceType type = geant4_surface_type(optSurf->GetType());
1430 G4OpticalSurfaceModel model = geant4_surface_model(optSurf->GetModel());
1431 G4OpticalSurfaceFinish finish = geant4_surface_finish(optSurf->GetFinish());
1432 std::string name = make_NCName(optSurf->GetName());
1434 g4 =
new G4OpticalSurface(name, model, finish, type, optSurf->GetValue());
1435 g4->SetSigmaAlpha(optSurf->GetSigmaAlpha());
1436 g4->SetPolish(optSurf->GetPolish());
1438 printout(lvl,
"Geant4Converter",
1439 "++ Created OpticalSurface: %-18s type:%s model:%s finish:%s SigmaAlphs: %.3e Polish: %.3e",
1441 TGeoOpticalSurface::TypeToString(optSurf->GetType()),
1442 TGeoOpticalSurface::ModelToString(optSurf->GetModel()),
1443 TGeoOpticalSurface::FinishToString(optSurf->GetFinish()),
1444 optSurf->GetSigmaAlpha(), optSurf->GetPolish());
1447 G4MaterialPropertiesTable* tab =
nullptr;
1448 TListIter itp(&optSurf->GetProperties());
1449 for(
TObject* obj = itp.Next(); obj; obj = itp.Next()) {
1450 std::string exc_str;
1452 TGDMLMatrix* matrix =
info.manager->GetGDMLMatrix(named->GetTitle());
1453 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1454 if (
nullptr != cptr )
1457 if (
nullptr == tab ) {
1458 tab =
new G4MaterialPropertiesTable();
1459 g4->SetMaterialPropertiesTable(tab);
1465 except(
"Geant4OpticalSurface",
"++ Failed to convert opt.surface %s. Property table %s is not defined!",
1466 optSurf->GetName(), named->GetTitle());
1470 idx = tab->GetPropertyIndex(named->GetName());
1478 printout(ERROR,
"Geant4Converter",
1479 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
1480 exc_str.c_str(), named->GetName());
1484 auto conv = g4PropertyConversion(idx);
1485 std::vector<double> bins(
v->bins), vals(
v->values);
1486 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1487 bins[i] *= conv.first, vals[i] *= conv.second;
1488 G4MaterialPropertyVector* vec =
new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
1489 tab->AddProperty(named->GetName(), vec);
1491 printout(lvl,
"Geant4Converter",
1492 "++ Property: %-20s [%ld x %ld] --> %s",
1493 named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
1494 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1495 printout(lvl, named->GetName(),
1496 " Geant4: %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
1497 bins[i],
v->bins[i], conv.first);
1501 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
1502 TListIter itc(&optSurf->GetConstProperties());
1503 for(
TObject* obj = itc.Next(); obj; obj = itc.Next()) {
1504 std::string exc_str;
1506 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
1507 if (
nullptr != cptr ) {
1508 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1509 named->GetName(), named->GetTitle());
1512 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
1513 if (
nullptr != cptr ) {
1514 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1515 named->GetName(), named->GetTitle());
1518 Bool_t err = kFALSE;
1519 Double_t value =
info.manager->GetProperty(named->GetTitle(),&err);
1520 if ( err != kFALSE ) {
1522 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
1523 optSurf->GetName(), named->GetName());
1525 if (
nullptr == tab ) {
1526 tab =
new G4MaterialPropertiesTable();
1527 g4->SetMaterialPropertiesTable(tab);
1531 idx = tab->GetConstPropertyIndex(named->GetName());
1539 printout(ERROR, name,
1540 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
1541 exc_str.c_str(), named->GetName());
1545 double conv = g4ConstPropertyConversion(idx);
1546 printout(lvl, name,
"++ CONST Property: %-20s %g * %g --> %g ",
1547 named->GetName(), value, conv, value * conv);
1548 tab->AddConstProperty(named->GetName(), value * conv);
1550 #endif // ROOT_VERSION >= 6.31.1
1551 info.g4OpticalSurfaces[optSurf] = g4;
1558 TGeoSkinSurface* surf = (TGeoSkinSurface*)surface;
1560 G4LogicalSkinSurface* g4 =
info.g4SkinSurfaces[surf];
1562 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1563 G4LogicalVolume*
v =
info.g4Volumes[surf->GetVolume()];
1564 std::string name = make_NCName(surf->GetName());
1565 g4 =
new G4LogicalSkinSurface(name,
v, optSurf);
1567 "++ Created SkinSurface: %-18s optical:%s",
1568 surf->GetName(), surf->GetSurface()->GetName());
1569 info.g4SkinSurfaces[surf] = g4;
1576 TGeoBorderSurface* surf = (TGeoBorderSurface*)surface;
1578 G4LogicalBorderSurface* g4 =
info.g4BorderSurfaces[surf];
1580 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1581 G4VPhysicalVolume* n1 =
info.g4Placements[surf->GetNode1()];
1582 G4VPhysicalVolume* n2 =
info.g4Placements[surf->GetNode2()];
1583 std::string name = make_NCName(surf->GetName());
1584 g4 =
new G4LogicalBorderSurface(name, n1, n2, optSurf);
1586 "++ Created BorderSurface: %-18s optical:%s",
1587 surf->GetName(), surf->GetSurface()->GetName());
1588 info.g4BorderSurfaces[surf] = g4;
1596 std::set<const TGeoVolume*>& volset =
info.sensitives[sens_det];
1598 std::stringstream str;
1600 printout(INFO,
"Geant4Converter",
"++ SensitiveDetector: %-18s %-20s Hits:%-16s", sd.
name(), (
"[" + sd.
type() +
"]").c_str(),
1602 str <<
" | " <<
"Cutoff:" << std::setw(6) << std::left
1603 << sd.
energyCutoff() << std::setw(5) << std::right << volset.size()
1606 str <<
" Region:" << std::setw(12) << std::left << sd.
region().
name();
1608 str <<
" Limits:" << std::setw(12) << std::left << sd.
limits().
name();
1610 printout(INFO,
"Geant4Converter", str.str().c_str());
1612 for (
const auto i : volset ) {
1613 std::map<Volume, G4LogicalVolume*>::iterator
v =
info.g4Volumes.find(i);
1614 if (
v !=
info.g4Volumes.end() ) {
1615 G4LogicalVolume* vol = (*v).second;
1617 str <<
" | " <<
"Volume:" << std::setw(24) << std::left << vol->GetName() <<
" "
1618 << vol->GetNoDaughters() <<
" daughters.";
1619 printout(INFO,
"Geant4Converter", str.str().c_str());
1625 std::stringstream str;
1626 if (
typeid(*sol) ==
typeid(G4Box)) {
1627 const G4Box* b = (G4Box*) sol;
1628 str <<
"++ Box: x=" << b->GetXHalfLength() <<
" y=" << b->GetYHalfLength() <<
" z=" << b->GetZHalfLength();
1630 else if (
typeid(*sol) ==
typeid(G4Tubs)) {
1631 const G4Tubs* t = (
const G4Tubs*) sol;
1632 str <<
" Tubs: Ri=" << t->GetInnerRadius() <<
" Ra=" << t->GetOuterRadius() <<
" z/2=" << t->GetZHalfLength() <<
" Phi="
1633 << t->GetStartPhiAngle() <<
"..." << t->GetDeltaPhiAngle();
1641 G4VPhysicalVolume* g4 =
info.g4Placements[node];
1642 G4LogicalVolume* vol =
info.g4Volumes[node->GetVolume()];
1643 G4LogicalVolume* mot =
info.g4Volumes[node->GetMotherVolume()];
1644 G4VSolid* sol = vol->GetSolid();
1645 G4ThreeVector tr = g4->GetObjectTranslation();
1650 std::stringstream str;
1651 str <<
"G4Cnv::placement: + " << name <<
" No:" << node->GetNumber() <<
" Vol:" << vol->GetName() <<
" Solid:"
1653 printout(
outputLevel,
"G4Placement", str.str().c_str());
1655 str <<
" |" <<
" Loc: x=" << tr.x() <<
" y=" << tr.y() <<
" z=" << tr.z();
1656 printout(
outputLevel,
"G4Placement", str.str().c_str());
1659 str <<
" |" <<
" Ndau:" << vol->GetNoDaughters()
1660 <<
" physvols." <<
" Mat:" << vol->GetMaterial()->GetName()
1661 <<
" Mother:" << (
char*) (mot ? mot->GetName().c_str() :
"---");
1662 printout(
outputLevel,
"G4Placement", str.str().c_str());
1664 str <<
" |" <<
" SD:" << sd->GetName();
1665 printout(
outputLevel,
"G4Placement", str.str().c_str());
1671 typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU;
1691 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld solids.", geo.
solids.size());
1693 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld visualization attributes.", geo.
vis.size());
1695 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld limit sets.", geo.
limits.size());
1697 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld regions.", geo.
regions.size());
1699 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld volumes.", geo.
volumes.size());
1703 std::map<int, std::vector<const TGeoNode*> >::const_reverse_iterator i =
m_data->rbegin();
1704 for ( ; i !=
m_data->rend(); ++i ) {
1705 for (
const TGeoNode* node : i->second ) {
1725 printout(INFO,
"Geant4Converter",
1726 "+++ Successfully converted geometry to Geant4. [%7.3f seconds]",
1727 stop.AsDouble()-start.AsDouble() );