8 #include "GeoModelKernel/GeoIntrusivePtr.h"
9 #include "GeoModelKernel/GeoMaterial.h"
10 #include "GeoModelKernel/GeoElement.h"
11 #include "GeoModelKernel/Units.h"
12 #include "GaudiKernel/SystemOfUnits.h"
31 m_managerName(managerName),
32 m_extraFunctionality(false),
33 m_athenaComps(nullptr) {
41 const std::string& space,
42 bool extraFunctionality)
44 m_managerName(managerName),
45 m_extraFunctionality(extraFunctionality),
46 m_athenaComps(nullptr) {
61 const std::string& space)
63 m_managerName(managerName),
64 m_extraFunctionality(true),
65 m_athenaComps(nullptr) {
75 m_managerName(managerName),
76 m_extraFunctionality(true),
77 m_athenaComps(athenaComps) {
92 std::string errorMessage(
"Null pointer to Stored Material Manager!");
94 throw std::runtime_error(errorMessage);
117 std::string errorMessage(
"Null pointer to Stored Material Manager!");
119 throw std::runtime_error(errorMessage);
129 MaterialStore::const_iterator
iter;
139 const double volumeTot,
140 const double volume1,
const std::string& matName1,
141 const double volume2,
const std::string& matName2
143 std::vector<std::string> baseMaterials;
144 std::vector<double> fracWeight;
145 baseMaterials.reserve(2);
146 fracWeight.reserve(2);
150 ATH_MSG_DEBUG(
"Composite material : " << matName1 <<
" " << matName2);
152 double density1, density2;
154 MaterialWeightMap::const_iterator
iter;
157 density1 = mat1->getDensity();
161 density1 = mat1->getDensity();
167 density2 = mat2->getDensity();
171 density2 = mat2->getDensity();
175 double weight1 = density1 * volume1;
176 double weight2 = density2 * volume2;
177 double invWeightTot = 1.0 / (weight1 + weight2);
179 double density = (weight1 + weight2) / volumeTot;
181 double frac1 = weight1 / (weight1 + weight2);
182 double frac2 = weight2 / (weight1 + weight2);
183 double density_2 = 1.0 / (frac1 / density1 + frac2 / density2);
184 double density_3 = (weight1 + weight2) / (volume1 + volume2);
190 baseMaterials.push_back(matName1);
191 baseMaterials.push_back(matName2);
192 fracWeight.push_back(weight1 * invWeightTot);
193 fracWeight.push_back(weight2 * invWeightTot);
195 return getMaterial(newMatName, baseMaterials, fracWeight, density);
221 std::string newName2 =
newName;
222 bool newNameProvided = !newName2.empty();
223 if (!newNameProvided) {
224 newName2 = origMaterialName +
"Modified";
227 const GeoMaterial* newMaterial =
nullptr;
237 newMaterial = material;
240 newMaterial = origMaterial;
244 if (newNameProvided || !
compareDensity(origMaterial->getDensity(), density)) {
246 GeoMaterial* newMaterialTmp =
new GeoMaterial(newName2, density);
247 newMaterialTmp->add(
const_cast<GeoMaterial*
>(origMaterial), 1.);
249 newMaterial = newMaterialTmp;
269 if (scaleFactor > 1000 || scaleFactor < 0.001) {
270 ATH_MSG_ERROR(
"Scale factor must be between 0.001 and 1000.");
278 if (
newName.empty() && scaleFactor == 1.)
return origMaterial;
280 const GeoMaterial* newMaterial =
nullptr;
283 double density = origMaterial->getDensity() * scaleFactor;
284 std::string newName2 =
newName;
285 if (newName2.empty()) {
287 int scaleInt =
static_cast<int>(scaleFactor * 10000);
288 int scale1 = scaleInt / 10000;
289 int scale2 = scaleInt % 10000;
291 std::ostringstream
os;
292 os << origMaterialName <<
scale1 <<
"_" << std::setw(4) << std::setfill(
'0') <<
scale2;
304 GeoIntrusivePtr<const GeoMaterial> matPtr{material};
305 std::string
name(material->getName());
314 ATH_MSG_DEBUG(
"Created new material: " <<
name <<
", " << material->getDensity() /
322 throw (std::runtime_error(
"InDetMaterialManager:compareDensity: Density is zero"));
324 return(std::abs(
d1 /
d2 - 1.) < 1
e-5);
329 ATH_MSG_DEBUG(
"Reading in weight table: " << weightTable->nodeName());
332 ATH_MSG_DEBUG(
"GeometryDBSvc not available. Using old version.");
337 std::string materialName =
db()->
getString(weightTable,
"MATERIAL",
i);
338 if (!space.empty()) {
339 materialName = space +
"::" + materialName;
341 std::string materialBase;
342 if (
db()->testField(weightTable,
"BASEMATERIAL",
i)) {
343 materialBase =
db()->
getString(weightTable,
"BASEMATERIAL",
i);
348 bool linearWeightFlag =
false;
350 linearWeightFlag =
db()->
getInt(weightTable,
"LINWEIGHTFLAG",
i);
354 ATH_MSG_WARNING(
"Material: " << materialName <<
" already exists in weight table");
358 <<
" linearWeightFlag " << linearWeightFlag
359 <<
" raw weight " <<
db()->getDouble(weightTable,
"WEIGHT",
i)
361 <<
" to weight table");
369 int linearWeightFlag) {
374 ATH_MSG_WARNING(
"Material: " << materialName <<
" already exists in weight table");
378 <<
" linearWeightFlag " << linearWeightFlag
379 <<
" to weight table");
386 for (
unsigned int i = 0;
i < weightTable->size();
i++) {
388 std::string materialName = record->
getString(
"MATERIAL");
389 if (!space.empty()) {
390 materialName = space +
"::" + materialName;
392 std::string materialBase;
394 materialBase = record->
getString(
"BASEMATERIAL");
399 bool linearWeightFlag =
false;
401 linearWeightFlag = record->
getInt(
"LINWEIGHTFLAG");
405 ATH_MSG_WARNING(
"Material: " << materialName <<
" already exists in weight table");
414 ATH_MSG_DEBUG(
"Reading in composition table: " << compositionTable->nodeName());
417 ATH_MSG_ERROR(
"GeometryDBSvc not available. Unable to read in composition table.");
420 std::string materialName =
db()->
getString(compositionTable,
"MATERIAL",
i);
421 if (!space.empty()) {
422 materialName = space +
"::" + materialName;
425 std::string componentName =
db()->
getString(compositionTable,
"COMPONENT",
i);
427 double factor =
db()->
getDouble(compositionTable,
"FACTOR",
i);
428 double actualLength =
db()->
getDouble(compositionTable,
"ACTUALLENGTH",
i);
439 if (!scalingTable)
return;
441 if (
db()->getTableSize(scalingTable) == 0)
return;
443 ATH_MSG_DEBUG(
"Reading in extra material scaling table: " << scalingTable->nodeName());
445 ATH_MSG_ERROR(
"GeometryDBSvc not available. Unable to read in scaling table.");
448 std::string materialName =
db()->
getString(scalingTable,
"MATERIAL",
i);
449 double scalingFactor =
db()->
getDouble(scalingTable,
"FACTOR",
i);
452 if (scalingFactor >= 0 || scalingFactor == 1) {
453 msg(
MSG::DEBUG) <<
"Material " << materialName <<
" will be scaled by: " << scalingFactor <<
endmsg;
460 ATH_MSG_WARNING(
"Overriding material: " << materialName <<
" which already exists in scaling table");
484 MaterialWeightMap::const_iterator
iter;
486 const std::string& materialBase =
iter->second.name;
488 double density =
weight / volume;
489 if (
iter->second.linearWeightFlag) {
490 ATH_MSG_ERROR(
"Material defined by linear weight cannot be created with getMaterialForVolume method: " <<
494 ATH_MSG_VERBOSE(
"Found material in weight table - name, base, weight(g), volume(cm3), density(g/cm3): "
495 << materialName <<
", "
496 << materialBase <<
", "
501 if (materialBase.empty()) {
505 return getMaterial(materialBase, density, materialName);
513 ATH_MSG_VERBOSE(
"Material not in weight table, using standard material: "
539 if (volume <= 0 ||
length <= 0) {
545 std::pair<MaterialCompositionMap::const_iterator, MaterialCompositionMap::const_iterator> iterRange;
548 ATH_MSG_VERBOSE(
"Found material in material composition table:" << materialName);
550 std::vector<double> factors;
551 std::vector<std::string> components;
552 for (MaterialCompositionMap::const_iterator
iter = iterRange.first;
iter != iterRange.second; ++
iter) {
553 double factorTmp =
iter->second.factor;
554 if (
iter->second.actualLength > 0) factorTmp *=
iter->second.actualLength /
length;
555 factors.push_back(factorTmp);
556 components.push_back(
iter->second.name);
562 MaterialWeightMap::const_iterator
iter;
564 const std::string& materialBase =
iter->second.name;
566 double density =
weight / volume;
569 if (materialBase.empty()) {
577 ATH_MSG_VERBOSE(
"Material not in weight table, using standard material: "
586 const std::string& materialComponent,
590 std::vector<std::string> tmpMaterialComponents(1, materialComponent);
591 std::vector<double> tmpFactors(1, factor);
597 const std::vector<std::string>& materialComponents,
598 const std::vector<double>& factors,
602 if (volume <= 0 ||
length <= 0) {
607 if (!factors.empty() && factors.size() < materialComponents.size()) {
608 ATH_MSG_WARNING(
"getMaterialForVolumeLength: factor vector size too small. Setting remaining factors to 1.");
611 std::vector<std::string> baseMaterials;
612 std::vector<double> fracWeight;
613 baseMaterials.reserve(materialComponents.size());
614 fracWeight.reserve(materialComponents.size());
616 double totWeight = 0;
617 for (
unsigned int iComp = 0; iComp < materialComponents.size(); ++iComp) {
618 const std::string& materialName = materialComponents[iComp];
621 MaterialWeightMap::const_iterator
iter;
623 const std::string& materialBase =
iter->second.name;
626 if (iComp < factors.size()) {
631 <<
" factor " << factors[iComp]
633 <<
" basMat " << materialBase
634 <<
" linear? " <<
iter->second.linearWeightFlag);
637 if (materialBase.empty()) {
639 baseMaterials.push_back(materialName);
641 baseMaterials.push_back(materialBase);
643 fracWeight.push_back(
weight);
662 baseMaterials.push_back(materialName);
663 fracWeight.push_back(
weight);
670 for (
unsigned int i = 0;
i < materialComponents.size(); ++
i) {
676 ATH_MSG_ERROR(
"totWeight is zero in InDetMaterialManager::getMaterialForVolumeLength");
679 for (
unsigned int i = 0;
i < fracWeight.size(); ++
i) {
680 fracWeight[
i] /= totWeight;
683 ATH_MSG_ERROR(
"volume is zero in InDetMaterialManager::getMaterialForVolumeLength");
686 double density = totWeight / volume;
694 const std::vector<std::string>& materialComponents,
695 const std::vector<double>& fracWeight,
702 const std::vector<std::string>& materialComponents,
703 const std::vector<double>& fracWeight,
705 const GeoMaterial* newMaterial =
nullptr;
714 newMaterial = material;
716 GeoMaterial* newMaterialTmp =
new GeoMaterial(
name, density);
717 for (
unsigned int i = 0;
i < materialComponents.size();
i++) {
720 newMaterialTmp->add(
const_cast<GeoMaterial*
>(origMaterial), fracWeight[
i]);
722 ATH_MSG_ERROR(
"Material component missing " << materialComponents[
i]);
726 newMaterial = newMaterialTmp;
740 const std::string materialTable =
"ExtraMaterials";
741 const std::string componentsTable =
"ExtraMatComponents";
746 if (!
db() || !
db()->testField(
"",
"TableSize:" + materialTable) || !
db()->getTableSize(materialTable)
747 || !
db()->testField(
"",
"TableSize:" + componentsTable) || !
db()->getTableSize(componentsTable))
return;
750 ATH_MSG_INFO(
"Extra materials being read in from text file.");
752 using MatMap = std::map<std::string, MaterialDef>;
756 for (
unsigned int iMat = 0; iMat <
db()->
getTableSize(materialTable); iMat++) {
757 std::string materialName =
db()->
getString(materialTable,
"NAME", iMat);
759 materials[materialName] =
MaterialDef(materialName, density);
763 for (
unsigned int iComp = 0; iComp <
db()->
getTableSize(componentsTable); iComp++) {
764 std::string materialName =
db()->
getString(componentsTable,
"NAME", iComp);
766 double fracWeight =
db()->
getDouble(componentsTable,
"FRACTION", iComp);
768 if (
iter != materials.end()) {
778 int matCountLast = -1;
779 bool someUndefined =
true;
783 while (someUndefined && matCount != matCountLast) {
784 matCountLast = matCount;
785 someUndefined =
false;
791 bool compsDefined =
true;
792 for (
unsigned int iComp = 0; iComp < tmpMat.
numComponents(); ++iComp) {
795 if (iter2 != materials.end()) {
796 if (!iter2->second.isCreated()) {
797 compsDefined =
false;
807 someUndefined =
true;
815 ATH_MSG_ERROR(
"Not all materials could be defined due to cyclic definitions");
828 bool byAtomicRatio =
false;
829 if (totWeight > 1.1) {
830 byAtomicRatio =
true;
832 if (material.
compName(
i).find(
"::") != std::string::npos) {
835 ", is assumed to be defined by atomic ratio (due to total fraction > 1)"
836 " but component is not an element: " << material.
compName(
i));
841 ATH_MSG_ERROR(
"Error making material " << material.
name() <<
". Element not found: " <<
845 totWeight += material.
fraction(
i) * element->getA();
849 if (std::abs(totWeight - 1) > 0.01) {
850 ATH_MSG_WARNING(
"Total fractional weight does not sum to 1. Will renormalize. Total = " << totWeight);
854 GeoIntrusivePtr<GeoMaterial> newMaterial{
new GeoMaterial(material.
name(), material.
density())};
858 ATH_MSG_ERROR(
"totWeight is zero in InDetMaterialManager::createMaterial");
862 double fracWeight = material.
fraction(
i) / totWeight;
863 if (material.
compName(
i).find(
"::") == std::string::npos) {
871 fracWeight = material.
fraction(
i) * element->getA() / totWeight;
873 newMaterial->add(
const_cast<GeoElement*
>(element), fracWeight);
886 newMaterial->add(
const_cast<GeoMaterial*
>(materialTmp.get()), fracWeight);
908 m_fractions.push_back(fraction);
915 for (
unsigned int i = 0;
i < m_fractions.size();
i++) {
916 sum += m_fractions[
i];
931 const GeoMaterial* origMaterial) {
941 if (!origMaterial)
throw std::runtime_error(std::string(
"Invalid material: ") + materialName);
946 if (scaleFactor < 0 || scaleFactor == 1 || materialName.find(
"Ether") != std::string::npos)
return origMaterial;
950 std::string
newName = materialName +
"_ExtraScaling";
956 if (newMaterial)
return newMaterial;
959 double density = origMaterial->getDensity() * scaleFactor;
962 GeoMaterial* newMaterialTmp =
new GeoMaterial(
newName, density);
963 newMaterialTmp->add(
const_cast<GeoMaterial*
>(origMaterial), 1.);
965 newMaterial = newMaterialTmp;
985 if (
iter !=
m_scalingMap.end() && materialName !=
"std::Air" && materialName !=
"std::Vacuum") {