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 available.";
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",
749 "++ Volume %s not converted [Veto'ed for simulation]",
753 else if (volIt ==
info.g4Volumes.end() ) {
754 const char* vnam = volume->GetName();
755 TGeoMedium* med = volume->GetMedium();
756 Solid sh = volume->GetShape();
757 bool is_assembly = sh->IsA() == TGeoShapeAssembly::Class() || volume->IsAssembly();
759 printout(lvl,
"Geant4Converter",
"++ Convert Volume %-32s: %p %s/%s assembly:%s",
760 vnam, volume, sh.
type(), _v.
type(), yes_no(is_assembly));
767 G4Region* g4region = reg.
isValid() ?
info.g4Regions[reg] :
nullptr;
769 G4VSolid* g4solid = (G4VSolid*)
handleSolid(sh->GetName(), sh);
773 except(
"G4Converter",
"++ No Geant4 Solid present for volume: %s", vnam);
775 else if ( !g4medium ) {
776 except(
"G4Converter",
"++ No Geant4 material present for volume: %s", vnam);
778 else if ( reg.
isValid() && !g4region ) {
779 except(
"G4Cnv::volume["+name+
"]",
" ++ Failed to access Geant4 region %s.", reg.
name());
781 else if ( lim.
isValid() && !g4limits ) {
782 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to access Geant4 user limits %s.", lim.
name());
784 else if ( g4limits ) {
785 printout(lvl,
"Geant4Converter",
"++ Volume + Apply LIMITS settings: %-24s to volume %s.",
789 G4LogicalVolume* g4vol =
nullptr;
792 std::string plugin = _v.
getProperty(GEANT4_TAG_PLUGIN,
"");
793 g4vol = PluginService::Create<G4LogicalVolume*>(plugin,
det, _v, g4solid, g4medium);
795 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to call plugin to create logical volume.");
799 g4vol =
new G4LogicalVolume(g4solid, g4medium, vnam,
nullptr,
nullptr,
nullptr);
805 printout(ALWAYS,
"Geant4Converter",
806 "++ Volume %s Set Smartless value to %d",
807 vnam,
int(smart_less_value));
808 g4vol->SetSmartless( smart_less_value );
812 g4vol->SetUserLimits(g4limits);
815 printout(plevel,
"Geant4Converter",
816 "++ Volume + Apply REGION settings: %-24s to volume %s.",
822 const char* wrd_nam =
"DefaultRegionForTheWorld";
823 const char* src_nam = g4region->GetName().c_str();
824 auto* world_region = G4RegionStore::GetInstance()->GetRegion(wrd_nam,
false);
825 if (
auto* cuts = g4region->GetProductionCuts() ) {
826 world_region->SetProductionCuts(cuts);
827 printout(plevel,
"Geant4Converter",
828 "++ Volume %s Region: %s. Apply production cuts from %s",
829 vnam, wrd_nam, src_nam);
831 if (
auto* lims = g4region->GetUserLimits() ) {
832 world_region->SetUserLimits(lims);
833 printout(plevel,
"Geant4Converter",
834 "++ Volume %s Region: %s. Apply user limits from %s",
835 vnam, wrd_nam, src_nam);
839 g4vol->SetRegion(g4region);
840 g4region->AddRootLogicalVolume(g4vol);
843 G4VisAttributes* g4vattr = vis.
isValid()
846 g4vol->SetVisAttributes(g4vattr);
848 info.g4Volumes[volume] = g4vol;
849 printout(lvl,
"Geant4Converter",
850 "++ Volume + %s converted: %p ---> G4: %p", vnam, volume, g4vol);
866 info.limits[lim].insert(volume);
868 info.regions[reg].insert(volume);
870 info.sensitives[
det].insert(volume);
872 return (
void*)volume;
877 TGeoVolume* mot_vol = node->GetVolume();
879 if ( mot_vol->IsA() != TGeoVolumeAssembly::Class() ) {
884 printout(lvl,
"Geant4Converter",
"++ AssemblyNode %s not converted [Veto'ed for simulation]",node->GetName());
890 printout(ALWAYS,
"Geant4Converter",
"+++ Assembly: **** : Re-using existing assembly: %s",node->GetName());
894 for(Int_t i=0; i < mot_vol->GetNdaughters(); ++i) {
895 TGeoNode* dau = mot_vol->GetNode(i);
896 TGeoVolume* dau_vol = dau->GetVolume();
897 TGeoMatrix* tr = dau->GetMatrix();
898 G4Transform3D transform;
901 if ( is_left_handed(tr) ) {
905 transform.getDecomposition(scale, rot, trans);
907 "++ Placing reflected ASSEMBLY. dau:%s to mother %s "
908 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
909 dau_vol->GetName(), mot_vol->GetName(),
910 transform.dx(), transform.dy(), transform.dz(),
911 scale.xx(), scale.yy(), scale.zz());
914 if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) {
915 Geant4GeometryMaps::AssemblyMap::iterator ia =
info.g4AssemblyVolumes.find(dau);
916 if ( ia ==
info.g4AssemblyVolumes.end() ) {
917 printout(FATAL,
"Geant4Converter",
"+++ Invalid child assembly at %s : %d parent: %s child:%s",
918 __FILE__, __LINE__, name.c_str(), dau->GetName());
923 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedAssembly %p: dau:%s "
924 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
925 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
926 transform.dx(), transform.dy(), transform.dz());
929 Geant4GeometryMaps::VolumeMap::iterator iv =
info.g4Volumes.find(dau_vol);
930 if ( iv ==
info.g4Volumes.end() ) {
931 printout(FATAL,
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
932 __FILE__, __LINE__, name.c_str(), dau->GetName());
933 except(
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
934 __FILE__, __LINE__, name.c_str(), dau->GetName());
937 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedVolume %p: dau:%s "
938 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
939 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
940 transform.dx(), transform.dy(), transform.dz());
943 info.g4AssemblyVolumes[node] = g4;
952 Geant4GeometryMaps::PlacementMap::const_iterator g4it =
info.g4Placements.find(node);
953 G4VPhysicalVolume* g4 = (g4it ==
info.g4Placements.end()) ? 0 : (*g4it).second;
954 TGeoVolume* vol = node->GetVolume();
958 printout(lvl,
"Geant4Converter",
"++ Placement %s not converted [Veto'ed for simulation]",node->GetName());
963 TGeoVolume* mot_vol = node->GetMotherVolume();
964 TGeoMatrix* tr = node->GetMatrix();
966 except(
"Geant4Converter",
967 "++ Attempt to handle placement without transformation:%p %s of type %s vol:%p",
968 node, node->GetName(), node->IsA()->GetName(), vol);
970 else if (
nullptr == vol) {
971 except(
"Geant4Converter",
"++ Unknown G4 volume:%p %s of type %s ptr:%p",
972 node, node->GetName(), node->IsA()->GetName(), vol);
975 int copy = node->GetNumber();
976 bool node_is_reflected = is_left_handed(tr);
977 bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class();
978 bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() :
false;
980 if ( mother_is_assembly ) {
987 printout(lvl,
"Geant4Converter",
"+++ Assembly: **** : daughter %s to mother %s",
988 vol->GetName(), mot_vol ? mot_vol->GetName() :
"????");
992 G4LogicalVolume* g4mot =
nullptr;
993 auto volIt =
info.g4Volumes.find(mot_vol);
994 if ( volIt !=
info.g4Volumes.end() ) {
1000 g4mot = (*volIt).second;
1002 else if ( node !=
info.manager->GetTopNode() ) {
1008 TGeoIterator iter(
info.manager->GetTopVolume());
1010 printout(ALWAYS,
"Geant4Converter",
"+++ (SHOULD NOT ENTER HERE) Assembly: no G4 mother: %s org mot: %p",
1011 node->GetName(), mot_vol);
1012 while ( (n1=iter.Next()) ) {
1014 TGeoNode* nmot = iter.GetNode(iter.GetLevel()-1);
1015 TGeoVolume* mmot = nmot->GetVolume();
1016 volIt =
info.g4Volumes.find(mmot);
1017 if ( volIt !=
info.g4Volumes.end() ) {
1020 g4mot = (*volIt).second;
1021 printout(ALWAYS,
"Geant4Converter",
"+++ Assembly: Realigned mother: %s org mot: %p aligned: %p",
1022 path.Data(), mot_vol, mmot);
1031 G4Translate3D trans;
1032 G4Transform3D transform;
1034 transform.getDecomposition(scale, rotate, trans);
1035 if ( node_is_assembly ) {
1040 printout(lvl,
"Geant4Converter",
"++ Assembly: makeImprint: dau:%-12s %s in mother %-12s "
1041 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1042 node->GetName(), node_is_reflected ?
"(REFLECTED)" :
"",
1043 mot_vol ? mot_vol->GetName() :
"<unknown>",
1044 transform.dx(), transform.dy(), transform.dz(),
1045 scale.xx(), scale.yy(), scale.zz());
1048 chain.emplace_back(node);
1050 except(
"Geant4Converter",
1051 "+++ Assembly: %s mother: %s Geant4AssemblyVolume not present!",
1052 node->GetName(), mot_vol ? mot_vol->GetName() :
"<unknown>");
1057 else if ( node !=
info.manager->GetTopNode() &&
nullptr == g4mot ) {
1061 const auto* pv_data = pv.
data();
1062 G4LogicalVolume* g4vol =
info.g4Volumes[vol];
1064 G4PhysicalVolumesPair pvPlaced {
nullptr,
nullptr };
1067 EAxis axis = kUndefined;
1068 double width = 0e0, offset = 0e0;
1069 auto flags = pv_data->params->flags;
1070 auto count = pv_data->params->trafo1D.second;
1071 auto start = pv_data->params->start.Translation().Vect();
1072 auto delta = pv_data->params->trafo1D.first.Translation().Vect();
1075 { axis = kXAxis; width =
delta.X(); offset = start.X(); }
1077 { axis = kYAxis; width =
delta.Y(); offset = start.Y(); }
1079 { axis = kZAxis; width =
delta.Z(); offset = start.Z(); }
1081 except(
"Geant4Converter",
1082 "++ Replication around unknown axis is not implemented. flags: %16X", flags);
1083 printout(INFO,
"Geant4Converter",
"++ Replicate: Axis: %ld Count: %ld offset: %f width: %f",
1084 axis, count, offset, width);
1085 auto* g4pv =
new G4PVReplica(name,
1092 pvPlaced = { g4pv,
nullptr };
1095 G4ReflectionFactory::Instance()->Replicate(name,
1103 auto* g4pv = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1105 for(
auto&
handle : pv_data->params->placements )
1108 else if ( pv_data && pv_data->params ) {
1110 auto* g4pv =
new G4PVParameterised(name,
1116 pvPlaced = { g4pv,
nullptr };
1118 for(
auto&
handle : pv_data->params->placements )
1123 G4ReflectionFactory::Instance()->Place(transform,
1132 "++ Place %svolume %-12s in mother %-12s "
1133 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1134 node_is_reflected ?
"REFLECTED " :
"", _v.
name(),
1135 mot_vol ? mot_vol->GetName() :
"<unknown>",
1136 transform.dx(), transform.dy(), transform.dz(),
1137 scale.xx(), scale.yy(), scale.zz());
1140 if ( node_is_reflected && !pvPlaced.second )
1141 return info.g4Placements[node] = pvPlaced.first;
1142 else if ( !node_is_reflected && !pvPlaced.second )
1143 return info.g4Placements[node] = pvPlaced.first;
1145 if ( node_is_reflected )
1146 return info.g4Placements[node] = pvPlaced.first;
1147 else if ( !node_is_reflected )
1148 return info.g4Placements[node] = pvPlaced.first;
1149 g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1151 info.g4Placements[node] = g4;
1152 printout(ERROR,
"Geant4Converter",
"++ DEAD code. Should not end up here!");
1163 g4 =
new G4Region(region.
name());
1167 throw std::runtime_error(
"G4Region: StoreSecondaries is True, but no explicit threshold set:");
1169 printout(lvl,
"Geant4Converter",
"++ Setting up region: %s", r.
name());
1170 G4UserRegionInformation*
info =
new G4UserRegionInformation();
1174 g4->SetUserInformation(
info);
1176 printout(lvl,
"Geant4Converter",
"++ Converted region settings of:%s.", r.
name());
1177 std::vector < std::string > &limits = r.
limits();
1178 G4ProductionCuts* cuts = 0;
1181 cuts =
new G4ProductionCuts();
1182 cuts->SetProductionCut(r.
cut()*CLHEP::mm/units::mm);
1183 printout(lvl,
"Geant4Converter",
"++ %s: Using default cut: %f [mm]",
1184 r.
name(), r.
cut()*CLHEP::mm/units::mm);
1186 for(
const auto& nam : limits ) {
1190 for (
const auto& c : cts ) {
1192 if ( c.particles ==
"*" ) pid = -1;
1193 else if ( c.particles ==
"e-" ) pid = idxG4ElectronCut;
1194 else if ( c.particles ==
"e+" ) pid = idxG4PositronCut;
1195 else if ( c.particles ==
"e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1196 else if ( c.particles ==
"e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1197 else if ( c.particles ==
"gamma" ) pid = idxG4GammaCut;
1198 else if ( c.particles ==
"proton" ) pid = idxG4ProtonCut;
1199 else throw std::runtime_error(
"G4Region: Invalid production cut particle-type:" + c.particles);
1200 if ( !cuts ) cuts =
new G4ProductionCuts();
1201 if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1202 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4PositronCut);
1203 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4ElectronCut);
1206 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, pid);
1208 printout(lvl,
"Geant4Converter",
"++ %s: Set cut [%s/%d] = %f [mm]",
1209 r.
name(), c.particles.c_str(), pid, c.value*CLHEP::mm/units::mm);
1213 for (
const auto& j : lm ) {
1214 if (nam == j.first->GetName()) {
1215 g4->SetUserLimits(j.second);
1216 printout(lvl,
"Geant4Converter",
"++ %s: Set limits %s to region type %s",
1217 r.
name(), nam.c_str(), j.second->GetType().c_str());
1226 except(
"Geant4Converter",
"++ G4Region: Failed to resolve limitset: " + nam);
1229 if ( cuts ) g4->SetProductionCuts(cuts);
1242 LimitPrint(
const LimitSet& lset) : ls(lset) {}
1245 printout(ALWAYS,
"Geant4Converter",
1246 "+++ LimitSet: Explicit Limit %s.%s applied for particles:",ls.
name(), pref.c_str());
1248 printout(ALWAYS,
"Geant4Converter",
"+++ LimitSet: Particle type: %-18s PDG: %-6d : %f",
1249 p.first->GetParticleName().c_str(), p.first->GetPDGEncoding(), p.second);
1252 printout(ALWAYS,
"Geant4Converter",
1253 "+++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f",
1261 printout(lvl,
"Geant4Converter",
1262 "++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]",
1263 limitset.
name(), limitset.
cuts().size(), limitset.
limits().size());
1265 LimitPrint print(limitset);
1266 print(
"maxTime", limits->
maxTime)
1280 G4VisAttributes* g4 =
info.g4Vis[attr];
1282 float red = 0, green = 0, blue = 0;
1284 attr.
rgb(red, green, blue);
1285 g4 =
new G4VisAttributes(attr.
visible(), G4Colour(red, green, blue, attr.
alpha()));
1289 g4->SetLineStyle(G4VisAttributes::unbroken);
1290 g4->SetForceWireframe(
false);
1291 g4->SetForceSolid(
true);
1294 g4->SetLineStyle(G4VisAttributes::dashed);
1295 g4->SetForceSolid(
false);
1296 g4->SetForceWireframe(
true);
1298 info.g4Vis[attr] = g4;
1305 std::map < std::string, std::string > processors;
1306 static int s_idd = 9999999;
1307 for(
const auto& [nam, vals] : prp ) {
1308 if ( nam.substr(0, 6) ==
"geant4" ) {
1309 auto id_it = vals.find(
"id");
1310 std::string
id = (id_it == vals.end()) ?
_toString(++s_idd,
"%d") : (*id_it).second;
1311 processors.emplace(
id, nam);
1314 for(
const auto& p : processors ) {
1317 auto iter = vals.find(
"type");
1318 if ( iter != vals.end() ) {
1319 std::string type = iter->second;
1320 std::string tag = type +
"_Geant4_action";
1322 long res = PluginService::Create<long>(tag,
det, hdlr, &vals);
1324 throw std::runtime_error(
"Failed to locate plugin to interprete files of type"
1325 " \"" + tag +
"\" - no factory:" + type);
1329 throw std::runtime_error(
"Failed to invoke the plugin " + tag +
" of type " + type);
1331 printout(
outputLevel,
"Geant4Converter",
"+++++ Executed Successfully Geant4 setup module *%s*.", type.c_str());
1334 printout(
outputLevel,
"Geant4Converter",
"+++++ FAILED to execute Geant4 setup module *%s*.", p.second.c_str());
1341 TGDMLMatrix* matrix = (TGDMLMatrix*)mtx;
1342 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1345 if (
nullptr != cptr ) {
1346 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1347 matrix->GetName(), matrix->GetTitle());
1350 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
1351 if (
nullptr != cptr ) {
1352 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1353 matrix->GetName(), matrix->GetTitle());
1360 std::size_t rows = matrix->GetRows();
1361 g4->
name = matrix->GetName();
1362 g4->
title = matrix->GetTitle();
1363 g4->
bins.reserve(rows);
1364 g4->
values.reserve(rows);
1365 for( std::size_t i=0; i<rows; ++i ) {
1366 g4->
bins.emplace_back(matrix->Get(i,0) );
1367 g4->
values.emplace_back(matrix->Get(i,1));
1369 printout(lvl,
"Geant4Converter",
1370 "++ Successfully converted material property:%s : %s [%ld rows]",
1371 matrix->GetName(), matrix->GetTitle(), rows);
1372 info.g4OpticalProperties[matrix] = g4;
1377 static G4OpticalSurfaceFinish geant4_surface_finish(TGeoOpticalSurface::ESurfaceFinish f) {
1378 #define TO_G4_FINISH(x) case TGeoOpticalSurface::kF##x : return x;
1426 printout(ERROR,
"Geant4Surfaces",
"++ Unknown finish style: %d [%s]. Assume polished!",
1427 int(f), TGeoOpticalSurface::FinishToString(f));
1433 static G4SurfaceType geant4_surface_type(TGeoOpticalSurface::ESurfaceType t) {
1434 #define TO_G4_TYPE(x) case TGeoOpticalSurface::kT##x : return x;
1444 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface type: %d [%s]. Assume dielectric_metal!",
1445 int(t), TGeoOpticalSurface::TypeToString(t));
1446 return dielectric_metal;
1451 static G4OpticalSurfaceModel geant4_surface_model(TGeoOpticalSurface::ESurfaceModel surfMod) {
1452 #define TO_G4_MODEL(x) case TGeoOpticalSurface::kM##x : return x;
1460 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface model: %d [%s]. Assume glisur!",
1461 int(surfMod), TGeoOpticalSurface::ModelToString(surfMod));
1469 TGeoOpticalSurface* optSurf = (TGeoOpticalSurface*)surface;
1471 G4OpticalSurface* g4 =
info.g4OpticalSurfaces[optSurf];
1473 G4SurfaceType type = geant4_surface_type(optSurf->GetType());
1474 G4OpticalSurfaceModel model = geant4_surface_model(optSurf->GetModel());
1475 G4OpticalSurfaceFinish finish = geant4_surface_finish(optSurf->GetFinish());
1476 std::string name = make_NCName(optSurf->GetName());
1478 g4 =
new G4OpticalSurface(name, model, finish, type, optSurf->GetValue());
1479 g4->SetSigmaAlpha(optSurf->GetSigmaAlpha());
1480 g4->SetPolish(optSurf->GetPolish());
1482 printout(lvl,
"Geant4Converter",
1483 "++ Created OpticalSurface: %-18s type:%s model:%s finish:%s SigmaAlphs: %.3e Polish: %.3e",
1485 TGeoOpticalSurface::TypeToString(optSurf->GetType()),
1486 TGeoOpticalSurface::ModelToString(optSurf->GetModel()),
1487 TGeoOpticalSurface::FinishToString(optSurf->GetFinish()),
1488 optSurf->GetSigmaAlpha(), optSurf->GetPolish());
1491 G4MaterialPropertiesTable* tab =
nullptr;
1492 TListIter itp(&optSurf->GetProperties());
1493 for(
TObject* obj = itp.Next(); obj; obj = itp.Next()) {
1494 std::string exc_str;
1496 TGDMLMatrix* matrix =
info.manager->GetGDMLMatrix(named->GetTitle());
1497 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1498 if (
nullptr != cptr )
1501 if (
nullptr == tab ) {
1502 tab =
new G4MaterialPropertiesTable();
1503 g4->SetMaterialPropertiesTable(tab);
1509 except(
"Geant4OpticalSurface",
"++ Failed to convert opt.surface %s. Property table %s is not defined!",
1510 optSurf->GetName(), named->GetTitle());
1514 idx = tab->GetPropertyIndex(named->GetName());
1522 printout(ERROR,
"Geant4Converter",
1523 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
1524 exc_str.c_str(), named->GetName());
1528 auto conv = g4PropertyConversion(idx);
1529 std::vector<double> bins(
v->bins), vals(
v->values);
1530 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1531 bins[i] *= conv.first, vals[i] *= conv.second;
1532 G4MaterialPropertyVector* vec =
new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
1533 tab->AddProperty(named->GetName(), vec);
1535 printout(lvl,
"Geant4Converter",
1536 "++ Property: %-20s [%ld x %ld] --> %s",
1537 named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
1538 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1539 printout(lvl, named->GetName(),
1540 " Geant4: %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
1541 bins[i],
v->bins[i], conv.first);
1545 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
1546 TListIter itc(&optSurf->GetConstProperties());
1547 for(
TObject* obj = itc.Next(); obj; obj = itc.Next()) {
1548 std::string exc_str;
1550 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
1551 if (
nullptr != cptr ) {
1552 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1553 named->GetName(), named->GetTitle());
1556 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
1557 if (
nullptr != cptr ) {
1558 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1559 named->GetName(), named->GetTitle());
1562 Bool_t err = kFALSE;
1563 Double_t value =
info.manager->GetProperty(named->GetTitle(),&err);
1564 if ( err != kFALSE ) {
1566 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
1567 optSurf->GetName(), named->GetName());
1569 if (
nullptr == tab ) {
1570 tab =
new G4MaterialPropertiesTable();
1571 g4->SetMaterialPropertiesTable(tab);
1575 idx = tab->GetConstPropertyIndex(named->GetName());
1583 printout(ERROR, name,
1584 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
1585 exc_str.c_str(), named->GetName());
1589 double conv = g4ConstPropertyConversion(idx);
1590 printout(lvl, name,
"++ CONST Property: %-20s %g * %g --> %g ",
1591 named->GetName(), value, conv, value * conv);
1592 tab->AddConstProperty(named->GetName(), value * conv);
1594 #endif // ROOT_VERSION >= 6.31.1
1595 info.g4OpticalSurfaces[optSurf] = g4;
1602 TGeoSkinSurface* surf = (TGeoSkinSurface*)surface;
1604 G4LogicalSkinSurface* g4 =
info.g4SkinSurfaces[surf];
1606 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1607 G4LogicalVolume*
v =
info.g4Volumes[surf->GetVolume()];
1608 std::string name = make_NCName(surf->GetName());
1609 g4 =
new G4LogicalSkinSurface(name,
v, optSurf);
1611 "++ Created SkinSurface: %-18s optical:%s",
1612 surf->GetName(), surf->GetSurface()->GetName());
1613 info.g4SkinSurfaces[surf] = g4;
1620 TGeoBorderSurface* surf = (TGeoBorderSurface*)surface;
1622 G4LogicalBorderSurface* g4 =
info.g4BorderSurfaces[surf];
1624 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1625 G4VPhysicalVolume* n1 =
info.g4Placements[surf->GetNode1()];
1626 G4VPhysicalVolume* n2 =
info.g4Placements[surf->GetNode2()];
1627 std::string name = make_NCName(surf->GetName());
1628 g4 =
new G4LogicalBorderSurface(name, n1, n2, optSurf);
1630 "++ Created BorderSurface: %-18s optical:%s",
1631 surf->GetName(), surf->GetSurface()->GetName());
1632 info.g4BorderSurfaces[surf] = g4;
1640 std::set<const TGeoVolume*>& volset =
info.sensitives[sens_det];
1642 std::stringstream str;
1644 printout(INFO,
"Geant4Converter",
"++ SensitiveDetector: %-18s %-20s Hits:%-16s", sd.
name(), (
"[" + sd.
type() +
"]").c_str(),
1646 str <<
" | " <<
"Cutoff:" << std::setw(6) << std::left
1647 << sd.
energyCutoff() << std::setw(5) << std::right << volset.size()
1650 str <<
" Region:" << std::setw(12) << std::left << sd.
region().
name();
1652 str <<
" Limits:" << std::setw(12) << std::left << sd.
limits().
name();
1654 printout(INFO,
"Geant4Converter", str.str().c_str());
1656 for (
const auto i : volset ) {
1657 std::map<Volume, G4LogicalVolume*>::iterator
v =
info.g4Volumes.find(i);
1658 if (
v !=
info.g4Volumes.end() ) {
1659 G4LogicalVolume* vol = (*v).second;
1661 str <<
" | " <<
"Volume:" << std::setw(24) << std::left << vol->GetName() <<
" "
1662 << vol->GetNoDaughters() <<
" daughters.";
1663 printout(INFO,
"Geant4Converter", str.str().c_str());
1669 std::stringstream str;
1670 if (
typeid(*sol) ==
typeid(G4Box)) {
1671 const G4Box* b = (G4Box*) sol;
1672 str <<
"++ Box: x=" << b->GetXHalfLength() <<
" y=" << b->GetYHalfLength() <<
" z=" << b->GetZHalfLength();
1674 else if (
typeid(*sol) ==
typeid(G4Tubs)) {
1675 const G4Tubs* t = (
const G4Tubs*) sol;
1676 str <<
" Tubs: Ri=" << t->GetInnerRadius() <<
" Ra=" << t->GetOuterRadius() <<
" z/2=" << t->GetZHalfLength() <<
" Phi="
1677 << t->GetStartPhiAngle() <<
"..." << t->GetDeltaPhiAngle();
1685 G4VPhysicalVolume* g4 =
info.g4Placements[node];
1686 G4LogicalVolume* vol =
info.g4Volumes[node->GetVolume()];
1687 G4LogicalVolume* mot =
info.g4Volumes[node->GetMotherVolume()];
1688 G4VSolid* sol = vol->GetSolid();
1689 G4ThreeVector tr = g4->GetObjectTranslation();
1694 std::stringstream str;
1695 str <<
"G4Cnv::placement: + " << name <<
" No:" << node->GetNumber() <<
" Vol:" << vol->GetName() <<
" Solid:"
1697 printout(
outputLevel,
"G4Placement", str.str().c_str());
1699 str <<
" |" <<
" Loc: x=" << tr.x() <<
" y=" << tr.y() <<
" z=" << tr.z();
1700 printout(
outputLevel,
"G4Placement", str.str().c_str());
1703 str <<
" |" <<
" Ndau:" << vol->GetNoDaughters()
1704 <<
" physvols." <<
" Mat:" << vol->GetMaterial()->GetName()
1705 <<
" Mother:" << (
char*) (mot ? mot->GetName().c_str() :
"---");
1706 printout(
outputLevel,
"G4Placement", str.str().c_str());
1708 str <<
" |" <<
" SD:" << sd->GetName();
1709 printout(
outputLevel,
"G4Placement", str.str().c_str());
1715 typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU;
1735 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld solids.", geo.
solids.size());
1737 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld visualization attributes.", geo.
vis.size());
1739 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld limit sets.", geo.
limits.size());
1741 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld regions.", geo.
regions.size());
1743 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld volumes.", geo.
volumes.size());
1747 std::map<int, std::vector<const TGeoNode*> >::const_reverse_iterator i =
m_data->rbegin();
1748 for ( ; i !=
m_data->rend(); ++i ) {
1749 for (
const TGeoNode* node : i->second ) {
1769 printout(INFO,
"Geant4Converter",
1770 "+++ Successfully converted geometry to Geant4. [%7.3f seconds]",
1771 stop.AsDouble()-start.AsDouble() );