ATLAS Offline Software
Loading...
Searching...
No Matches
ExtParameterisedVolumeBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
7#include "Geo2G4LVFactory.h"
9#include "G4LogicalVolume.hh"
10
11#include "G4PVPlacement.hh"
12#include "G4ReflectionFactory.hh"
13#include "G4VPVParameterisation.hh"
14#include "G4PVParameterised.hh"
15#include "globals.hh"
16
18
19#include "GeoModelKernel/GeoAccessVolAndSTAction.h"
20#include "GeoModelKernel/GeoVolumeCursor.h"
21#include "GeoModelKernel/GeoMaterial.h"
22#include "GeoModelKernel/GeoLogVol.h"
23#include "GeoModelKernel/GeoSerialTransformer.h"
25
27#include <iostream>
28#include <format>
29
31
34
35G4LogicalVolume* ExtParameterisedVolumeBuilder::Build(const PVConstLink theGeoPhysVolume, OpticalVolumesMap* optical_volumes) {
36
37 PVConstLink theGeoPhysChild;
38 const GeoSerialTransformer* serialTransformerChild{nullptr};
39 G4LogicalVolume* theG4LogChild{nullptr};
40 unsigned int numChildNodes; // number of child nodes (PV and ST)
41 bool descend; // flag to continue geo tree navigation
42 bool serialExists = false; // flag for existence of ST among childs
43 std::string nameChild;
44
45 if(m_getMatEther) {
47 }
48 // BuildAssembly
49
50 static Geo2G4LVFactory LVFactory;
51
52 G4LogicalVolume* theG4LogVolume = LVFactory.Build(theGeoPhysVolume, descend);
53
54 if(!descend) {
55 return theG4LogVolume;
56 }
57 numChildNodes = theGeoPhysVolume->getNChildVolAndST();
58
59 // *****************************************************************
60 // **
61 // ** If m_ST2Param flag is set:
62 // ** Check if there's any serial transformer among child volumes
63 // **
64 // *****************************************************************
65
66 if(m_paramOn){
67 for(size_t counter1=0; counter1<numChildNodes; ++counter1) {
68 GeoAccessVolAndSTAction actionVolAndST(counter1);
69 theGeoPhysVolume->exec(&actionVolAndST);
70
71 serialTransformerChild=actionVolAndST.getSerialTransformer();
72 if(serialTransformerChild) {
73 nameChild = actionVolAndST.getName();
74 serialExists = true;
75 break;
76 }
77 }
78 }
79 // ***************************************************************************
80 // ** Next steps:
81 // **
82 // ** 1. If ST exists and numChildNodes==1, translate ST to G4 ST
83 // **
84 // ** 2. If ST exists and numChildNodes !=1, print information message and
85 // ** translate ST to single placements as well as all other child volumes
86 // **
87 // ** 3. There's no ST - ok, nothing special ...
88 // **
89 // ***************************************************************************
90
91 if(serialExists && numChildNodes==1) {
92 theGeoPhysChild = serialTransformerChild->getVolume();
93
94 // Build the child
95 theG4LogChild = Build(theGeoPhysChild,optical_volumes);
96 if(!theG4LogChild) {
97 return nullptr;
98 }
99 if (nameChild == "ANON") {
100 nameChild=theG4LogChild->GetName();
101 }
102 nameChild += "_Param";
103
104 Geo2G4STParameterisation* stParameterisation = new Geo2G4STParameterisation(serialTransformerChild->getFunction(),
105 serialTransformerChild->getNCopies());
106
107 [[maybe_unused]] G4VPhysicalVolume* pvParametrised = new G4PVParameterised(nameChild,
108 theG4LogChild,
109 theG4LogVolume,
110 kUndefined,
111 serialTransformerChild->getNCopies(),
112 stParameterisation);
113 } else {
114 if(serialExists) {
115 PrintSTInfo(theGeoPhysVolume->getLogVol()->getName());
116 }
117
118 GeoVolumeCursor av(theGeoPhysVolume);
119 while (!av.atEnd()) {
120 int id = 16969;
121
122 // Get child phys volume
123 theGeoPhysChild = av.getVolume();
124 // Get its transform
125 G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform()));
126
127 std::optional<int> Qint = av.getId();
128 if(Qint) {
129 id = *Qint;
130 }
131
132 const bool isEther = theGeoPhysChild->getLogVol()->getMaterial()->getName() =="special::Ether";
133 const bool isHypUr = theGeoPhysChild->getLogVol()->getMaterial()->getName() =="special::HyperUranium";
134
135 if(isEther) {
136 Geo2G4AssemblyVolume* assembly = BuildAssembly(theGeoPhysChild);
137
138 if(Qint) {
139 assembly->MakeImprint(theG4LogVolume,theG4Position, id);
140 } else {
141 assembly->MakeImprint(theG4LogVolume,theG4Position);
142 }
143 } else if(isHypUr) {
144 Geo2G4AssemblyVolume* assembly = BuildAssembly(theGeoPhysChild);
145
146 if(Qint) {
147 assembly->MakeImprint(theG4LogVolume,theG4Position,id,true);
148 } else {
149 assembly->MakeImprint(theG4LogVolume,theG4Position,0,true);
150 }
151 } else {
152 nameChild = av.getName();
153
154 // Build the child
155 theG4LogChild = Build(theGeoPhysChild,optical_volumes);
156 if(!theG4LogChild) {
157 return nullptr;
158 }
159 if (nameChild == "ANON") {
160 nameChild=theG4LogChild->GetName();
161 }
162 G4PhysicalVolumesPair pvPair = G4ReflectionFactory::Instance()->Place(theG4Position, nameChild,
163 theG4LogChild, theG4LogVolume, false, id);
164
165 // if GeoModel volume is optical store it in the map
166 if(optical_volumes!=nullptr) {
167 const GeoOpticalPhysVol* opticalGeoPhysChild = dynamic_cast < const GeoOpticalPhysVol* >(theGeoPhysChild.get());
168 if(opticalGeoPhysChild) {
169 (*optical_volumes)[opticalGeoPhysChild] = pvPair.first;
170 }
171 }
172 }
173 av.next();
174 }
175 }
176
177 return theG4LogVolume;
178}
179
181 PVConstLink theGeoPhysChild;
182 G4LogicalVolume* theG4LogChild{nullptr};
183 Geo2G4AssemblyVolume* theG4AssemblyChild{nullptr};
184 bool descend{false}; // flag to continue geo tree navigation
185
186 if(m_getMatEther) {
187 getMatEther();
188 }
189 Geo2G4AssemblyVolume* assemblyVolume = m_G4AssemblyFactory->Build(pv, descend);
190
191 if(!descend) {
192 return assemblyVolume;
193 }
194 // Loop over child volumes and add them to the Geo2G4AssemblyVolume
195 GeoVolumeCursor av(pv);
196 while (!av.atEnd()) {
197 theGeoPhysChild = av.getVolume();
198 std::string nameChild = av.getName();
199
200 std::string strVolume = std::format("Volume {:} ({:})", nameChild,
201 theGeoPhysChild->getLogVol()->getName());
202
203 // Check if it is an assembly
204 bool isEther = theGeoPhysChild->getLogVol()->getMaterial()->getName() == "special::Ether";
205 bool isHypUr = theGeoPhysChild->getLogVol()->getMaterial()->getName() == "special::HyperUranium";
206
207 if(isEther || isHypUr) {
208 // Build the child assembly
209 theG4AssemblyChild = BuildAssembly(theGeoPhysChild);
210 if(!theG4AssemblyChild) {
211 return nullptr;
212 }
213 // Get its transform
214 G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform()));
215
216 assemblyVolume->AddPlacedAssembly(theG4AssemblyChild,theG4Position);
217 } else {
218 std::optional<int> Qint = av.getId();
219
220 // Build the child
221 theG4LogChild = Build(theGeoPhysChild);
222 if(!theG4LogChild) {
223 return nullptr;
224 }
225 // Get its transform
226 G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform()));
227
228 int placedID = 0;
229 if(Qint) placedID = *Qint;
230
231 std::string placedName = nameChild=="ANON" ? "" : nameChild;
232
233 assemblyVolume->AddPlacedVolume(theG4LogChild,theG4Position,placedID,placedName);
234 }
235 av.next();
236 }
237 return assemblyVolume;
238}
239
240void ExtParameterisedVolumeBuilder::PrintSTInfo(const std::string& volume) const
241{
242 ATH_MSG_INFO ( "**********************************************" );
243 ATH_MSG_INFO ( "** " );
244 ATH_MSG_INFO ( "** The Volume " << volume );
245 ATH_MSG_INFO ( "** Has children of two different types" );
246 ATH_MSG_INFO ( "** PeoPhysVolume and GeoSerialTransformer" );
247 ATH_MSG_INFO ( "** In this case GeoSerialTransformer will be " );
248 ATH_MSG_INFO ( "** translated into G4 placement but not in " );
249 ATH_MSG_INFO ( "** G4Parameterisation" );
250 ATH_MSG_INFO ( "** " );
251 ATH_MSG_INFO ( "********************************************** " );
252}
253
255{
256 SmartIF<IService> smartDetStore = Gaudi::svcLocator()->service("DetectorStore");
257 StoreGateSvc *pDetStore = dynamic_cast<StoreGateSvc*>(smartDetStore.get());
258 if (!pDetStore) {
259 ATH_MSG_ERROR ( "ExtParameterisedVolumeBuilder: Unable to access Detector Store" );
260 }
261 else {
262 StoredMaterialManager* theMaterialManager = pDetStore->tryRetrieve<StoredMaterialManager>("MATERIALS");
263 if (theMaterialManager) {
264 m_matEther = theMaterialManager->getMaterial("special::Ether");
265 m_matHypUr = theMaterialManager->getMaterial("special::HyperUranium");
266 }
267 }
268 m_getMatEther = false;
269}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
std::map< const GeoOpticalPhysVol *, G4VPhysicalVolume *, std::less< const GeoOpticalPhysVol * > > OpticalVolumesMap
void descend(TDirectory *d, int level, int maxdepth, const std::vector< std::string > &labels)
Definition chains.cxx:107
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
void PrintSTInfo(const std::string &volume) const
Prints info when some PhysVol contains both types (PV and ST) of daughters.
virtual G4LogicalVolume * Build(PVConstLink pv, OpticalVolumesMap *optical_volumes=0) override
Geo2G4AssemblyVolume * BuildAssembly(const PVConstLink &pv)
ExtParameterisedVolumeBuilder(const std::string &n, Geo2G4AssemblyFactory *G4AssemblyFactory)
void MakeImprint(G4LogicalVolume *pMotherLV, G4ThreeVector &translationInMother, const G4RotationMatrix *pRotationInMother, G4int copyNumBase=0, G4bool ITkScheme=false, G4bool surfCheck=false)
void AddPlacedAssembly(Geo2G4AssemblyVolume *pAssembly, G4Transform3D &transformation)
void AddPlacedVolume(G4LogicalVolume *pPlacedVolume, G4ThreeVector &translation, G4RotationMatrix *rotation, int copyNo=0, const G4String &userComment="")
Ensure that the extensions for the Vector3D are properly loaded.
The Athena Transient Store API.
T * tryRetrieve() const
Variant of the above which doesn't print a warning message.
This class holds one or more material managers and makes them storeable, under StoreGate.
virtual const GeoMaterial * getMaterial(const std::string &name)=0
HepGeom::Transform3D EigenTransformToCLHEP(const Amg::Transform3D &eigenTransf)
Converts an Eigen-based Amg::Transform3D into a CLHEP-based HepGeom::Transform3D.