ATLAS Offline Software
Loading...
Searching...
No Matches
RDBMaterialManager.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
8
9#include "GeoModelKernel/GeoMaterial.h"
10#include "GeoModelKernel/Units.h"
11
15
16#include "GaudiKernel/ISvcLocator.h"
17#include "GaudiKernel/SystemOfUnits.h"
19
20#include <algorithm>
21#include <iostream>
22#include <stdexcept>
23
25 : AthMessaging("GeoModelSvc::RDBMaterialManager")
26{
27 if(!readMaterialsFromDB(pSvcLocator).isSuccess()) {
28 throw std::runtime_error("RDBMaterialManager failed to read Geometry DB");
29 }
30}
31
32StatusCode RDBMaterialManager::readMaterialsFromDB(ISvcLocator* pSvcLocator)
33{
34 SmartIF<IGeoModelSvc> iGeoModel{pSvcLocator->service("GeoModelSvc")};
35 ATH_CHECK( iGeoModel.isValid() );
36
37 SmartIF<IRDBAccessSvc> iAccessSvc{pSvcLocator->service("RDBAccessSvc")};
38 ATH_CHECK( iAccessSvc.isValid() );
39
40 const bool loadDefaults = iGeoModel->geoConfig() != GeoModel::GEO_RUN4;
41 auto defaulted = [=](const IRDBRecordset_ptr pRecordset) -> bool{
42 return (loadDefaults and pRecordset->size() == 0);
43 };
44 // Do not load defaults for RUN4
45 if (loadDefaults) ATH_MSG_DEBUG("Will load material defaults if not present");
46
47 // --- Elements
48 DecodeVersionKey keyAtlas(iGeoModel, "ATLAS");
49 m_elements = iAccessSvc->getRecordsetPtr("Elements",keyAtlas.tag(),keyAtlas.node());
50 if(defaulted(m_elements)) {
51 ATH_MSG_WARNING("Getting Elements with default tag");
52 m_elements = iAccessSvc->getRecordsetPtr("Elements","Materials-00","Materials");
53 }
54
55 IRDBRecordset_ptr recMaterials{};
56 IRDBRecordset_ptr recMatcomponents{};
57
58 // --- Standard materials
59 recMatcomponents = iAccessSvc->getRecordsetPtr("StdMatComponents",keyAtlas.tag(),keyAtlas.node());
60 if(defaulted(recMatcomponents)) {
61 ATH_MSG_WARNING("Getting StdMatComponents with default tag");
62 recMatcomponents = iAccessSvc->getRecordsetPtr("StdMatComponents","Materials-00","Materials");
63 }
64 recMaterials = iAccessSvc->getRecordsetPtr("StdMaterials",keyAtlas.tag(),keyAtlas.node());
65 if(defaulted(recMaterials)) {
66 ATH_MSG_WARNING("Getting StdMaterials with default tag");
67 recMaterials = iAccessSvc->getRecordsetPtr("StdMaterials","Materials-00","Materials");
68 }
69 m_detData.emplace("std",DetectorAuxData{"STDMATERIALS_DATA_ID", recMaterials, recMatcomponents});
70
71 // --- Pixel materials
72 DecodeVersionKey keyPixel(iGeoModel, "Pixel");
73 recMatcomponents = iAccessSvc->getRecordsetPtr("PixMatComponents",keyPixel.tag(),keyPixel.node());
74 if(defaulted(recMatcomponents)) {
75 ATH_MSG_WARNING("Getting PixMatComponents with default tag");
76 recMatcomponents = iAccessSvc->getRecordsetPtr("PixMatComponents","PixMatComponents-00");
77 }
78 recMaterials = iAccessSvc->getRecordsetPtr("PixMaterials",keyPixel.tag(),keyPixel.node());
79 if(defaulted(recMaterials)) {
80 ATH_MSG_WARNING("Getting PixMaterials with default tag");
81 recMaterials = iAccessSvc->getRecordsetPtr("PixMaterials","PixMaterials-00");
82 }
83 m_detData.emplace("pix",DetectorAuxData{"PIXMATERIALS_DATA_ID", recMaterials, recMatcomponents});
84
85 // --- SCT materials
86 DecodeVersionKey keySCT(iGeoModel, "SCT");
87 recMatcomponents = iAccessSvc->getRecordsetPtr("SCTMatComponents",keySCT.tag(),keySCT.node());
88 if(defaulted(recMatcomponents)) {
89 ATH_MSG_WARNING("Getting SCTMatComponents with default tag");
90 recMatcomponents = iAccessSvc->getRecordsetPtr("SCTMatComponents","SCTMatComponents-00");
91 }
92 recMaterials = iAccessSvc->getRecordsetPtr("SCTMaterials",keySCT.tag(),keySCT.node());
93 if(defaulted(recMaterials)) {
94 ATH_MSG_WARNING("Getting SCTMaterials with default tag");
95 recMaterials = iAccessSvc->getRecordsetPtr("SCTMaterials","SCTMaterials-00");
96 }
97 m_detData.emplace("sct",DetectorAuxData{"SCTMATERIALS_DATA_ID", recMaterials, recMatcomponents});
98
99 // --- TRT materials
100 DecodeVersionKey keyTRT(iGeoModel, "TRT");
101 recMatcomponents = iAccessSvc->getRecordsetPtr("TrtMatComponents",keyTRT.tag(),keyTRT.node());
102 if(defaulted(recMatcomponents)) {
103 ATH_MSG_WARNING("Getting TrtMatComponents with default tag");
104 recMatcomponents = iAccessSvc->getRecordsetPtr("TrtMatComponents","TrtMatComponents-00");
105 }
106 recMaterials = iAccessSvc->getRecordsetPtr("TrtMaterials",keyTRT.tag(),keyTRT.node());
107 if(defaulted(recMaterials)) {
108 ATH_MSG_WARNING("Getting TrtMaterials with default tag");
109 recMaterials = iAccessSvc->getRecordsetPtr("TrtMaterials","TrtMaterials-00");
110 }
111 m_detData.emplace("trt",DetectorAuxData{"TRTMATERIALS_DATA_ID", recMaterials, recMatcomponents});
112
113 // --- InDet common materials
114 DecodeVersionKey keyInDet(iGeoModel, "InnerDetector");
115 recMatcomponents = iAccessSvc->getRecordsetPtr("InDetMatComponents",keyInDet.tag(),keyInDet.node());
116 if(defaulted(recMatcomponents)) {
117 ATH_MSG_DEBUG("Getting InDetMatComponents with default tag");
118 recMatcomponents = iAccessSvc->getRecordsetPtr("InDetMatComponents","InDetMatComponents-00");
119 }
120 recMaterials = iAccessSvc->getRecordsetPtr("InDetMaterials",keyInDet.tag(),keyInDet.node());
121 if(defaulted(recMaterials)) {
122 ATH_MSG_DEBUG("Getting InDetMaterials with default tag");
123 recMaterials = iAccessSvc->getRecordsetPtr("InDetMaterials","InDetMaterials-00");
124 }
125 m_detData.emplace("indet",DetectorAuxData{"INDETMATERIALS_DATA_ID", recMaterials, recMatcomponents});
126
127 // --- LAr materials
128 DecodeVersionKey keyLAr(iGeoModel, "LAr");
129 recMatcomponents = iAccessSvc->getRecordsetPtr("LArMatComponents",keyLAr.tag(),keyLAr.node());
130 if(defaulted(recMatcomponents)) {
131 ATH_MSG_WARNING("Getting LArMatComponents with default tag");
132 recMatcomponents = iAccessSvc->getRecordsetPtr("LArMatComponents","LArMatComponents-00");
133 }
134 recMaterials = iAccessSvc->getRecordsetPtr("LArMaterials",keyLAr.tag(),keyLAr.node());
135 if(defaulted(recMaterials)) {
136 ATH_MSG_WARNING("Getting LArMaterials with default tag");
137 recMaterials = iAccessSvc->getRecordsetPtr("LArMaterials","LArMaterials-00");
138 }
139 m_detData.emplace("LAr",DetectorAuxData{"LARMATERIALS_DATA_ID", recMaterials, recMatcomponents});
140
141 // --- Tile materials
142 DecodeVersionKey keyTile(iGeoModel, "TileCal");
143 recMatcomponents = iAccessSvc->getRecordsetPtr("TileMatComponents",keyTile.tag(),keyTile.node());
144 if (defaulted(recMatcomponents)) {
145 ATH_MSG_WARNING("Getting TileMatComponents with default tag" );
146 recMatcomponents = iAccessSvc->getRecordsetPtr("TileMatComponents","TileMatComponents-00");
147 }
148 recMaterials = iAccessSvc->getRecordsetPtr("TileMaterials",keyTile.tag(),keyTile.node());
149 if(defaulted(recMaterials)) {
150 ATH_MSG_WARNING("Getting TileMaterials with default tag");
151 recMaterials = iAccessSvc->getRecordsetPtr("TileMaterials","TileMaterials-00");
152 }
153 m_detData.emplace("tile",DetectorAuxData{"TILEMATERIALS_DATA_ID", recMaterials, recMatcomponents});
154
155 // --- Muon
156 DecodeVersionKey keyMuon(iGeoModel, "MuonSpectrometer");
157 recMatcomponents = iAccessSvc->getRecordsetPtr("MUOMatComponents",keyMuon.tag(),keyMuon.node());
158 if(defaulted(recMatcomponents)) {
159 ATH_MSG_WARNING("Getting MUOMatComponents with default tag");
160 recMatcomponents = iAccessSvc->getRecordsetPtr("MUOMatComponents","MUOMatComponents-00");
161 }
162 recMaterials = iAccessSvc->getRecordsetPtr("MUOMaterials",keyMuon.tag(),keyMuon.node());
163 if(defaulted(recMaterials)) {
164 ATH_MSG_WARNING("Getting MUOMaterials with default tag" );
165 recMaterials = iAccessSvc->getRecordsetPtr("MUOMaterials","MUOMaterials-00");
166 }
167 m_detData.emplace("muo",DetectorAuxData{"MUOMATERIALS_DATA_ID", recMaterials, recMatcomponents});
168
169 // --- Shield
170 recMatcomponents = iAccessSvc->getRecordsetPtr("ShieldMatComponents",keyMuon.tag(),keyMuon.node());
171 if(defaulted(recMatcomponents)) {
172 ATH_MSG_WARNING("Getting ShieldMatComponents with default tag");
173 recMatcomponents = iAccessSvc->getRecordsetPtr("ShieldMatComponents","ShieldMatComponents-00");
174 }
175 recMaterials = iAccessSvc->getRecordsetPtr("ShieldMaterials",keyMuon.tag(),keyMuon.node());
176 if(defaulted(recMaterials)) {
177 ATH_MSG_WARNING("Getting ShieldMaterials with default tag");
178 recMaterials = iAccessSvc->getRecordsetPtr("ShieldMaterials","ShieldMaterials-00");
179 }
180 m_detData.emplace("shield",DetectorAuxData{"SHIELDMATERIALS_DATA_ID", recMaterials, recMatcomponents});
181
182 // --- Toro
183 recMatcomponents = iAccessSvc->getRecordsetPtr("ToroMatComponents",keyMuon.tag(),keyMuon.node());
184 if(defaulted(recMatcomponents)) {
185 ATH_MSG_WARNING("Getting ToroMatComponents with default tag");
186 recMatcomponents = iAccessSvc->getRecordsetPtr("ToroMatComponents","ToroMatComponents-00");
187 }
188 recMaterials = iAccessSvc->getRecordsetPtr("ToroMaterials",keyMuon.tag(),keyMuon.node());
189 if(defaulted(recMaterials)) {
190 ATH_MSG_WARNING("Getting ToroMaterials with default tag");
191 recMaterials = iAccessSvc->getRecordsetPtr("ToroMaterials","ToroMaterials-00");
192 }
193 m_detData.emplace("toro",DetectorAuxData{"TOROMATERIALS_DATA_ID", std::move(recMaterials), std::move(recMatcomponents)});
194
195 return StatusCode::SUCCESS;
196}
197
198// Destructor:
200
201GeoMaterial* RDBMaterialManager::searchMaterialMap(const std::string & name) const
202{
203 MaterialMapIterator m = m_materialMap.find(name);
204
205 if (m!=m_materialMap.end()) {
206 ATH_MSG_VERBOSE(" ***** in searchMaterialMap(): search success for " << name);
207 return (*m).second;
208 }
209
210 ATH_MSG_VERBOSE(" ***** in searchMaterialMap(): search failed for " << name);
211 return nullptr;
212}
213
214
215GeoElement *RDBMaterialManager::searchElementVector(const std::string & name) const
216{
217 GeoEleVec::const_iterator it_element = std::find_if(m_elementVector.begin()
218 , m_elementVector.end()
219 , [&name](const GeoElement* element) {
220 return name == element->getName();
221 });
222
223 if (it_element != m_elementVector.end()) {
224 ATH_MSG_VERBOSE(" ***** in searchElementVector() search success for " << name);
225 return *it_element;
226 }
227
228 ATH_MSG_VERBOSE(" ***** in searchElementVector() search failed for " << name);
229 return nullptr;
230}
231
232
233GeoElement *RDBMaterialManager::searchElementVector(const unsigned int atomicNumber) const
234{
235 GeoEleVec::const_iterator it_element = std::find_if(m_elementVector.begin()
236 , m_elementVector.end()
237 , [atomicNumber](const GeoElement* element) {
238 return atomicNumber == element->getZ();
239 });
240
241 if (it_element != m_elementVector.end()) {
242 ATH_MSG_VERBOSE(" ***** in searchElementVector(atomicNumber) search success for atomic number " << atomicNumber);
243 return *it_element;
244 }
245
246 ATH_MSG_VERBOSE(" ***** in searchElementVector(atomicNumber) search success for atomic number " << atomicNumber);
247 return nullptr;
248}
249
250const GeoMaterial* RDBMaterialManager::getMaterial(const std::string &name)
251{
252 [[maybe_unused]] static const bool specialMaterialsDone = [this]() {
254 return true;
255 }();
256
257 ATH_MSG_DEBUG(" ***** getMaterial( ): " << name);
258
259 GeoMaterial* pmaterial = searchMaterialMap(name);
260 if (pmaterial)
261 return pmaterial;
262
263 size_t pos = name.find("::");
264 if(pos==std::string::npos) {
265 ATH_MSG_ERROR("Wrong format for the material name " << name
266 << ". Must be detector::material");
267 return nullptr;
268 }
269
270 const std::string detector = name.substr(0,pos);
271 auto it = m_detData.find(detector);
272 if(it==m_detData.end()) {
273 ATH_MSG_ERROR("Wrong detector name " << detector
274 << " passed to getMaterial()");
275 return nullptr;
276 }
277
278 IRDBRecordset_ptr tmp_materials = it->second.m_materials;
279 IRDBRecordset_ptr tmp_matcomponents = it->second.m_matcomponents;
280 const std::string& data_id = it->second.m_prim_key;
281
282 auto it_material = std::find_if(tmp_materials->begin()
283 , tmp_materials->end()
284 , [&name, &detector](const IRDBRecord_ptr& rec) {
285 return name == detector+"::"+rec->getString("NAME");
286 });
287
288 if(it_material==tmp_materials->end()) {
289 ATH_MSG_VERBOSE(detector << " materials retrieved from the database don't include " << name);
290 return nullptr;
291 }
292
293 const auto& rec = *it_material;
294 std::string material_name = detector+"::"+rec->getString("NAME");
295 long material_id = rec->getLong(data_id);
296 double material_density = rec->getDouble("DENSITY");
297
298 ATH_MSG_DEBUG(" ***** Material: name id density: " << material_name <<" " << material_id <<" "<< material_density);
299
300 pmaterial = new GeoMaterial( material_name,material_density * (GeoModelKernelUnits::gram / Gaudi::Units::cm3));
301
302 bool firstComponent = true;
303 bool hasSubMaterial = false;
304 bool calculateFraction = false;
305 double totalFraction = 0.;
306 double component_fraction = 0.;
307 std::string component_name{};
308
309 std::vector <const GeoElement*> elementComponents;
310 std::vector <double> elementFractions;
311
312 for(const auto& rec : *tmp_matcomponents) {
313 if(rec->getLong("MATERIAL_ID") == material_id) {
314 component_name = rec->getString("COMPNAME");
315 component_fraction = rec->getDouble("FRACTION");
316
317 if(firstComponent) {
318 firstComponent = false;
319 if(component_fraction>=1.) {
320 calculateFraction = true;
321 }
322 }
323
324 if(component_name.find("::",0) == std::string::npos) {
325 const GeoElement* p_com_element = getElement(component_name);
326
327 if(calculateFraction) {
328 totalFraction += component_fraction*p_com_element->getA();
329 elementComponents.push_back(p_com_element);
330 elementFractions.push_back(component_fraction);
331 }
332 else {
333 pmaterial->add( p_com_element, component_fraction);
334 }
335 }
336 else {
337 hasSubMaterial = true;
338 const GeoMaterial* p_com_material = getMaterial(component_name);
339 pmaterial->add(p_com_material, component_fraction);
340 } // Element vs Sub-Material
341 } // Deal with the component
342 } // Loop over records
343
344 if(calculateFraction && hasSubMaterial && elementComponents.size()>0)
345 ATH_MSG_WARNING(material_name << " description should be changed. Please indicate the exact fraction for elements");
346
347 if(calculateFraction && !elementComponents.empty()) {
348 double inv_totalFraction = totalFraction == 0 ? 1 : 1. / totalFraction;
349 for(unsigned i=0; i<elementComponents.size(); ++i) {
350 pmaterial->add(elementComponents[i],elementFractions[i]*elementComponents[i]->getA() * inv_totalFraction);
351 }
352 }
353
354 // Cache new material
355 addMaterial(detector,pmaterial);
356
357 return pmaterial;
358}
359
360const GeoElement *RDBMaterialManager::getElement(const std::string & name)
361{
362 ATH_MSG_VERBOSE(" ***** getElement(): " << name);
363
364 GeoElement* pelement = searchElementVector(name);
365 if(!pelement) {
366 for(const auto& rec : *m_elements) {
367 if(name == rec->getString("NAME")) {
368 pelement = new GeoElement(rec->getString("NAME")
369 , rec->getString("SYMBOL")
370 , rec->getDouble("Z")
371 , rec->getDouble("A")*GeoModelKernelUnits::gram/Gaudi::Units::mole);
372
373 // a table to keep the memory allocation, and easy for delete
374 m_elementVector.push_back(pelement);
375 break;
376 }
377 }
378 }
379 return pelement;
380}
381
382const GeoElement *RDBMaterialManager::getElement(unsigned int atomicNumber)
383{
384 ATH_MSG_VERBOSE(" ***** const getElement(atomicNumber) const : " << atomicNumber);
385
386 GeoElement* pelement = searchElementVector(atomicNumber);
387 if(!pelement) {
388 for(const auto& rec : *m_elements) {
389 if(atomicNumber == rec->getDouble("A")) {
390 pelement = new GeoElement(rec->getString("NAME")
391 , rec->getString("SYMBOL")
392 , rec->getDouble("Z")
393 , rec->getDouble("A")*GeoModelKernelUnits::gram/Gaudi::Units::mole);
394
395 // a table to keep the memory allocation, and easy for delete
396 m_elementVector.push_back( pelement);
397 break;
398 }
399 }
400 }
401 return pelement;
402}
403
404void RDBMaterialManager::addMaterial(const std::string & /*space*/, GeoMaterial *material)
405{
406 ATH_MSG_VERBOSE(" ***** RDBMaterialManager::addMaterial() ");
407 const std::string& key = material->getName();
408 const auto [it_material, success] = m_materialMap.emplace(key,material);
409 if(success) {
410 it_material->second->lock();
411 }
412 else {
413 // Warn if we already have material with the same name defined
414 ATH_MSG_WARNING(" Attempt to redefine material " << key
415 << "!. The existing instance is kept. Please choose another name for new material");
416 }
417}
418
423
428
430{
431 return m_materialMap.size();
432}
433
434std::ostream & RDBMaterialManager::printAll(std::ostream & o) const
435{
436 o << "============Material Manager Element List========================\n";
437 for (GeoElement* elt : m_elementVector){
438 o << elt->getSymbol() << '\t' << elt->getZ() << '\t' << elt->getA() * (Gaudi::Units::mole / GeoModelKernelUnits::gram) << '\t' << elt->getName() << "\n";
439 }
440
441 for (const auto& p : m_materialMap){
442 o << "Material: " << p.first << " Density " << p.second->getDensity() * (Gaudi::Units::cm3 / GeoModelKernelUnits::gram) << "\n";
443 for (size_t i = 0; i< p.second->getNumElements();i++) {
444 o <<" ***** ***** "<< int (p.second->getFraction(i)*100) << "% \t" << p.second->getElement(i)->getName() << std::endl;
445 }
446 }
447
448 return o;
449}
450
452{
453 // Create special materials
454 GeoElement* ethElement = new GeoElement("Ether","ET",500.0,0.0);
455 m_elementVector.push_back(ethElement);
456 GeoMaterial* ether = new GeoMaterial("special::Ether",0.0);
457 ether->add(ethElement,1.);
458 addMaterial("special",ether);
459 // "Alternative" assembly material
460 GeoMaterial* hu = new GeoMaterial("special::HyperUranium",0.0);
461 hu->add(ethElement,1.);
462 addMaterial("special",hu);
463}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Definition of the abstract IRDBAccessSvc interface.
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
This is a helper class to query the version tags from GeoModelSvc and determine the appropriate tag a...
const std::string & tag() const
Return version tag.
const std::string & node() const
Return the version node.
virtual const std::string & getString(const std::string &fieldName) const =0
Get string field value.
virtual long getLong(const std::string &fieldName) const =0
Get long field value.
virtual double getDouble(const std::string &fieldName) const =0
Get double field value.
virtual const_iterator begin() const =0
virtual const_iterator end() const =0
GeoMaterial * searchMaterialMap(const std::string &name) const
virtual std::ostream & printAll(std::ostream &o=std::cout) const override
StatusCode readMaterialsFromDB(ISvcLocator *pSvcLocator)
virtual StoredMaterialManager::MaterialMapIterator end() const override
virtual const GeoMaterial * getMaterial(const std::string &name) override
virtual void addMaterial(const std::string &space, GeoMaterial *material) override
std::map< std::string, DetectorAuxData > m_detData
virtual StoredMaterialManager::MaterialMapIterator begin() const override
RDBMaterialManager(ISvcLocator *pSvcLocator)
IRDBRecordset_ptr m_elements
GeoElement * searchElementVector(const std::string &name) const
StoredMaterialManager::MaterialMap m_materialMap
virtual size_t size() override
virtual ~RDBMaterialManager()
virtual const GeoElement * getElement(const std::string &name) override
MaterialMap::const_iterator MaterialMapIterator