9 #include <framework/logging/Logger.h> 
   10 #include <framework/gearbox/GearDir.h> 
   11 #include <framework/database/IntervalOfValidity.h> 
   12 #include <geometry/GeometryManager.h> 
   13 #include <geometry/Materials.h> 
   14 #include <geometry/CreatorManager.h> 
   15 #include <geometry/CreatorBase.h> 
   16 #include <geometry/utilities.h> 
   17 #include <geometry/dbobjects/GeoConfiguration.h> 
   18 #include <geometry/bfieldmap/BFieldMap.h> 
   19 #include <geometry/bfieldmap/BFieldFrameworkInterface.h> 
   20 #include <framework/dbobjects/MagneticField.h> 
   21 #include <framework/database/DBStore.h> 
   24 #include "G4ThreeVector.hh" 
   25 #include "G4LogicalVolume.hh" 
   26 #include "G4PVPlacement.hh" 
   28 #include "G4RunManager.hh" 
   29 #include "G4GeometryManager.hh" 
   30 #include "G4PhysicalVolumeStore.hh" 
   31 #include "G4LogicalVolumeStore.hh" 
   32 #include "G4SolidStore.hh" 
   33 #include "G4RegionStore.hh" 
   34 #include "G4SurfaceProperty.hh" 
   35 #include "G4LogicalBorderSurface.hh" 
   36 #include "G4LogicalSkinSurface.hh" 
   37 #include "G4VisAttributes.hh" 
   38 #include "G4VoxelLimits.hh" 
   41 #include "Geant4GM/volumes/Factory.h" 
   42 #include "RootGM/volumes/Factory.h" 
   43 #include "VGM/volumes/IPlacement.h" 
   44 #include "TGeoManager.h" 
   55   using namespace gearbox;
 
   67     double getTopMinSize(
const std::string& name, EAxis axis, G4LogicalVolume* volume, 
double current)
 
   69       G4VoxelLimits dummyLimits;
 
   71       for (
size_t i = 0; i < volume->GetNoDaughters(); ++i) {
 
   72         G4VPhysicalVolume* daughter = volume->GetDaughter(i);
 
   73         G4AffineTransform trans(daughter->GetRotation(), daughter->GetTranslation());
 
   74         double vmin{0}, vmax{0};
 
   75         daughter->GetLogicalVolume()->GetSolid()->CalculateExtent((EAxis) axis, dummyLimits, trans, vmin, vmax);
 
   76         extent = std::max({extent, std::fabs(vmin), std::fabs(vmax)});
 
   78       B2DEBUG(100, 
"Current global volume size in " << name << 
": " << std::fixed
 
   79               << std::setprecision(std::numeric_limits<double>::max_digits10)
 
   80               << current << 
", needed: " <<  extent);
 
   81       if (current < extent && (extent - current) > Unit::um) {
 
   83           B2WARNING(
"Global volume not large enough in " << name << 
" direction, enlarging from " 
   84                     << current << 
" mm to " << extent << 
" mm");
 
   86           B2DEBUG(10, 
"Setting global volume size to " << name << 
"= +-" << extent << 
" mm");
 
  102     void GeometryManager::clear()
 
  104       B2DEBUG(50, 
"Cleaning up Geometry");
 
  105       for (G4VisAttributes* visAttr : m_VisAttributes) 
delete visAttr;
 
  106       m_VisAttributes.clear();
 
  107       for (
CreatorBase* creator : m_creators) 
delete creator;
 
  109       m_topVolume = 
nullptr;
 
  111       G4GeometryManager::GetInstance()->OpenGeometry();
 
  112       G4PhysicalVolumeStore::Clean();
 
  113       G4LogicalVolumeStore::Clean();
 
  114       G4SolidStore::Clean();
 
  115       G4LogicalBorderSurface::CleanSurfaceTable();
 
  116       G4LogicalSkinSurface::CleanSurfaceTable();
 
  117       G4SurfaceProperty::CleanSurfacePropertyTable();
 
  119       Materials::getInstance().clear();
 
  124       std::string detectorName;
 
  126         detectorName = detectorDir.
getString(
"Name");
 
  127         B2DEBUG(50, 
"Creating geometry for detector: " << detectorName);
 
  128       } 
catch (gearbox::PathEmptyError& e) {
 
  129         B2FATAL(
"Could not read detector name, make sure gearbox is connected and " 
  130                 << detectorDir.
getPath() << 
" points to the geometry description");
 
  133       const double globalWidth  = detectorDir.
getLength(
"Global/width",  0);
 
  134       const double globalHeight = detectorDir.
getLength(
"Global/height", 0);
 
  135       const double globalLength = detectorDir.
getLength(
"Global/length", 0);
 
  136       const std::string globalMaterial = detectorDir.
getString(
"Global/material", 
"Air");
 
  138       GeoConfiguration config(detectorName, globalWidth, globalHeight, globalLength, globalMaterial);
 
  141       Materials& materials = Materials::getInstance();
 
  149       std::set<std::string> componentNames = m_components;
 
  150       std::set<std::string> excludedNames = m_excluded;
 
  151       std::set<std::string> additionalNames = m_additional;
 
  152       if (!m_components.empty() && !m_additional.empty()) {
 
  153         B2WARNING(
"Additional components are ignored when a list of components is provided.");
 
  157       for (
const GearDir& component : detectorDir.
getNodes(
"DetectorComponent")) {
 
  161           name        = component.getString(
"@name");
 
  162           creatorName = component.getString(
"Creator");
 
  163         } 
catch (gearbox::PathEmptyError& e) {
 
  164           B2ERROR(
"Could not find required element Name or Creator for " << component.getPath());
 
  167         const bool isDefault = component.getBool(
"@isDefault", 
true);
 
  170         componentNames.erase(name);
 
  171         excludedNames.erase(name);
 
  172         additionalNames.erase(name);
 
  173         if (!m_components.empty() && m_components.count(name) == 0) {
 
  174           B2DEBUG(50, 
"DetectorComponent " << name << 
" not in list of components, skipping");
 
  177         if (m_components.empty() && !isDefault) {
 
  178           if (m_additional.count(name) == 0) {
 
  179             B2DEBUG(50, 
"DectorComponent " << name << 
" is not enabled by default, skipping");
 
  182             B2DEBUG(50, 
"DectorComponent " << name << 
" is enabled in addition to the default components");
 
  185         if (!m_excluded.empty() && m_excluded.count(name) > 0) {
 
  186           B2DEBUG(10, 
"DetectorComponent " << name << 
" in list of excluded components, skipping");
 
  190         string libraryName = component.getString(
"Creator/@library", 
"");
 
  192           CreatorBase* creator = CreatorManager::getCreator(creatorName, libraryName);
 
  196             B2ERROR(
"Could not load creator " << creatorName << 
" from " << libraryName);
 
  205       auto checkRemaining = [](
const std::string & type, 
const std::set<std::string>& remainingNames) {
 
  206         for (
const std::string& name : remainingNames) {
 
  207           B2ERROR(
"Geometry '" << name << 
"' is specified in list of " 
  208                   << type << 
" but could not be found");
 
  212       checkRemaining(
"components", componentNames);
 
  213       checkRemaining(
"excluded components", excludedNames);
 
  214       checkRemaining(
"additional components", additionalNames);
 
  222       createGeometry(config, type, 
false);
 
  232       BFieldMap::Instance().clear();
 
  236         DBStore::Instance().addConstantOverride(
"MagneticField", fieldmap, 
false);
 
  240       G4RunManager* runManager = G4RunManager::GetRunManager();
 
  241       if (runManager) runManager->ReinitializeGeometry(
true, 
true);
 
  244       B2DEBUG(10, 
"Creating geometry for detector: " << config.
getName());
 
  247       Materials& materials = Materials::getInstance();
 
  255       double xHalfLength = config.
getGlobalWidth() / Unit::cm * CLHEP::cm;
 
  261       G4Box*           top_box = 
new G4Box(
"Top", xHalfLength > 0 ? xHalfLength : 1,
 
  262                                            yHalfLength > 0 ? yHalfLength : 1,
 
  263                                            zHalfLength > 0 ? zHalfLength : 1);
 
  264       G4LogicalVolume* top_log = 
new G4LogicalVolume(top_box, top_mat, 
"Top", 
nullptr, 
nullptr, 
nullptr);
 
  266       m_topVolume = 
new G4PVPlacement(
nullptr, G4ThreeVector(), top_log, 
"Top", 
nullptr, 
false, 0);
 
  267       B2DEBUG(10, 
"Created top volume with x= +-" << config.
getGlobalWidth() << 
" cm, y= +-" 
  271       auto getDensityScale = [
this](
const std::string & name) {
 
  272         std::optional<double> scale;
 
  273         if (
auto it = m_densityScaling.find(name); it != m_densityScaling.end()) {
 
  278       auto globalScale = getDensityScale(
"*");
 
  281         CreatorBase* creator = CreatorManager::getCreator(component.getCreator(), component.getLibrary());
 
  284           auto componentScale = getDensityScale(component.getName());
 
  285           if (componentScale or globalScale) {
 
  286             double scale = globalScale ? *globalScale : 1.0;
 
  287             if (componentScale) scale *= *componentScale;
 
  288             Materials::getInstance().setDensityScale(scale);
 
  291           int oldSolids = G4SolidStore::GetInstance()->size();
 
  292           int oldLogical = G4LogicalVolumeStore::GetInstance()->size();
 
  293           int oldPhysical = G4PhysicalVolumeStore::GetInstance()->size();
 
  295             if (!useDB) 
throw CreatorBase::DBNotImplemented();
 
  296             creator->
createFromDB(component.getName(), *top_log, type);
 
  297             B2DEBUG(50, 
"called creator " << component.getCreator() << 
" to create component " << component.getName() << 
" from DB");
 
  299           } 
catch (CreatorBase::DBNotImplemented& e) {
 
  300             GearDir parameters = Gearbox::getInstance().getDetectorComponent(component.getName());
 
  301             creator->
create(parameters, *top_log, type);
 
  302             B2DEBUG(50, 
"called creator " << component.getCreator() << 
" to create component " << component.getName() << 
" from Gearbox");
 
  304           int newSolids = G4SolidStore::GetInstance()->size() - oldSolids;
 
  305           int newLogical = G4LogicalVolumeStore::GetInstance()->size() - oldLogical;
 
  306           int newPhysical = G4PhysicalVolumeStore::GetInstance()->size() - oldPhysical;
 
  307           B2DEBUG(50, 
"DetectorComponent " << component.getName() << 
" created " << newSolids
 
  308                   << 
" solids, " << newLogical << 
" logical volumes and " 
  309                   << newPhysical << 
" physical volumes");
 
  310           m_creators.push_back(creator);
 
  312           Materials::getInstance().resetDensityScale();
 
  313           if (m_assignRegions) {
 
  315             G4Region* region {
nullptr};
 
  318             for (
size_t i = 0; i < top_log->GetNoDaughters(); ++i) {
 
  319               G4LogicalVolume* vol = top_log->GetDaughter(i)->GetLogicalVolume();
 
  321               if (!vol->GetRegion()) {
 
  323                 if (!region) region = G4RegionStore::GetInstance()->FindOrCreateRegion(component.getName());
 
  324                 vol->SetRegion(region);
 
  326                 region->AddRootLogicalVolume(vol);
 
  333       int newSolids = G4SolidStore::GetInstance()->size();
 
  334       int newLogical = G4LogicalVolumeStore::GetInstance()->size();
 
  335       int newPhysical = G4PhysicalVolumeStore::GetInstance()->size();
 
  336       B2DEBUG(50, 
"Created a total of " << newSolids << 
" solids, " << newLogical
 
  337               << 
" logical volumes and " << newPhysical << 
" physical volumes");
 
  340       top_box->SetXHalfLength(getTopMinSize(
"x", kXAxis, top_log, xHalfLength));
 
  341       top_box->SetYHalfLength(getTopMinSize(
"y", kYAxis, top_log, yHalfLength));
 
  342       top_box->SetZHalfLength(getTopMinSize(
"z", kZAxis, top_log, zHalfLength));
 
  344       B2DEBUG(50, 
"Optimizing geometry and creating lookup tables ...");
 
  345       G4GeometryManager::GetInstance()->CloseGeometry(
true, LogSystem::Instance().isLevelEnabled(LogConfig::c_Debug, 200, PACKAGENAME()));
 
  348     void GeometryManager::createTGeoRepresentation()
 
  351         B2ERROR(
"No Geometry found, please create a geometry before converting it to ROOT::TGeo");
 
  355       Geant4GM::Factory g4Factory;
 
  356       if (LogSystem::Instance().isLevelEnabled(LogConfig::c_Debug, 200, PACKAGENAME())) {
 
  357         g4Factory.SetDebug(1);
 
  359       g4Factory.Import(m_topVolume);
 
  360       RootGM::Factory rtFactory;
 
  361       rtFactory.SetIgnore(1);
 
  362       if (LogSystem::Instance().isLevelEnabled(LogConfig::c_Debug, 200, PACKAGENAME())) {
 
  363         rtFactory.SetDebug(1);
 
  365       g4Factory.Export(&rtFactory);
 
  366       gGeoManager->CloseGeometry();
 
  367       delete g4Factory.Top();
 
  368       delete rtFactory.Top();
 
  371     G4VisAttributes* GeometryManager::newVisAttributes()
 
  373       m_VisAttributes.push_back(
new G4VisAttributes());
 
  374       return m_VisAttributes.back();
 
Simple BFieldComponent to just wrap the existing BFieldMap with the new BFieldManager.
GearDir is the basic class used for accessing the parameter store.
virtual std::string getString(const std::string &path="") const noexcept(false) override
Get the parameter path as a string.
Describe one component of the Geometry.
configuration of the geometry
const std::vector< GeoComponent > & getComponents() const
get list of components
void addMaterial(const GeoMaterial &material)
add a material to the list of materials
void addComponent(const GeoComponent &component)
add a component to the list of components
const std::vector< GeoMaterial > & getMaterials() const
get List of Materials
double getGlobalWidth() const
get the half width of the global volume, that is length in + and - x direction.
const std::string & getName() const
get the name of the detector
double getGlobalHeight() const
get the half height of the global volume, that is length in + and - y direction.
const std::string & getGlobalMaterial() const
get the material of the global volume
double getGlobalLength() const
get the half length of the global volume, that is length in + and - z direction.
Class to represent a material informaion in the Database.
A class that describes the interval of experiments/runs for which an object in the database is valid.
std::string getPath() const
Return path of the current interface.
double getLength(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard length unit.
std::vector< GearDir > getNodes(const std::string &path="") const
Get vector of GearDirs which point to all the nodes the given path evaluates to.
Pure virtual base class for all geometry creators.
virtual void createFromDB(const std::string &name, G4LogicalVolume &topVolume, GeometryTypes type)
Function to create the geometry from the Database.
virtual void create(const GearDir &content, G4LogicalVolume &topVolume, GeometryTypes type)=0
Function to actually create the geometry, has to be overridden by derived classes.
virtual void createPayloads(const GearDir &content, const IntervalOfValidity &iov)
Function to create the geometry database.
Class to manage the creation and conversion of the geometry.
Thin wrapper around the Geant4 Material system.
GeoMaterial createMaterialConfig(const gearbox::Interface ¶meters)
Create Material from XML description.
G4Material * createMaterial(const gearbox::Interface ¶meters)
Create a material from the parameters specified by parameters.
void setVisibility(G4LogicalVolume &volume, bool visible)
Helper function to quickly set the visibility of a given volume.
GeometryTypes
Flag indiciating the type of geometry to be used.
Abstract base class for different kinds of events.