38 #include <Geant4/G4DisplacedSolid.hh>
39 #include <Geant4/G4LogicalBorderSurface.hh>
40 #include <Geant4/G4LogicalSkinSurface.hh>
41 #include <Geant4/G4LogicalVolumeStore.hh>
42 #include <Geant4/G4Material.hh>
43 #include <Geant4/G4OpticalSurface.hh>
44 #include <Geant4/G4PVDivision.hh>
45 #include <Geant4/G4PVReplica.hh>
46 #include <Geant4/G4PhysicalVolumeStore.hh>
47 #include <Geant4/G4ReflectedSolid.hh>
48 #include <Geant4/G4ReflectionFactory.hh>
49 #include <Geant4/G4Region.hh>
51 #include <Geant4/G4Electron.hh>
52 #include <Geant4/G4Gamma.hh>
53 #include <Geant4/G4Positron.hh>
54 #include <Geant4/G4ProductionCuts.hh>
55 #include <Geant4/G4ProductionCutsTable.hh>
56 #include <Geant4/G4Proton.hh>
57 #include <Geant4/G4Version.hh>
63 , structureElement(nullptr)
76 const G4PVDivision*
const divisionvol)
78 EAxis axis = kUndefined;
82 G4bool consuming =
false;
84 divisionvol->GetReplicationData(axis, number, width, offset, consuming);
85 axis = divisionvol->GetDivisionAxis();
87 G4String unitString(
"mm");
88 G4String axisString(
"kUndefined");
91 axisString =
"kXAxis";
93 else if (axis == kYAxis)
95 axisString =
"kYAxis";
97 else if (axis == kZAxis)
99 axisString =
"kZAxis";
101 else if (axis == kRho)
105 else if (axis == kPhi)
112 const G4String volumeref =
GenerateName(divisionvol->GetLogicalVolume()->GetName(),
113 divisionvol->GetLogicalVolume());
115 xercesc::DOMElement* divisionvolElement =
NewElement(
"divisionvol");
116 divisionvolElement->setAttributeNode(
NewAttribute(
"axis", axisString));
117 divisionvolElement->setAttributeNode(
NewAttribute(
"number", number));
118 divisionvolElement->setAttributeNode(
NewAttribute(
"width", width));
119 divisionvolElement->setAttributeNode(
NewAttribute(
"offset", offset));
120 divisionvolElement->setAttributeNode(
NewAttribute(
"unit", unitString));
121 xercesc::DOMElement* volumerefElement =
NewElement(
"volumeref");
122 volumerefElement->setAttributeNode(
NewAttribute(
"ref", volumeref));
123 divisionvolElement->appendChild(volumerefElement);
124 volumeElement->appendChild(divisionvolElement);
129 const G4Transform3D&
T,
130 const G4String& ModuleName)
132 HepGeom::Scale3D scale;
133 HepGeom::Rotate3D rotate;
134 HepGeom::Translate3D translate;
136 T.getDecomposition(scale, rotate, translate);
138 const G4ThreeVector scl(scale(0, 0), scale(1, 1), scale(2, 2));
139 const G4ThreeVector rot =
GetAngles(rotate.getRotation());
140 const G4ThreeVector
pos = T.getTranslation();
143 const G4int copynumber = physvol->GetCopyNo();
145 xercesc::DOMElement* physvolElement =
NewElement(
"physvol");
146 physvolElement->setAttributeNode(
NewAttribute(
"name", name));
147 if (copynumber) physvolElement->setAttributeNode(
NewAttribute(
"copynumber", copynumber));
149 volumeElement->appendChild(physvolElement);
153 if (
reflFactory->IsReflected(physvol->GetLogicalVolume()))
155 lv =
reflFactory->GetConstituentLV(physvol->GetLogicalVolume());
159 lv = physvol->GetLogicalVolume();
162 const G4String volumeref =
GenerateName(lv->GetName(), lv);
164 if (ModuleName.empty())
166 xercesc::DOMElement* volumerefElement =
NewElement(
"volumeref");
167 volumerefElement->setAttributeNode(
NewAttribute(
"ref", volumeref));
168 physvolElement->appendChild(volumerefElement);
172 xercesc::DOMElement* fileElement =
NewElement(
"file");
173 fileElement->setAttributeNode(
NewAttribute(
"name", ModuleName));
174 fileElement->setAttributeNode(
NewAttribute(
"volname", volumeref));
175 physvolElement->appendChild(fileElement);
188 ScaleWrite(physvolElement, name +
"_scl", scl);
195 EAxis axis = kUndefined;
197 G4double
width = 0.0;
199 G4bool consuming =
false;
200 G4String unitString(
"mm");
202 replicavol->GetReplicationData(axis, number, width, offset, consuming);
204 const G4String volumeref =
GenerateName(replicavol->GetLogicalVolume()->GetName(),
205 replicavol->GetLogicalVolume());
207 xercesc::DOMElement* replicavolElement =
NewElement(
"replicavol");
208 replicavolElement->setAttributeNode(
NewAttribute(
"number", number));
209 xercesc::DOMElement* volumerefElement =
NewElement(
"volumeref");
210 volumerefElement->setAttributeNode(
NewAttribute(
"ref", volumeref));
211 replicavolElement->appendChild(volumerefElement);
212 xercesc::DOMElement* replicateElement =
NewElement(
"replicate_along_axis");
213 replicavolElement->appendChild(replicateElement);
215 xercesc::DOMElement* dirElement =
NewElement(
"direction");
220 else if (axis == kYAxis)
224 else if (axis == kZAxis)
228 else if (axis == kRho)
232 else if (axis == kPhi)
237 replicateElement->appendChild(dirElement);
239 xercesc::DOMElement* widthElement =
NewElement(
"width");
240 widthElement->setAttributeNode(
NewAttribute(
"value", width));
241 widthElement->setAttributeNode(
NewAttribute(
"unit", unitString));
242 replicateElement->appendChild(widthElement);
244 xercesc::DOMElement* offsetElement =
NewElement(
"offset");
245 offsetElement->setAttributeNode(
NewAttribute(
"value", offset));
246 offsetElement->setAttributeNode(
NewAttribute(
"unit", unitString));
247 replicateElement->appendChild(offsetElement);
249 volumeElement->appendChild(replicavolElement);
260 const G4SurfaceProperty* psurf = bsurf->GetSurfaceProperty();
264 xercesc::DOMElement* borderElement =
NewElement(
"bordersurface");
265 borderElement->setAttributeNode(
NewAttribute(
"name", bsurf->GetName()));
266 borderElement->setAttributeNode(
NewAttribute(
"surfaceproperty",
269 const G4String volumeref1 =
GenerateName(bsurf->GetVolume1()->GetName(),
270 bsurf->GetVolume1());
271 const G4String volumeref2 =
GenerateName(bsurf->GetVolume2()->GetName(),
272 bsurf->GetVolume2());
273 xercesc::DOMElement* volumerefElement1 =
NewElement(
"physvolref");
274 xercesc::DOMElement* volumerefElement2 =
NewElement(
"physvolref");
275 volumerefElement1->setAttributeNode(
NewAttribute(
"ref", volumeref1));
276 volumerefElement2->setAttributeNode(
NewAttribute(
"ref", volumeref2));
277 borderElement->appendChild(volumerefElement1);
278 borderElement->appendChild(volumerefElement2);
282 const G4OpticalSurface* opsurf =
283 dynamic_cast<const G4OpticalSurface*
>(psurf);
286 G4Exception(
"PHG4GDMLWriteStructure::BorderSurfaceCache()",
287 "InvalidSetup", FatalException,
"No optical surface found!");
304 const G4SurfaceProperty* psurf = ssurf->GetSurfaceProperty();
308 xercesc::DOMElement* skinElement =
NewElement(
"skinsurface");
309 skinElement->setAttributeNode(
NewAttribute(
"name", ssurf->GetName()));
310 skinElement->setAttributeNode(
NewAttribute(
"surfaceproperty",
313 const G4String volumeref =
GenerateName(ssurf->GetLogicalVolume()->GetName(),
314 ssurf->GetLogicalVolume());
315 xercesc::DOMElement* volumerefElement =
NewElement(
"volumeref");
316 volumerefElement->setAttributeNode(
NewAttribute(
"ref", volumeref));
317 skinElement->appendChild(volumerefElement);
321 const G4OpticalSurface* opsurf =
322 dynamic_cast<const G4OpticalSurface*
>(psurf);
325 G4Exception(
"PHG4GDMLWriteStructure::SkinSurfaceCache()",
326 "InvalidSetup", FatalException,
"No optical surface found!");
337 const G4OpticalSurface* osurf =
dynamic_cast<const G4OpticalSurface*
>(psurf);
338 std::vector<const G4OpticalSurface*>::const_iterator
pos;
349 const G4LogicalSkinSurface*
352 G4LogicalSkinSurface*
surf = 0;
353 G4int nsurf = G4LogicalSkinSurface::GetNumberOfSkinSurfaces();
356 const G4LogicalSkinSurfaceTable* stable =
357 G4LogicalSkinSurface::GetSurfaceTable();
358 std::vector<G4LogicalSkinSurface*>::const_iterator
pos;
359 for (pos = stable->begin(); pos != stable->end(); ++
pos)
361 if (lvol == (*pos)->GetLogicalVolume())
371 #if G4VERSION_NUMBER >= 1007
376 G4LogicalBorderSurface*
surf =
nullptr;
377 G4int nsurf = G4LogicalBorderSurface::GetNumberOfBorderSurfaces();
380 const G4LogicalBorderSurfaceTable* btable =
381 G4LogicalBorderSurface::GetSurfaceTable();
382 for (
auto pos = btable->cbegin();
pos != btable->cend(); ++
pos)
384 if (pvol ==
pos->first.first)
396 const G4LogicalBorderSurface*
399 G4LogicalBorderSurface* surf = 0;
400 G4int nsurf = G4LogicalBorderSurface::GetNumberOfBorderSurfaces();
403 const G4LogicalBorderSurfaceTable* btable =
404 G4LogicalBorderSurface::GetSurfaceTable();
405 std::vector<G4LogicalBorderSurface*>::const_iterator
pos;
406 for (pos = btable->begin(); pos != btable->end(); ++
pos)
408 if (pvol == (*pos)->GetVolume1())
422 std::cout <<
"PHG4GDML: Writing surfaces..." << std::endl;
424 std::vector<xercesc::DOMElement*>::const_iterator
pos;
437 std::cout <<
"PHG4GDML: Writing structure..." << std::endl;
455 return G4Transform3D::Identity;
458 G4VSolid* solidPtr = volumePtr->GetSolid();
459 G4Transform3D
R, invR;
462 std::map<const G4LogicalVolume*, PHG4GDMLAuxListType>::iterator auxiter;
468 G4String
ErrorMessage =
"Referenced solid in volume '" + volumePtr->GetName() +
"' was displaced/reflected too many times!";
469 G4Exception(
"PHG4GDMLWriteStructure::TraverseVolumeTree()",
470 "InvalidSetup", FatalException, ErrorMessage);
473 if (G4ReflectedSolid* refl = dynamic_cast<G4ReflectedSolid*>(solidPtr))
475 R = R * refl->GetTransform3D();
476 solidPtr = refl->GetConstituentMovedSolid();
481 if (G4DisplacedSolid*
disp = dynamic_cast<G4DisplacedSolid*>(solidPtr))
483 R = R * G4Transform3D(
disp->GetObjectRotation(),
484 disp->GetObjectTranslation());
485 solidPtr =
disp->GetConstituentMovedSolid();
494 G4LogicalVolume* tmplv =
const_cast<G4LogicalVolume*
>(volumePtr);
513 const G4String materialref =
GenerateName(volumePtr->GetMaterial()->GetName(),
514 volumePtr->GetMaterial());
515 const G4String solidref =
GenerateName(solidPtr->GetName(), solidPtr);
517 xercesc::DOMElement* volumeElement =
NewElement(
"volume");
518 volumeElement->setAttributeNode(
NewAttribute(
"name", name));
519 xercesc::DOMElement* materialrefElement =
NewElement(
"materialref");
520 materialrefElement->setAttributeNode(
NewAttribute(
"ref", materialref));
521 volumeElement->appendChild(materialrefElement);
522 xercesc::DOMElement* solidrefElement =
NewElement(
"solidref");
523 solidrefElement->setAttributeNode(
NewAttribute(
"ref", solidref));
524 volumeElement->appendChild(solidrefElement);
526 const G4int daughterCount = volumePtr->GetNoDaughters();
528 for (G4int
i = 0;
i < daughterCount;
i++)
537 const G4String ModuleName =
Modularize(physvol, depth);
539 G4Transform3D daughterR;
541 if (ModuleName.empty())
548 daughterR = writer.
Write(ModuleName, physvol->GetLogicalVolume(),
552 if (
const G4PVDivision*
const divisionvol = dynamic_cast<const G4PVDivision*>(physvol))
556 G4String
ErrorMessage =
"Division volume in '" + name +
"' can not be related to reflected solid!";
557 G4Exception(
"PHG4GDMLWriteStructure::TraverseVolumeTree()",
558 "InvalidSetup", FatalException, ErrorMessage);
562 else if (physvol->IsParameterised())
566 G4String
ErrorMessage =
"Parameterised volume in '" + name +
"' can not be related to reflected solid!";
567 G4Exception(
"PHG4GDMLWriteStructure::TraverseVolumeTree()",
568 "InvalidSetup", FatalException, ErrorMessage);
572 else if (physvol->IsReplicated())
576 G4String
ErrorMessage =
"Replica volume in '" + name +
"' can not be related to reflected solid!";
577 G4Exception(
"PHG4GDMLWriteStructure::TraverseVolumeTree()",
578 "InvalidSetup", FatalException, ErrorMessage);
584 G4RotationMatrix rot;
585 if (physvol->GetFrameRotation() != 0)
587 rot = *(physvol->GetFrameRotation());
589 G4Transform3D
P(rot, physvol->GetObjectTranslation());
591 PhysvolWrite(volumeElement, physvol, invR *
P * daughterR, ModuleName);
604 auxiter =
auxmap.find(volumePtr);
605 if (auxiter !=
auxmap.end())
607 AddAuxInfo(&(auxiter->second), volumeElement);
630 const G4LogicalVolume*
const lvol)
632 std::map<
const G4LogicalVolume*,
640 auxmap[lvol].push_back(myaux);
651 G4ProductionCuts* pcuts = lvol->GetRegion()->GetProductionCuts();
652 G4ProductionCutsTable* ctab = G4ProductionCutsTable::GetProductionCutsTable();
653 G4Gamma* gamma = G4Gamma::Gamma();
654 G4Electron* eminus = G4Electron::Electron();
655 G4Positron* eplus = G4Positron::Positron();
656 G4Proton* proton = G4Proton::Proton();
658 G4double
gamma_cut = ctab->ConvertRangeToEnergy(gamma, lvol->GetMaterial(),
659 pcuts->GetProductionCut(
"gamma"));
660 G4double eminus_cut = ctab->ConvertRangeToEnergy(eminus, lvol->GetMaterial(),
661 pcuts->GetProductionCut(
"e-"));
662 G4double eplus_cut = ctab->ConvertRangeToEnergy(eplus, lvol->GetMaterial(),
663 pcuts->GetProductionCut(
"e+"));
664 G4double proton_cut = ctab->ConvertRangeToEnergy(proton, lvol->GetMaterial(),
665 pcuts->GetProductionCut(
"proton"));
684 std::ostringstream
os;
686 G4String vl = os.str();