ATLAS Offline Software
Loading...
Searching...
No Matches
ExtParameterisedVolumeBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 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
30
33 AthMessaging(n),
34 m_getMatEther(true),
35 m_matEther(nullptr),
36 m_matHypUr(nullptr),
37 m_G4AssemblyFactory(G4AssemblyFactory)
38{
39}
40
41G4LogicalVolume* ExtParameterisedVolumeBuilder::Build(const PVConstLink theGeoPhysVolume, OpticalVolumesMap* optical_volumes)
42{
43 PVConstLink theGeoPhysChild;
44 const GeoSerialTransformer* serialTransformerChild{nullptr};
45 G4LogicalVolume* theG4LogChild{nullptr};
46 unsigned int numChildNodes; // number of child nodes (PV and ST)
47 bool descend; // flag to continue geo tree navigation
48 bool serialExists = false; // flag for existence of ST among childs
49 std::string nameChild;
50
52
53 static Geo2G4LVFactory LVFactory;
54
55 G4LogicalVolume* theG4LogVolume = LVFactory.Build(theGeoPhysVolume,descend);
56
57 if(!descend) return theG4LogVolume;
58
59 numChildNodes = theGeoPhysVolume->getNChildVolAndST();
60
61 // *****************************************************************
62 // **
63 // ** If m_ST2Param flag is set:
64 // ** Check if there's any serial transformer among child volumes
65 // **
66 // *****************************************************************
67
68 if(m_paramOn)
69 for(size_t counter1=0; counter1<numChildNodes; counter1++)
70 {
71 GeoAccessVolAndSTAction actionVolAndST(counter1);
72 theGeoPhysVolume->exec(&actionVolAndST);
73
74 if((serialTransformerChild=actionVolAndST.getSerialTransformer()))
75 {
76 nameChild = actionVolAndST.getName();
77 serialExists = true;
78 break;
79 }
80 }
81 // ***************************************************************************
82 // ** Next steps:
83 // **
84 // ** 1. If ST exists and numChildNodes==1, translate ST to G4 ST
85 // **
86 // ** 2. If ST exists and numChildNodes !=1, print information message and
87 // ** translate ST to single placements as well as all other child volumes
88 // **
89 // ** 3. There's no ST - ok, nothing special ...
90 // **
91 // ***************************************************************************
92
93 if(serialExists && (numChildNodes==1))
94 {
95 theGeoPhysChild = serialTransformerChild->getVolume();
96
97 // Build the child
98 if(!(theG4LogChild = Build(theGeoPhysChild,optical_volumes))) return nullptr;
99
100 if (nameChild == "ANON") nameChild=theG4LogChild->GetName();
101 nameChild += "_Param";
102
103 Geo2G4STParameterisation* stParameterisation = new Geo2G4STParameterisation(serialTransformerChild->getFunction(),
104 serialTransformerChild->getNCopies());
105
106 [[maybe_unused]] G4VPhysicalVolume* pvParametrised = new G4PVParameterised(nameChild,
107 theG4LogChild,
108 theG4LogVolume,
109 kUndefined,
110 serialTransformerChild->getNCopies(),
111 stParameterisation);
112 }
113 else
114 {
115 if(serialExists)
116 {
117 std::string volName = theGeoPhysVolume->getLogVol()->getName();
118 PrintSTInfo(volName);
119 }
120
121 GeoVolumeCursor av(theGeoPhysVolume);
122 while (!av.atEnd())
123 {
124 int id = 16969;
125
126 // Get child phys volume
127 theGeoPhysChild = av.getVolume();
128 // Get its transform
129 G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform()));
130
131 std::optional<int> Qint = av.getId();
132 if(Qint) id = *Qint;
133
134 bool isEther = theGeoPhysChild->getLogVol()->getMaterial()->getName().compare("special::Ether")==0;
135 bool isHypUr = theGeoPhysChild->getLogVol()->getMaterial()->getName().compare("special::HyperUranium")==0;
136
137 if(isEther) {
138 Geo2G4AssemblyVolume* assembly = BuildAssembly(theGeoPhysChild);
139
140 if(Qint) {
141 assembly->MakeImprint(theG4LogVolume,theG4Position,id);
142 }
143 else {
144 assembly->MakeImprint(theG4LogVolume,theG4Position);
145 }
146 }
147 else if(isHypUr) {
148 Geo2G4AssemblyVolume* assembly = BuildAssembly(theGeoPhysChild);
149
150 if(Qint) {
151 assembly->MakeImprint(theG4LogVolume,theG4Position,id,true);
152 }
153 else {
154 assembly->MakeImprint(theG4LogVolume,theG4Position,0,true);
155 }
156 }
157 else {
158 nameChild = av.getName();
159
160 // Build the child
161 if(!(theG4LogChild = Build(theGeoPhysChild,optical_volumes))) return nullptr;
162
163 if (nameChild == "ANON") nameChild=theG4LogChild->GetName();
164
165 G4PhysicalVolumesPair pvPair = G4ReflectionFactory::Instance()->Place(theG4Position
166 , nameChild
167 , theG4LogChild
168 , theG4LogVolume
169 , false
170 , id);
171
172 // if GeoModel volume is optical store it in the map
173 if(optical_volumes!=0) {
174 const GeoOpticalPhysVol* opticalGeoPhysChild =
175 dynamic_cast < const GeoOpticalPhysVol* >(theGeoPhysChild.operator->());
176 if(opticalGeoPhysChild)
177 (*optical_volumes)[opticalGeoPhysChild] = pvPair.first;
178 }
179 }
180
181 av.next();
182 }
183 }
184
185 return theG4LogVolume;
186}
187
189{
190 PVConstLink theGeoPhysChild;
191 G4LogicalVolume* theG4LogChild{nullptr};
192 Geo2G4AssemblyVolume* theG4AssemblyChild{nullptr};
193 bool descend; // flag to continue geo tree navigation
194
196
197 Geo2G4AssemblyVolume* assemblyVolume = m_G4AssemblyFactory->Build(pv,descend);
198
199 if(!descend) return assemblyVolume;
200
201 // Loop over child volumes and add them to the Geo2G4AssemblyVolume
202 GeoVolumeCursor av(pv);
203 while (!av.atEnd())
204 {
205 theGeoPhysChild = av.getVolume();
206 std::string nameChild = av.getName();
207
208 std::string strVolume = std::string("Volume ") + nameChild + " ("
209 + theGeoPhysChild->getLogVol()->getName() + ")";
210
211 // Check if it is an assembly
212 bool isEther = theGeoPhysChild->getLogVol()->getMaterial()->getName().compare("special::Ether")==0;
213 bool isHypUr = theGeoPhysChild->getLogVol()->getMaterial()->getName().compare("special::HyperUranium")==0;
214
215 if(isEther || isHypUr) {
216 // Build the child assembly
217 if(!(theG4AssemblyChild = BuildAssembly(theGeoPhysChild))) return nullptr;
218
219 // Get its transform
220 G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform()));
221
222 assemblyVolume->AddPlacedAssembly(theG4AssemblyChild,theG4Position);
223 }
224 else {
225 std::optional<int> Qint = av.getId();
226
227 // Build the child
228 if(!(theG4LogChild = Build(theGeoPhysChild))) return nullptr;
229
230 // Get its transform
231 G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform()));
232
233 int placedID = 0;
234 if(Qint) placedID = *Qint;
235
236 std::string placedName = nameChild=="ANON" ? "" : nameChild;
237
238 assemblyVolume->AddPlacedVolume(theG4LogChild,theG4Position,placedID,placedName);
239 }
240
241 av.next();
242 }
243
244 return assemblyVolume;
245}
246
247void ExtParameterisedVolumeBuilder::PrintSTInfo(const std::string& volume) const
248{
249 ATH_MSG_INFO ( "**********************************************" );
250 ATH_MSG_INFO ( "** " );
251 ATH_MSG_INFO ( "** The Volume " << volume );
252 ATH_MSG_INFO ( "** Has children of two different types" );
253 ATH_MSG_INFO ( "** PeoPhysVolume and GeoSerialTransformer" );
254 ATH_MSG_INFO ( "** In this case GeoSerialTransformer will be " );
255 ATH_MSG_INFO ( "** translated into G4 placement but not in " );
256 ATH_MSG_INFO ( "** G4Parameterisation" );
257 ATH_MSG_INFO ( "** " );
258 ATH_MSG_INFO ( "********************************************** " );
259}
260
262{
263 SmartIF<IService> smartDetStore = Gaudi::svcLocator()->service("DetectorStore");
264 StoreGateSvc *pDetStore = dynamic_cast<StoreGateSvc*>(smartDetStore.get());
265 if (!pDetStore) {
266 ATH_MSG_ERROR ( "ExtParameterisedVolumeBuilder: Unable to access Detector Store" );
267 }
268 else {
269 StoredMaterialManager* theMaterialManager = pDetStore->tryRetrieve<StoredMaterialManager>("MATERIALS");
270 if (theMaterialManager) {
271 m_matEther = theMaterialManager->getMaterial("special::Ether");
272 m_matHypUr = theMaterialManager->getMaterial("special::HyperUranium");
273 }
274 }
275 m_getMatEther = false;
276}
#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.