9 #include <geometry/Materials.h> 
   10 #include <framework/logging/Logger.h> 
   11 #include <framework/gearbox/GearDir.h> 
   12 #include <framework/gearbox/Unit.h> 
   13 #include <geometry/dbobjects/GeoMaterial.h> 
   14 #include <geometry/dbobjects/GeoOpticalSurface.h> 
   18 #include <boost/algorithm/string.hpp> 
   20 #include <G4Material.hh> 
   21 #include <G4Element.hh> 
   22 #include <G4NistManager.hh> 
   23 #include <G4OpticalSurface.hh> 
   24 #include <G4MaterialPropertiesTable.hh> 
   26 #include "CLHEP/Units/PhysicalConstants.h" 
   41       template<
class T> 
void addProperties(T& 
object, 
const gearbox::Interface& parameters)
 
   44         if (parameters.getNumberNodes(
"Property") > 0) {
 
   46           for (
const GearDir& property : parameters.getNodes(
"Property")) {
 
   49               name = 
property.getString(
"@name");
 
   50             } 
catch (gearbox::PathEmptyError&) {
 
   51               B2ERROR(
"Property at " << property.getPath() << 
" does not have a name attribute, ignoring");
 
   54             const double conversionFactor = Unit::convertValue(1, property.getString(
"@unit", 
"GeV"));
 
   55             unsigned int nValues = 
property.getNumberNodes(
"value");
 
   56             std::vector<double> energies(nValues, 0);
 
   57             std::vector<double> values(nValues, 0);
 
   58             for (
unsigned int i = 0; i < nValues; ++i) {
 
   59               GearDir value(property, 
"value", i + 1);
 
   60               energies[i] = value.getDouble(
"@energy") * conversionFactor;
 
   61               values[i] = value.getDouble();
 
   63             object.addProperty({name, energies, values});
 
   69     G4MaterialPropertiesTable* Materials::createProperties(
const std::vector<GeoMaterialProperty>& props)
 
   71       if (!props.size()) 
return nullptr;
 
   72       auto* table = 
new G4MaterialPropertiesTable();
 
   73       m_PropTables.push_back(table);
 
   75         std::vector<double> energies = prop.getEnergies();
 
   76         std::vector<double> values = prop.getValues();
 
   77         const size_t n = values.size();
 
   79         for (
double& energy : energies) energy *= CLHEP::GeV / Unit::GeV;
 
   80         table->AddProperty(prop.getName().c_str(), energies.data(), values.data(), n);
 
   87       static unique_ptr<Materials> instance(
new Materials());
 
   91     Materials::~Materials()
 
   96     void Materials::initBuilders()
 
   98       if (!m_nistMaterialBuilder) {
 
   99         B2DEBUG(50, 
"Creating new Nist Builder instances");
 
  100         m_nistElementBuilder = 
new G4NistElementBuilder(0);
 
  101         m_nistMaterialBuilder = 
new G4NistMaterialBuilder(m_nistElementBuilder, 0);
 
  105     G4Material* Materials::findMaterial(
const string& name)
 
  107       G4Material* mat{
nullptr};
 
  108       if (m_materialCache.retrieve(name, mat)) {
 
  112       mat = m_nistMaterialBuilder->FindOrBuildMaterial(name);
 
  115       if (!mat && name.substr(0, 3) != 
"G4_") {
 
  117         mat = m_nistMaterialBuilder->FindOrBuildMaterial(
"G4_" + name);
 
  119         if (!mat) mat = m_nistMaterialBuilder->FindOrBuildMaterial(
"G4_" + boost::to_upper_copy(name));
 
  123       m_materialCache.insert(name, mat);
 
  127     G4Material* Materials::getMaterial(
const string& name, 
bool showErrors)
 
  129       G4Material* mat = findMaterial(name);
 
  130       if (!mat && showErrors) B2ERROR(
"Material '" << name << 
"' could not be found");
 
  133       if (m_densityScale) {
 
  134         if (m_ignoreScaling.count(name) > 0) 
return mat;
 
  135         if (name.substr(0, 7) == 
"scaled:")
 
  136           B2WARNING(
"Requested an already scaled material ... scaling once more" << 
LogVar(
"material", name));
 
  137         std::string scaled = 
"scaled:" + std::to_string(*m_densityScale) + 
":" + name;
 
  138         G4Material* scaledMat = findMaterial(scaled);
 
  140           scaledMat = 
new G4Material(scaled, mat->GetDensity() * *m_densityScale, mat,
 
  141                                      mat->GetState(), mat->GetTemperature(), mat->GetPressure());
 
  142           m_materialCache.insert(scaled, scaledMat);
 
  149     G4Element* Materials::getElement(
const string& name)
 
  152       G4Element* elm = m_nistElementBuilder->FindOrBuildElement(name);
 
  153       if (!elm) B2ERROR(
"Element '" << name << 
"' could not be found");
 
  159       GeoMaterial material = createMaterialConfig(parameters);
 
  160       return createMaterial(material);
 
  163     G4Material* Materials::createMaterial(
const GeoMaterial& parameters)
 
  165       G4Material* oldmat = getMaterial(parameters.getName(), 
false);
 
  168         B2ERROR(
"Material with name " << parameters.getName() << 
" already existing");
 
  171       B2DEBUG(10, 
"Creating Material " << parameters.getName());
 
  174       double density = parameters.getDensity() * CLHEP::g / CLHEP::cm3;
 
  175       if (density < 1e-25) {
 
  180           if (component.getIselement()) {
 
  181             B2ERROR(
"createMaterial " << parameters.getName()
 
  182                     << 
": Cannot calculate density when adding elements, please provde a density");
 
  185           G4Material* mat = getMaterial(component.getName());
 
  187             B2ERROR(
"createMaterial " << parameters.getName() << 
": Material '" << component.getName() << 
"' not found");
 
  190           density += mat->GetDensity() * component.getFraction();
 
  195       G4Material* mat = 
new G4Material(parameters.getName(), density, parameters.getComponents().size(),
 
  196                                        (G4State)parameters.getState(), parameters.getTemperature(), parameters.getPressure() * CLHEP::pascal);
 
  199         if (component.getIselement()) {
 
  200           G4Element* cmp = getElement(component.getName());
 
  202             B2ERROR(
"Cannot create material " << parameters.getName() << 
": element " << component.getName() << 
" not found");
 
  205           mat->AddElement(cmp, component.getFraction());
 
  207           G4Material* cmp = getMaterial(component.getName());
 
  209             B2ERROR(
"Cannot create material " << parameters.getName() << 
": material " << component.getName() << 
" not found");
 
  212           mat->AddMaterial(cmp, component.getFraction());
 
  217       mat->SetMaterialPropertiesTable(createProperties(parameters.getProperties()));
 
  220       m_materialCache.insert(parameters.getName(), mat);
 
  227       string name = parameters.getString(
"@name");
 
  228       B2DEBUG(10, 
"Creating Material Config " << name);
 
  229       string stateStr = parameters.getString(
"state", 
"undefined");
 
  230       double density = parameters.getDensity(
"density", 0); 
 
  231       double temperature = parameters.getDouble(
"temperature", CLHEP::STP_Temperature);
 
  232       double pressure = parameters.getDouble(
"pressure", CLHEP::STP_Pressure / CLHEP::pascal);
 
  242       double sumFractions(0);
 
  245       for (
const GearDir& component : parameters.getNodes(
"Components/Material")) {
 
  246         const string componentName = component.getString();
 
  247         double fraction = component.getDouble(
"@fraction", 1.0);
 
  248         material.
addComponent({componentName, 
false, fraction});
 
  249         sumFractions += fraction;
 
  252       for (
const GearDir& element : parameters.getNodes(
"Components/Element")) {
 
  253         const std::string elementName = element.getString();
 
  254         double fraction = element.getDouble(
"@fraction", 1.0);
 
  256         sumFractions += fraction;
 
  260       if (abs(sumFractions - 1) > numeric_limits<double>::epsilon()) {
 
  261         B2WARNING(
"createMaterial " << name << 
": Fractions not normalized, scaling by 1/" << sumFractions);
 
  263           cmp.setFraction(cmp.getFraction() / sumFractions);
 
  268       boost::to_lower(stateStr);
 
  269       G4State state = kStateUndefined;
 
  270       if (stateStr == 
"solid") {
 
  272       } 
else if (stateStr == 
"liquid") {
 
  273         state = kStateLiquid;
 
  274       } 
else if (stateStr == 
"gas") {
 
  276       } 
else if (stateStr != 
"undefined") {
 
  277         B2WARNING(
"createMaterial " << name << 
": Unknown state '" << stateStr << 
"', using undefined");
 
  281       addProperties(material, parameters);
 
  289       return createOpticalSurface(surface);
 
  294       G4OpticalSurface* optSurf = 
new G4OpticalSurface(surface.
getName(),
 
  295                                                        (G4OpticalSurfaceModel) surface.
getModel(),
 
  296                                                        (G4OpticalSurfaceFinish) surface.
getFinish(),
 
  297                                                        (G4SurfaceType) surface.
getType(),
 
  299       optSurf->SetMaterialPropertiesTable(createProperties(surface.
getProperties()));
 
  306       string name         = parameters.getString(
"@name", 
"OpticalSurface");
 
  307       string modelString  = parameters.getString(
"Model", 
"glisur");
 
  308       string finishString = parameters.getString(
"Finish", 
"polished");
 
  309       string typeString   = parameters.getString(
"Type", 
"dielectric_dielectric");
 
  310       double value        = parameters.getDouble(
"Value", 1.0);
 
  312 #define CHECK_ENUM_VALUE(name,value) if (name##String == #value) { name = value; } 
  313       G4OpticalSurfaceModel model;
 
  314       boost::to_lower(modelString);
 
  315       CHECK_ENUM_VALUE(model, glisur)
 
  316       else CHECK_ENUM_VALUE(model, unified)
 
  317         else CHECK_ENUM_VALUE(model, LUT)
 
  319             B2FATAL(
"Unknown Optical Surface Model: " << modelString);
 
  322       G4OpticalSurfaceFinish finish;
 
  323       boost::to_lower(finishString);
 
  324       CHECK_ENUM_VALUE(finish, polished)
 
  325       else CHECK_ENUM_VALUE(finish, polishedfrontpainted)
 
  326         else CHECK_ENUM_VALUE(finish, polishedbackpainted)
 
  327           else CHECK_ENUM_VALUE(finish, ground)
 
  328             else CHECK_ENUM_VALUE(finish, groundfrontpainted)
 
  329               else CHECK_ENUM_VALUE(finish, groundbackpainted)
 
  330                 else CHECK_ENUM_VALUE(finish, polishedlumirrorair)
 
  331                   else CHECK_ENUM_VALUE(finish, polishedlumirrorglue)
 
  332                     else CHECK_ENUM_VALUE(finish, polishedair)
 
  333                       else CHECK_ENUM_VALUE(finish, polishedteflonair)
 
  334                         else CHECK_ENUM_VALUE(finish, polishedtioair)
 
  335                           else CHECK_ENUM_VALUE(finish, polishedtyvekair)
 
  336                             else CHECK_ENUM_VALUE(finish, polishedvm2000air)
 
  337                               else CHECK_ENUM_VALUE(finish, polishedvm2000glue)
 
  338                                 else CHECK_ENUM_VALUE(finish, etchedlumirrorair)
 
  339                                   else CHECK_ENUM_VALUE(finish, etchedlumirrorglue)
 
  340                                     else CHECK_ENUM_VALUE(finish, etchedair)
 
  341                                       else CHECK_ENUM_VALUE(finish, etchedteflonair)
 
  342                                         else CHECK_ENUM_VALUE(finish, etchedtioair)
 
  343                                           else CHECK_ENUM_VALUE(finish, etchedtyvekair)
 
  344                                             else CHECK_ENUM_VALUE(finish, etchedvm2000air)
 
  345                                               else CHECK_ENUM_VALUE(finish, etchedvm2000glue)
 
  346                                                 else CHECK_ENUM_VALUE(finish, groundlumirrorair)
 
  347                                                   else CHECK_ENUM_VALUE(finish, groundlumirrorglue)
 
  348                                                     else CHECK_ENUM_VALUE(finish, groundair)
 
  349                                                       else CHECK_ENUM_VALUE(finish, groundteflonair)
 
  350                                                         else CHECK_ENUM_VALUE(finish, groundtioair)
 
  351                                                           else CHECK_ENUM_VALUE(finish, groundtyvekair)
 
  352                                                             else CHECK_ENUM_VALUE(finish, groundvm2000air)
 
  353                                                               else CHECK_ENUM_VALUE(finish, groundvm2000glue)
 
  355                                                                   B2FATAL(
"Unknown Optical Surface Finish: " << finishString);
 
  359       boost::to_lower(typeString);
 
  360       CHECK_ENUM_VALUE(type, dielectric_metal)
 
  361       else CHECK_ENUM_VALUE(type, dielectric_dielectric)
 
  362         else CHECK_ENUM_VALUE(type, dielectric_LUT)
 
  363           else CHECK_ENUM_VALUE(type, firsov)
 
  364             else CHECK_ENUM_VALUE(type, x_ray)
 
  366                 B2FATAL(
"Unknown Optical Surface Type: " << typeString);
 
  368 #undef CHECK_ENUM_VALUE 
  371       addProperties(surface, 
GearDir(parameters, 
"Properties"));
 
  375     void Materials::clear()
 
  378       B2DEBUG(50, 
"Cleaning G4MaterialPropertiesTable");
 
  379       for (G4MaterialPropertiesTable* prop : m_PropTables) 
delete prop;
 
  380       m_PropTables.clear();
 
  382       B2DEBUG(50, 
"Cleaning G4Materials");
 
  383       G4MaterialTable& materials = *G4Material::GetMaterialTable();
 
  384       for (G4Material* mat : materials) 
delete mat;
 
  386       B2DEBUG(50, 
"Cleaning G4Elements");
 
  387       G4ElementTable& elements = *G4Element::GetElementTable();
 
  388       for (G4Element* elm : elements) 
delete elm;
 
  390       B2DEBUG(50, 
"Cleaning G4Isotopes");
 
  391       auto& isotopes = 
const_cast<G4IsotopeTable&
>(*G4Isotope::GetIsotopeTable());
 
  392       for (G4Isotope* iso : isotopes) 
delete iso;
 
  395       delete m_nistMaterialBuilder;
 
  396       delete m_nistElementBuilder;
 
  397       m_nistMaterialBuilder = 
nullptr;
 
  398       m_nistElementBuilder = 
nullptr;
 
  400       B2DEBUG(50, 
"Clean up material cache");
 
  401       m_materialCache.clear();
 
GearDir is the basic class used for accessing the parameter store.
Class to represent a material informaion in the Database.
void setPressure(double pressure)
set the pressure of the material (in default framework units
void setState(int state)
set the state of the material
void addComponent(const GeoMaterialComponent &component)
add a component to the material.
std::vector< GeoMaterialComponent > & getComponents()
get all components
void setName(const std::string &name)
set the name of the material
void setTemperature(double temperature)
set the temperature of the material (in default framework units
void setDensity(double density)
set the density of the material (in default framework units
Represent an optical finish of a surface.
int getFinish() const
get finish of the surface
const std::string & getName() const
get name of the optical surface
double getValue() const
get value for the surface condition
const std::vector< GeoMaterialProperty > & getProperties() const
get all properties
int getType() const
get type of the surface
int getModel() const
get model for the surface
Exception to be thrown in case of an empty result.
Thin wrapper around the Geant4 Material system.
Class to store variables with their name which were sent to the logging service.
Abstract base class for different kinds of events.