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 const auto& pn = tab->GetMaterialPropertyNames();
445 if( std::find(std::begin(pn), std::end(pn), named->GetName()) != pn.end() ) {
446 idx = tab->GetPropertyIndex(named->GetName());
457 printout(ERROR,
"Geant4Converter",
458 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
459 exc_str.c_str(), named->GetName());
463 auto conv = g4PropertyConversion(idx);
464 std::vector<double> bins(
v->bins), vals(
v->values);
465 for(std::size_t i=0, count=bins.size(); i<count; ++i)
466 bins[i] *= conv.first, vals[i] *= conv.second;
468 G4MaterialPropertyVector* vec =
469 new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
470 tab->AddProperty(named->GetName(), vec);
471 printout(lvl, name,
"++ Property: %-20s [%ld x %ld] -> %s ",
472 named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
473 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
474 printout(lvl, name,
" Geant4: %s %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
475 named->GetName(), bins[i],
v->bins[i], conv.first);
479 TListIter cpropIt(&material->GetConstProperties());
480 for(
TObject* obj=cpropIt.Next(); obj; obj = cpropIt.Next()) {
485 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
486 if (
nullptr != cptr ) {
487 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
488 named->GetName(), named->GetTitle());
491 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
492 if (
nullptr != cptr ) {
493 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
494 named->GetName(), named->GetTitle());
497 cptr = ::strstr(named->GetName(), GEANT4_TAG_PLUGIN);
498 if (
nullptr != cptr ) {
499 printout(INFO, name,
"++ Ignore CONST property %s [%s] --> Plugin.",
500 named->GetName(), named->GetTitle());
501 plugin_name = named->GetTitle();
504 cptr = ::strstr(named->GetName(), GEANT4_TAG_BIRKSCONSTANT);
505 if (
nullptr != cptr ) {
507 value = material->GetConstProperty(GEANT4_TAG_BIRKSCONSTANT,&err);
508 if ( err == kFALSE ) ionisation_birks_constant = value * (CLHEP::mm/CLHEP::MeV)/(units::mm/units::MeV);
511 cptr = ::strstr(named->GetName(), GEANT4_TAG_MEE);
512 if (
nullptr != cptr ) {
514 value = material->GetConstProperty(GEANT4_TAG_MEE, &err);
515 if ( err == kFALSE ) ionisation_mee = value * (CLHEP::MeV/units::MeV);
518 cptr = ::strstr(named->GetName(), GEANT4_TAG_ENE_PER_ION_PAIR);
519 if (
nullptr != cptr ) {
521 value = material->GetConstProperty(GEANT4_TAG_ENE_PER_ION_PAIR,&err);
522 if ( err == kFALSE ) ionisation_ene_per_ion_pair = value * (CLHEP::MeV/units::MeV);
527 value =
info.manager->GetProperty(named->GetTitle(), &err);
528 if ( err != kFALSE ) {
530 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
531 material->GetName(), named->GetName());
533 if (
nullptr == tab ) {
534 tab =
new G4MaterialPropertiesTable();
535 mat->SetMaterialPropertiesTable(tab);
539 const auto& pn = tab->GetMaterialConstPropertyNames();
540 if( std::find(std::begin(pn), std::end(pn), named->GetName()) != pn.end() ) {
541 idx = tab->GetConstPropertyIndex(named->GetName());
552 printout(ERROR, name,
553 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
554 exc_str.c_str(), named->GetName());
558 double conv = g4ConstPropertyConversion(idx);
559 printout(lvl, name,
"++ CONST Property: %-20s %g ", named->GetName(), value);
560 tab->AddConstProperty(named->GetName(), value * conv);
564 auto* ionisation = mat->GetIonisation();
565 std::stringstream str;
568 if ( ionisation_birks_constant > 0e0 ) {
569 ionisation->SetBirksConstant(ionisation_birks_constant);
571 if ( ionisation_mee > -1e100 ) {
572 ionisation->SetMeanExcitationEnergy(ionisation_mee);
574 if ( ionisation_ene_per_ion_pair > 0e0 ) {
575 ionisation->SetMeanEnergyPerIonPair(ionisation_ene_per_ion_pair);
577 str <<
" log(MEE): " << std::setprecision(4) << ionisation->GetLogMeanExcEnergy();
578 if ( ionisation_birks_constant > 0e0 )
579 str <<
" Birk's constant: " << std::setprecision(4) << ionisation->GetBirksConstant() <<
" [mm/MeV]";
580 if ( ionisation_ene_per_ion_pair > 0e0 )
581 str <<
" Mean Energy Per Ion Pair: " << std::setprecision(4) << ionisation->GetMeanEnergyPerIonPair()/CLHEP::eV <<
" [eV]";
584 str <<
" No ionisation parameters available.";
586 printout(lvl, name,
"++ Created G4 material %s", str.str().c_str());
588 if ( !plugin_name.empty() ) {
591 G4Material* extended_mat = PluginService::Create<G4Material*>(plugin_name,
det, medium, mat);
592 if ( !extended_mat ) {
593 except(
"G4Cnv::material["+name+
"]",
"++ FATAL Failed to call plugin to create material.");
597 info.g4Materials[medium] = mat;
604 G4VSolid* solid =
nullptr;
606 if (
nullptr != (solid =
data().g4Solids[shape]) ) {
609 TClass* isa = shape->IsA();
611 if (isa == TGeoShapeAssembly::Class()) {
617 else if (isa == TGeoBBox::Class())
619 else if (isa == TGeoTube::Class())
621 else if (isa == TGeoTubeSeg::Class())
623 else if (isa == TGeoCtub::Class())
625 else if (isa == TGeoEltu::Class())
627 else if (isa == TwistedTubeObject::Class())
629 else if (isa == TGeoTrd1::Class())
631 else if (isa == TGeoTrd2::Class())
633 else if (isa == TGeoHype::Class())
635 else if (isa == TGeoXtru::Class())
637 else if (isa == TGeoPgon::Class())
639 else if (isa == TGeoPcon::Class())
641 else if (isa == TGeoCone::Class())
643 else if (isa == TGeoConeSeg::Class())
645 else if (isa == TGeoParaboloid::Class())
647 else if (isa == TGeoSphere::Class())
649 else if (isa == TGeoTorus::Class())
651 else if (isa == TGeoTrap::Class())
653 else if (isa == TGeoArb8::Class())
655 else if (isa == TGeoPara::Class())
657 else if (isa == TGeoTessellated::Class())
659 else if (isa == TGeoScaledShape::Class()) {
660 TGeoScaledShape* sh = (TGeoScaledShape*) shape;
661 TGeoShape* sol = sh->GetShape();
662 if ( sol->IsA() == TGeoShapeAssembly::Class() ) {
665 const double* vals = sh->GetScale()->GetScale();
666 G4Scale3D scal(vals[0], vals[1], vals[2]);
667 G4VSolid* g4solid = (G4VSolid*)
handleSolid(sol->GetName(), sol);
668 if ( scal.xx()>0e0 && scal.yy()>0e0 && scal.zz()>0e0 )
669 solid =
new G4ScaledSolid(sh->GetName(), g4solid, scal);
671 solid =
new G4ReflectedSolid(g4solid->GetName()+
"_refl", g4solid, scal);
673 else if ( isa == TGeoCompositeShape::Class() ) {
674 const TGeoCompositeShape* sh = (
const TGeoCompositeShape*) shape;
675 const TGeoBoolNode*
boolean = sh->GetBoolNode();
676 TGeoBoolNode::EGeoBoolType oper =
boolean->GetBooleanOperator();
677 TGeoMatrix* matrix =
boolean->GetRightMatrix();
678 G4VSolid* left = (G4VSolid*)
handleSolid(name +
"_left", boolean->GetLeftShape());
679 G4VSolid* right = (G4VSolid*)
handleSolid(name +
"_right", boolean->GetRightShape());
682 except(
"Geant4Converter",
"++ No left Geant4 Solid present for composite shape: %s",name.c_str());
685 except(
"Geant4Converter",
"++ No right Geant4 Solid present for composite shape: %s",name.c_str());
688 TGeoShape* ls =
boolean->GetLeftShape();
689 TGeoShape* rs =
boolean->GetRightShape();
690 if (strcmp(ls->ClassName(),
"TGeoScaledShape") == 0 &&
691 strcmp(rs->ClassName(),
"TGeoBBox") == 0) {
692 if (strcmp(((TGeoScaledShape *)ls)->GetShape()->ClassName(),
"TGeoSphere") == 0) {
693 if (oper == TGeoBoolNode::kGeoIntersection) {
694 TGeoScaledShape* lls = (TGeoScaledShape *)ls;
695 TGeoBBox* rrs = (TGeoBBox*)rs;
696 double sx = lls->GetScale()->GetScale()[0];
697 double sy = lls->GetScale()->GetScale()[1];
698 double radius = ((TGeoSphere *)lls->GetShape())->GetRmax();
699 double dz = rrs->GetDZ();
700 double zorig = rrs->GetOrigin()[2];
701 double zcut2 = dz + zorig;
702 double zcut1 = 2 * zorig - zcut2;
703 solid =
new G4Ellipsoid(name,
715 if ( matrix->IsRotation() ) {
716 G4Transform3D transform;
718 if (oper == TGeoBoolNode::kGeoSubtraction)
719 solid =
new G4SubtractionSolid(name, left, right, transform);
720 else if (oper == TGeoBoolNode::kGeoUnion)
721 solid =
new G4UnionSolid(name, left, right, transform);
722 else if (oper == TGeoBoolNode::kGeoIntersection)
723 solid =
new G4IntersectionSolid(name, left, right, transform);
726 const Double_t *t = matrix->GetTranslation();
728 if (oper == TGeoBoolNode::kGeoSubtraction)
729 solid =
new G4SubtractionSolid(name, left, right, 0, transform);
730 else if (oper == TGeoBoolNode::kGeoUnion)
731 solid =
new G4UnionSolid(name, left, right, 0, transform);
732 else if (oper == TGeoBoolNode::kGeoIntersection)
733 solid =
new G4IntersectionSolid(name, left, right, 0, transform);
738 except(
"Geant4Converter",
"++ Failed to handle unknown solid shape: %s of type %s",
739 name.c_str(), isa->GetName());
740 printout(lvl,
"Geant4Converter",
"++ Successessfully converted shape [%p] of type:%s to %s.",
741 solid,isa->GetName(),typeName(
typeid(*solid)).c_str());
752 Geant4GeometryMaps::VolumeMap::const_iterator volIt =
info.g4Volumes.find(volume);
754 printout(lvl,
"Geant4Converter",
755 "++ Volume %s not converted [Veto'ed for simulation]",
759 else if (volIt ==
info.g4Volumes.end() ) {
760 const char* vnam = volume->GetName();
761 TGeoMedium* med = volume->GetMedium();
762 Solid sh = volume->GetShape();
763 bool is_assembly = sh->IsA() == TGeoShapeAssembly::Class() || volume->IsAssembly();
765 printout(lvl,
"Geant4Converter",
"++ Convert Volume %-32s: %p %s/%s assembly:%s",
766 vnam, volume, sh.
type(), _v.
type(), yes_no(is_assembly));
773 G4Region* g4region = reg.
isValid() ?
info.g4Regions[reg] :
nullptr;
775 G4VSolid* g4solid = (G4VSolid*)
handleSolid(sh->GetName(), sh);
779 except(
"G4Converter",
"++ No Geant4 Solid present for volume: %s", vnam);
781 else if ( !g4medium ) {
782 except(
"G4Converter",
"++ No Geant4 material present for volume: %s", vnam);
784 else if ( reg.
isValid() && !g4region ) {
785 except(
"G4Cnv::volume["+name+
"]",
" ++ Failed to access Geant4 region %s.", reg.
name());
787 else if ( lim.
isValid() && !g4limits ) {
788 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to access Geant4 user limits %s.", lim.
name());
790 else if ( g4limits ) {
791 printout(lvl,
"Geant4Converter",
"++ Volume + Apply LIMITS settings: %-24s to volume %s.",
795 G4LogicalVolume* g4vol =
nullptr;
798 std::string plugin = _v.
getProperty(GEANT4_TAG_PLUGIN,
"");
799 g4vol = PluginService::Create<G4LogicalVolume*>(plugin,
det, _v, g4solid, g4medium);
801 except(
"G4Cnv::volume["+name+
"]",
"++ FATAL Failed to call plugin to create logical volume.");
805 g4vol =
new G4LogicalVolume(g4solid, g4medium, vnam,
nullptr,
nullptr,
nullptr);
811 printout(ALWAYS,
"Geant4Converter",
812 "++ Volume %s Set Smartless value to %d",
813 vnam,
int(smart_less_value));
814 g4vol->SetSmartless( smart_less_value );
818 g4vol->SetUserLimits(g4limits);
821 printout(plevel,
"Geant4Converter",
822 "++ Volume + Apply REGION settings: %-24s to volume %s.",
828 const char* wrd_nam =
"DefaultRegionForTheWorld";
829 const char* src_nam = g4region->GetName().c_str();
830 auto* world_region = G4RegionStore::GetInstance()->GetRegion(wrd_nam,
false);
831 if (
auto* cuts = g4region->GetProductionCuts() ) {
832 world_region->SetProductionCuts(cuts);
833 printout(plevel,
"Geant4Converter",
834 "++ Volume %s Region: %s. Apply production cuts from %s",
835 vnam, wrd_nam, src_nam);
837 if (
auto* lims = g4region->GetUserLimits() ) {
838 world_region->SetUserLimits(lims);
839 printout(plevel,
"Geant4Converter",
840 "++ Volume %s Region: %s. Apply user limits from %s",
841 vnam, wrd_nam, src_nam);
845 g4vol->SetRegion(g4region);
846 g4region->AddRootLogicalVolume(g4vol);
849 G4VisAttributes* g4vattr = vis.
isValid()
852 g4vol->SetVisAttributes(g4vattr);
854 info.g4Volumes[volume] = g4vol;
855 printout(lvl,
"Geant4Converter",
856 "++ Volume + %s converted: %p ---> G4: %p", vnam, volume, g4vol);
872 info.limits[lim].insert(volume);
874 info.regions[reg].insert(volume);
876 info.sensitives[
det].insert(volume);
878 return (
void*)volume;
883 TGeoVolume* mot_vol = node->GetVolume();
885 if ( mot_vol->IsA() != TGeoVolumeAssembly::Class() ) {
890 printout(lvl,
"Geant4Converter",
"++ AssemblyNode %s not converted [Veto'ed for simulation]",node->GetName());
896 printout(ALWAYS,
"Geant4Converter",
"+++ Assembly: **** : Re-using existing assembly: %s",node->GetName());
900 for(Int_t i=0; i < mot_vol->GetNdaughters(); ++i) {
901 TGeoNode* dau = mot_vol->GetNode(i);
902 TGeoVolume* dau_vol = dau->GetVolume();
903 TGeoMatrix* tr = dau->GetMatrix();
904 G4Transform3D transform;
907 if ( is_left_handed(tr) ) {
911 transform.getDecomposition(scale, rot, trans);
913 "++ Placing reflected ASSEMBLY. dau:%s to mother %s "
914 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
915 dau_vol->GetName(), mot_vol->GetName(),
916 transform.dx(), transform.dy(), transform.dz(),
917 scale.xx(), scale.yy(), scale.zz());
920 if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) {
921 Geant4GeometryMaps::AssemblyMap::iterator ia =
info.g4AssemblyVolumes.find(dau);
922 if ( ia ==
info.g4AssemblyVolumes.end() ) {
923 printout(FATAL,
"Geant4Converter",
"+++ Invalid child assembly at %s : %d parent: %s child:%s",
924 __FILE__, __LINE__, name.c_str(), dau->GetName());
929 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedAssembly %p: dau:%s "
930 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
931 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
932 transform.dx(), transform.dy(), transform.dz());
935 Geant4GeometryMaps::VolumeMap::iterator iv =
info.g4Volumes.find(dau_vol);
936 if ( iv ==
info.g4Volumes.end() ) {
937 printout(FATAL,
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
938 __FILE__, __LINE__, name.c_str(), dau->GetName());
939 except(
"Geant4Converter",
"+++ Invalid child volume at %s : %d parent: %s child:%s",
940 __FILE__, __LINE__, name.c_str(), dau->GetName());
943 printout(lvl,
"Geant4Converter",
"+++ Assembly: AddPlacedVolume %p: dau:%s "
944 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
945 (
void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
946 transform.dx(), transform.dy(), transform.dz());
949 info.g4AssemblyVolumes[node] = g4;
958 Geant4GeometryMaps::PlacementMap::const_iterator g4it =
info.g4Placements.find(node);
959 G4VPhysicalVolume* g4 = (g4it ==
info.g4Placements.end()) ? 0 : (*g4it).second;
960 TGeoVolume* vol = node->GetVolume();
964 printout(lvl,
"Geant4Converter",
"++ Placement %s not converted [Veto'ed for simulation]",node->GetName());
969 TGeoVolume* mot_vol = node->GetMotherVolume();
970 TGeoMatrix* tr = node->GetMatrix();
972 except(
"Geant4Converter",
973 "++ Attempt to handle placement without transformation:%p %s of type %s vol:%p",
974 node, node->GetName(), node->IsA()->GetName(), vol);
976 else if (
nullptr == vol) {
977 except(
"Geant4Converter",
"++ Unknown G4 volume:%p %s of type %s ptr:%p",
978 node, node->GetName(), node->IsA()->GetName(), vol);
981 int copy = node->GetNumber();
982 bool node_is_reflected = is_left_handed(tr);
983 bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class();
984 bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() :
false;
986 if ( mother_is_assembly ) {
993 printout(lvl,
"Geant4Converter",
"+++ Assembly: **** : daughter %s to mother %s",
994 vol->GetName(), mot_vol ? mot_vol->GetName() :
"????");
998 G4LogicalVolume* g4mot =
nullptr;
999 auto volIt =
info.g4Volumes.find(mot_vol);
1000 if ( volIt !=
info.g4Volumes.end() ) {
1006 g4mot = (*volIt).second;
1008 else if ( node !=
info.manager->GetTopNode() ) {
1014 TGeoIterator iter(
info.manager->GetTopVolume());
1016 printout(ALWAYS,
"Geant4Converter",
"+++ (SHOULD NOT ENTER HERE) Assembly: no G4 mother: %s org mot: %p",
1017 node->GetName(), mot_vol);
1018 while ( (n1=iter.Next()) ) {
1020 TGeoNode* nmot = iter.GetNode(iter.GetLevel()-1);
1021 TGeoVolume* mmot = nmot->GetVolume();
1022 volIt =
info.g4Volumes.find(mmot);
1023 if ( volIt !=
info.g4Volumes.end() ) {
1026 g4mot = (*volIt).second;
1027 printout(ALWAYS,
"Geant4Converter",
"+++ Assembly: Realigned mother: %s org mot: %p aligned: %p",
1028 path.Data(), mot_vol, mmot);
1037 G4Translate3D trans;
1038 G4Transform3D transform;
1040 transform.getDecomposition(scale, rotate, trans);
1041 if ( node_is_assembly ) {
1046 printout(lvl,
"Geant4Converter",
"++ Assembly: makeImprint: dau:%-12s %s in mother %-12s "
1047 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1048 node->GetName(), node_is_reflected ?
"(REFLECTED)" :
"",
1049 mot_vol ? mot_vol->GetName() :
"<unknown>",
1050 transform.dx(), transform.dy(), transform.dz(),
1051 scale.xx(), scale.yy(), scale.zz());
1054 chain.emplace_back(node);
1056 except(
"Geant4Converter",
1057 "+++ Assembly: %s mother: %s Geant4AssemblyVolume not present!",
1058 node->GetName(), mot_vol ? mot_vol->GetName() :
"<unknown>");
1063 else if ( node !=
info.manager->GetTopNode() &&
nullptr == g4mot ) {
1067 const auto* pv_data = pv.
data();
1068 G4LogicalVolume* g4vol =
info.g4Volumes[vol];
1070 G4PhysicalVolumesPair pvPlaced {
nullptr,
nullptr };
1073 EAxis axis = kUndefined;
1074 double width = 0e0, offset = 0e0;
1075 auto flags = pv_data->params->flags;
1076 auto count = pv_data->params->trafo1D.second;
1077 auto start = pv_data->params->start.Translation().Vect();
1078 auto delta = pv_data->params->trafo1D.first.Translation().Vect();
1081 { axis = kXAxis; width =
delta.X(); offset = start.X(); }
1083 { axis = kYAxis; width =
delta.Y(); offset = start.Y(); }
1085 { axis = kZAxis; width =
delta.Z(); offset = start.Z(); }
1087 except(
"Geant4Converter",
1088 "++ Replication around unknown axis is not implemented. flags: %16X", flags);
1089 printout(INFO,
"Geant4Converter",
"++ Replicate: Axis: %ld Count: %ld offset: %f width: %f",
1090 axis, count, offset, width);
1091 auto* g4pv =
new G4PVReplica(name,
1098 pvPlaced = { g4pv,
nullptr };
1101 G4ReflectionFactory::Instance()->Replicate(name,
1109 auto* g4pv = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1111 for(
auto& handle : pv_data->params->placements )
1112 info.g4Placements[handle.ptr()] = g4pv;
1114 else if ( pv_data && pv_data->params ) {
1116 auto* g4pv =
new G4PVParameterised(name,
1122 pvPlaced = { g4pv,
nullptr };
1124 for(
auto& handle : pv_data->params->placements )
1125 info.g4Placements[handle.ptr()] = g4pv;
1129 G4ReflectionFactory::Instance()->Place(transform,
1138 "++ Place %svolume %-12s in mother %-12s "
1139 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1140 node_is_reflected ?
"REFLECTED " :
"", _v.
name(),
1141 mot_vol ? mot_vol->GetName() :
"<unknown>",
1142 transform.dx(), transform.dy(), transform.dz(),
1143 scale.xx(), scale.yy(), scale.zz());
1146 if ( node_is_reflected && !pvPlaced.second )
1147 return info.g4Placements[node] = pvPlaced.first;
1148 else if ( !node_is_reflected && !pvPlaced.second )
1149 return info.g4Placements[node] = pvPlaced.first;
1151 if ( node_is_reflected )
1152 return info.g4Placements[node] = pvPlaced.first;
1153 else if ( !node_is_reflected )
1154 return info.g4Placements[node] = pvPlaced.first;
1155 g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1157 info.g4Placements[node] = g4;
1158 printout(ERROR,
"Geant4Converter",
"++ DEAD code. Should not end up here!");
1169 g4 =
new G4Region(region.
name());
1173 throw std::runtime_error(
"G4Region: StoreSecondaries is True, but no explicit threshold set:");
1175 printout(lvl,
"Geant4Converter",
"++ Setting up region: %s", r.
name());
1176 G4UserRegionInformation*
info =
new G4UserRegionInformation();
1180 g4->SetUserInformation(
info);
1182 printout(lvl,
"Geant4Converter",
"++ Converted region settings of:%s.", r.
name());
1183 std::vector < std::string > &limits = r.
limits();
1184 G4ProductionCuts* cuts = 0;
1187 cuts =
new G4ProductionCuts();
1188 cuts->SetProductionCut(r.
cut()*CLHEP::mm/units::mm);
1189 printout(lvl,
"Geant4Converter",
"++ %s: Using default cut: %f [mm]",
1190 r.
name(), r.
cut()*CLHEP::mm/units::mm);
1192 for(
const auto& nam : limits ) {
1196 for (
const auto& c : cts ) {
1198 if ( c.particles ==
"*" ) pid = -1;
1199 else if ( c.particles ==
"e-" ) pid = idxG4ElectronCut;
1200 else if ( c.particles ==
"e+" ) pid = idxG4PositronCut;
1201 else if ( c.particles ==
"e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1202 else if ( c.particles ==
"e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1203 else if ( c.particles ==
"gamma" ) pid = idxG4GammaCut;
1204 else if ( c.particles ==
"proton" ) pid = idxG4ProtonCut;
1205 else throw std::runtime_error(
"G4Region: Invalid production cut particle-type:" + c.particles);
1206 if ( !cuts ) cuts =
new G4ProductionCuts();
1207 if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1208 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4PositronCut);
1209 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4ElectronCut);
1212 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, pid);
1214 printout(lvl,
"Geant4Converter",
"++ %s: Set cut [%s/%d] = %f [mm]",
1215 r.
name(), c.particles.c_str(), pid, c.value*CLHEP::mm/units::mm);
1219 for (
const auto& j : lm ) {
1220 if (nam == j.first->GetName()) {
1221 g4->SetUserLimits(j.second);
1222 printout(lvl,
"Geant4Converter",
"++ %s: Set limits %s to region type %s",
1223 r.
name(), nam.c_str(), j.second->GetType().c_str());
1232 except(
"Geant4Converter",
"++ G4Region: Failed to resolve limitset: " + nam);
1235 if ( cuts ) g4->SetProductionCuts(cuts);
1248 LimitPrint(
const LimitSet& lset) : ls(lset) {}
1251 printout(ALWAYS,
"Geant4Converter",
1252 "+++ LimitSet: Explicit Limit %s.%s applied for particles:",ls.
name(), pref.c_str());
1254 printout(ALWAYS,
"Geant4Converter",
"+++ LimitSet: Particle type: %-18s PDG: %-6d : %f",
1255 p.first->GetParticleName().c_str(), p.first->GetPDGEncoding(), p.second);
1258 printout(ALWAYS,
"Geant4Converter",
1259 "+++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f",
1267 printout(lvl,
"Geant4Converter",
1268 "++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]",
1269 limitset.
name(), limitset.
cuts().size(), limitset.
limits().size());
1271 LimitPrint print(limitset);
1272 print(
"maxTime", limits->
maxTime)
1286 G4VisAttributes* g4 =
info.g4Vis[attr];
1288 float red = 0, green = 0, blue = 0;
1290 attr.
rgb(red, green, blue);
1291 g4 =
new G4VisAttributes(attr.
visible(), G4Colour(red, green, blue, attr.
alpha()));
1295 g4->SetLineStyle(G4VisAttributes::unbroken);
1296 g4->SetForceWireframe(
false);
1297 g4->SetForceSolid(
true);
1300 g4->SetLineStyle(G4VisAttributes::dashed);
1301 g4->SetForceSolid(
false);
1302 g4->SetForceWireframe(
true);
1304 info.g4Vis[attr] = g4;
1311 std::map < std::string, std::string > processors;
1312 static int s_idd = 9999999;
1313 for(
const auto& [nam, vals] : prp ) {
1314 if ( nam.substr(0, 6) ==
"geant4" ) {
1315 auto id_it = vals.find(
"id");
1316 std::string
id = (id_it == vals.end()) ?
_toString(++s_idd,
"%d") : (*id_it).second;
1317 processors.emplace(
id, nam);
1320 for(
const auto& p : processors ) {
1323 auto iter = vals.find(
"type");
1324 if ( iter != vals.end() ) {
1325 std::string type = iter->second;
1326 std::string tag = type +
"_Geant4_action";
1328 long res = PluginService::Create<long>(tag,
det, hdlr, &vals);
1330 throw std::runtime_error(
"Failed to locate plugin to interprete files of type"
1331 " \"" + tag +
"\" - no factory:" + type);
1335 throw std::runtime_error(
"Failed to invoke the plugin " + tag +
" of type " + type);
1337 printout(
outputLevel,
"Geant4Converter",
"+++++ Executed Successfully Geant4 setup module *%s*.", type.c_str());
1340 printout(
outputLevel,
"Geant4Converter",
"+++++ FAILED to execute Geant4 setup module *%s*.", p.second.c_str());
1347 TGDMLMatrix* matrix = (TGDMLMatrix*)mtx;
1348 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1351 if (
nullptr != cptr ) {
1352 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1353 matrix->GetName(), matrix->GetTitle());
1356 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
1357 if (
nullptr != cptr ) {
1358 printout(INFO,
"Geant4MaterialProperties",
"++ Ignore property %s [%s].",
1359 matrix->GetName(), matrix->GetTitle());
1366 std::size_t rows = matrix->GetRows();
1367 g4->
name = matrix->GetName();
1368 g4->
title = matrix->GetTitle();
1369 g4->
bins.reserve(rows);
1370 g4->
values.reserve(rows);
1371 for( std::size_t i=0; i<rows; ++i ) {
1372 g4->
bins.emplace_back(matrix->Get(i,0) );
1373 g4->
values.emplace_back(matrix->Get(i,1));
1375 printout(lvl,
"Geant4Converter",
1376 "++ Successfully converted material property:%s : %s [%ld rows]",
1377 matrix->GetName(), matrix->GetTitle(), rows);
1378 info.g4OpticalProperties[matrix] = g4;
1383 static G4OpticalSurfaceFinish geant4_surface_finish(TGeoOpticalSurface::ESurfaceFinish f) {
1384 #define TO_G4_FINISH(x) case TGeoOpticalSurface::kF##x : return x;
1432 printout(ERROR,
"Geant4Surfaces",
"++ Unknown finish style: %d [%s]. Assume polished!",
1433 int(f), TGeoOpticalSurface::FinishToString(f));
1439 static G4SurfaceType geant4_surface_type(TGeoOpticalSurface::ESurfaceType t) {
1440 #define TO_G4_TYPE(x) case TGeoOpticalSurface::kT##x : return x;
1450 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface type: %d [%s]. Assume dielectric_metal!",
1451 int(t), TGeoOpticalSurface::TypeToString(t));
1452 return dielectric_metal;
1457 static G4OpticalSurfaceModel geant4_surface_model(TGeoOpticalSurface::ESurfaceModel surfMod) {
1458 #define TO_G4_MODEL(x) case TGeoOpticalSurface::kM##x : return x;
1466 printout(ERROR,
"Geant4Surfaces",
"++ Unknown surface model: %d [%s]. Assume glisur!",
1467 int(surfMod), TGeoOpticalSurface::ModelToString(surfMod));
1475 TGeoOpticalSurface* optSurf = (TGeoOpticalSurface*)surface;
1477 G4OpticalSurface* g4 =
info.g4OpticalSurfaces[optSurf];
1479 G4SurfaceType type = geant4_surface_type(optSurf->GetType());
1480 G4OpticalSurfaceModel model = geant4_surface_model(optSurf->GetModel());
1481 G4OpticalSurfaceFinish finish = geant4_surface_finish(optSurf->GetFinish());
1482 std::string name = make_NCName(optSurf->GetName());
1484 g4 =
new G4OpticalSurface(name, model, finish, type, optSurf->GetValue());
1485 g4->SetSigmaAlpha(optSurf->GetSigmaAlpha());
1486 g4->SetPolish(optSurf->GetPolish());
1488 printout(lvl,
"Geant4Converter",
1489 "++ Created OpticalSurface: %-18s type:%s model:%s finish:%s SigmaAlphs: %.3e Polish: %.3e",
1491 TGeoOpticalSurface::TypeToString(optSurf->GetType()),
1492 TGeoOpticalSurface::ModelToString(optSurf->GetModel()),
1493 TGeoOpticalSurface::FinishToString(optSurf->GetFinish()),
1494 optSurf->GetSigmaAlpha(), optSurf->GetPolish());
1497 G4MaterialPropertiesTable* tab =
nullptr;
1498 TListIter itp(&optSurf->GetProperties());
1499 for(
TObject* obj = itp.Next(); obj; obj = itp.Next()) {
1500 std::string exc_str;
1502 TGDMLMatrix* matrix =
info.manager->GetGDMLMatrix(named->GetTitle());
1503 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1504 if (
nullptr != cptr )
1507 if (
nullptr == tab ) {
1508 tab =
new G4MaterialPropertiesTable();
1509 g4->SetMaterialPropertiesTable(tab);
1515 except(
"Geant4OpticalSurface",
"++ Failed to convert opt.surface %s. Property table %s is not defined!",
1516 optSurf->GetName(), named->GetTitle());
1520 idx = tab->GetPropertyIndex(named->GetName());
1528 printout(ERROR,
"Geant4Converter",
1529 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
1530 exc_str.c_str(), named->GetName());
1534 auto conv = g4PropertyConversion(idx);
1535 std::vector<double> bins(
v->bins), vals(
v->values);
1536 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1537 bins[i] *= conv.first, vals[i] *= conv.second;
1538 G4MaterialPropertyVector* vec =
new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
1539 tab->AddProperty(named->GetName(), vec);
1541 printout(lvl,
"Geant4Converter",
1542 "++ Property: %-20s [%ld x %ld] --> %s",
1543 named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
1544 for(std::size_t i=0, count=
v->bins.size(); i<count; ++i)
1545 printout(lvl, named->GetName(),
1546 " Geant4: %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
1547 bins[i],
v->bins[i], conv.first);
1551 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
1552 TListIter itc(&optSurf->GetConstProperties());
1553 for(
TObject* obj = itc.Next(); obj; obj = itc.Next()) {
1554 std::string exc_str;
1556 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
1557 if (
nullptr != cptr ) {
1558 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1559 named->GetName(), named->GetTitle());
1562 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
1563 if (
nullptr != cptr ) {
1564 printout(INFO, name,
"++ Ignore CONST property %s [%s].",
1565 named->GetName(), named->GetTitle());
1568 Bool_t err = kFALSE;
1569 Double_t value =
info.manager->GetProperty(named->GetTitle(),&err);
1570 if ( err != kFALSE ) {
1572 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
1573 optSurf->GetName(), named->GetName());
1575 if (
nullptr == tab ) {
1576 tab =
new G4MaterialPropertiesTable();
1577 g4->SetMaterialPropertiesTable(tab);
1581 idx = tab->GetConstPropertyIndex(named->GetName());
1589 printout(ERROR, name,
1590 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
1591 exc_str.c_str(), named->GetName());
1595 double conv = g4ConstPropertyConversion(idx);
1596 printout(lvl, name,
"++ CONST Property: %-20s %g * %g --> %g ",
1597 named->GetName(), value, conv, value * conv);
1598 tab->AddConstProperty(named->GetName(), value * conv);
1600 #endif // ROOT_VERSION >= 6.31.1
1601 info.g4OpticalSurfaces[optSurf] = g4;
1608 TGeoSkinSurface* surf = (TGeoSkinSurface*)surface;
1610 G4LogicalSkinSurface* g4 =
info.g4SkinSurfaces[surf];
1612 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1613 G4LogicalVolume*
v =
info.g4Volumes[surf->GetVolume()];
1614 std::string name = make_NCName(surf->GetName());
1615 g4 =
new G4LogicalSkinSurface(name,
v, optSurf);
1617 "++ Created SkinSurface: %-18s optical:%s",
1618 surf->GetName(), surf->GetSurface()->GetName());
1619 info.g4SkinSurfaces[surf] = g4;
1626 TGeoBorderSurface* surf = (TGeoBorderSurface*)surface;
1628 G4LogicalBorderSurface* g4 =
info.g4BorderSurfaces[surf];
1630 G4OpticalSurface* optSurf =
info.g4OpticalSurfaces[
OpticalSurface(surf->GetSurface())];
1631 G4VPhysicalVolume* n1 =
info.g4Placements[surf->GetNode1()];
1632 G4VPhysicalVolume* n2 =
info.g4Placements[surf->GetNode2()];
1633 std::string name = make_NCName(surf->GetName());
1634 g4 =
new G4LogicalBorderSurface(name, n1, n2, optSurf);
1636 "++ Created BorderSurface: %-18s optical:%s",
1637 surf->GetName(), surf->GetSurface()->GetName());
1638 info.g4BorderSurfaces[surf] = g4;
1646 std::set<const TGeoVolume*>& volset =
info.sensitives[sens_det];
1648 std::stringstream str;
1650 printout(INFO,
"Geant4Converter",
"++ SensitiveDetector: %-18s %-20s Hits:%-16s", sd.
name(), (
"[" + sd.
type() +
"]").c_str(),
1652 str <<
" | " <<
"Cutoff:" << std::setw(6) << std::left
1653 << sd.
energyCutoff() << std::setw(5) << std::right << volset.size()
1656 str <<
" Region:" << std::setw(12) << std::left << sd.
region().
name();
1658 str <<
" Limits:" << std::setw(12) << std::left << sd.
limits().
name();
1660 printout(INFO,
"Geant4Converter", str.str().c_str());
1662 for (
const auto i : volset ) {
1663 std::map<Volume, G4LogicalVolume*>::iterator
v =
info.g4Volumes.find(i);
1664 if (
v !=
info.g4Volumes.end() ) {
1665 G4LogicalVolume* vol = (*v).second;
1667 str <<
" | " <<
"Volume:" << std::setw(24) << std::left << vol->GetName() <<
" "
1668 << vol->GetNoDaughters() <<
" daughters.";
1669 printout(INFO,
"Geant4Converter", str.str().c_str());
1675 std::stringstream str;
1676 if (
typeid(*sol) ==
typeid(G4Box)) {
1677 const G4Box* b = (G4Box*) sol;
1678 str <<
"++ Box: x=" << b->GetXHalfLength() <<
" y=" << b->GetYHalfLength() <<
" z=" << b->GetZHalfLength();
1680 else if (
typeid(*sol) ==
typeid(G4Tubs)) {
1681 const G4Tubs* t = (
const G4Tubs*) sol;
1682 str <<
" Tubs: Ri=" << t->GetInnerRadius() <<
" Ra=" << t->GetOuterRadius() <<
" z/2=" << t->GetZHalfLength() <<
" Phi="
1683 << t->GetStartPhiAngle() <<
"..." << t->GetDeltaPhiAngle();
1691 G4VPhysicalVolume* g4 =
info.g4Placements[node];
1692 G4LogicalVolume* vol =
info.g4Volumes[node->GetVolume()];
1693 G4LogicalVolume* mot =
info.g4Volumes[node->GetMotherVolume()];
1694 G4VSolid* sol = vol->GetSolid();
1695 G4ThreeVector tr = g4->GetObjectTranslation();
1700 std::stringstream str;
1701 str <<
"G4Cnv::placement: + " << name <<
" No:" << node->GetNumber() <<
" Vol:" << vol->GetName() <<
" Solid:"
1703 printout(
outputLevel,
"G4Placement", str.str().c_str());
1705 str <<
" |" <<
" Loc: x=" << tr.x() <<
" y=" << tr.y() <<
" z=" << tr.z();
1706 printout(
outputLevel,
"G4Placement", str.str().c_str());
1709 str <<
" |" <<
" Ndau:" << vol->GetNoDaughters()
1710 <<
" physvols." <<
" Mat:" << vol->GetMaterial()->GetName()
1711 <<
" Mother:" << (
char*) (mot ? mot->GetName().c_str() :
"---");
1712 printout(
outputLevel,
"G4Placement", str.str().c_str());
1714 str <<
" |" <<
" SD:" << sd->GetName();
1715 printout(
outputLevel,
"G4Placement", str.str().c_str());
1721 typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU;
1741 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld solids.", geo.
solids.size());
1743 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld visualization attributes.", geo.
vis.size());
1745 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld limit sets.", geo.
limits.size());
1747 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld regions.", geo.
regions.size());
1749 printout(
outputLevel,
"Geant4Converter",
"++ Handled %ld volumes.", geo.
volumes.size());
1753 std::map<int, std::vector<const TGeoNode*> >::const_reverse_iterator i =
m_data->rbegin();
1754 for ( ; i !=
m_data->rend(); ++i ) {
1755 for (
const TGeoNode* node : i->second ) {
1775 printout(INFO,
"Geant4Converter",
1776 "+++ Successfully converted geometry to Geant4. [%7.3f seconds]",
1777 stop.AsDouble()-start.AsDouble() );