diff --git a/Plugins/GeoModel/CMakeLists.txt b/Plugins/GeoModel/CMakeLists.txt index 5e40ade3230..ba974e82649 100644 --- a/Plugins/GeoModel/CMakeLists.txt +++ b/Plugins/GeoModel/CMakeLists.txt @@ -5,9 +5,11 @@ add_library( SHARED src/GeoModelBlueprintCreater.cpp src/GeoModelConversionError.cpp + src/GeoModelToDetectorVolume.cpp src/GeoModelReader.cpp src/GeoModelDetectorElement.cpp src/GeoModelDetectorSurfaceFactory.cpp + src/GeoModelMaterialConverter.cpp src/detail/GeoBoxConverter.cpp src/detail/GeoTrdConverter.cpp src/detail/GeoTubeConverter.cpp diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelMaterialConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelMaterialConverter.hpp new file mode 100644 index 00000000000..bde01e92f60 --- /dev/null +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelMaterialConverter.hpp @@ -0,0 +1,24 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Material/Material.hpp" + +class GeoMaterial; + +namespace Acts::GeoModel { + +/// @brief Convert GeoMaterial to Acts::Material +/// +/// @param gm The GeoMaterial to be converted +/// @return the Acts::Material +Material geoMaterialConverter(const GeoMaterial* gm, + bool useMolarDensity = true); + +} // namespace Acts::GeoModel diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp new file mode 100644 index 00000000000..e71863a49b6 --- /dev/null +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp @@ -0,0 +1,28 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Detector/DetectorVolume.hpp" + +#include "GeoModelKernel/GeoDefinitions.h" + +class GeoShape; + +namespace Acts::GeoModel { + +/// @brief Convert a GeoModel shape to a DetectorVolume +/// +/// @param shape the GeoModel shape +/// @param transform the transform to be applied +/// @return the DetectorVolume +std::shared_ptr convertVolume( + const GeometryContext& context, const GeoShape* shape, + const std::string& name, const GeoTrf::Transform3D transform); + +} // namespace Acts::GeoModel diff --git a/Plugins/GeoModel/src/GeoModelMaterialConverter.cpp b/Plugins/GeoModel/src/GeoModelMaterialConverter.cpp new file mode 100644 index 00000000000..e60dbca87ed --- /dev/null +++ b/Plugins/GeoModel/src/GeoModelMaterialConverter.cpp @@ -0,0 +1,38 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/GeoModel/GeoModelMaterialConverter.hpp" + +#include "Acts/Material/Material.hpp" + +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/Units.h" + +Acts::Material Acts::GeoModel::geoMaterialConverter(const GeoMaterial* gm, + bool useMolarDensity) { + constexpr double densityCnvFactor = 1. / GeoModelKernelUnits::gram; + double x0 = gm->getRadLength(); + double l0 = gm->getIntLength(); + double density = gm->getDensity() * densityCnvFactor; + double A = 0.; + double Z = 0.; + // Get number elements + int numberOfElements = gm->getNumElements(); + // Loop + for (int iEl = 0; iEl < numberOfElements; ++iEl) { + const GeoElement* geoEl = gm->getElement(iEl); + double fraction = gm->getFraction(iEl); + A += fraction * (geoEl->getA() / GeoModelKernelUnits::gram); + Z += fraction * geoEl->getZ(); + } + if (useMolarDensity) { + return Material::fromMolarDensity(x0, l0, A, Z, density); + } else { + return Material::fromMassDensity(x0, l0, A, Z, density); + } +} diff --git a/Plugins/GeoModel/src/GeoModelToDetectorVolume.cpp b/Plugins/GeoModel/src/GeoModelToDetectorVolume.cpp new file mode 100644 index 00000000000..2b567337f2e --- /dev/null +++ b/Plugins/GeoModel/src/GeoModelToDetectorVolume.cpp @@ -0,0 +1,168 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp" + +#include "Acts/Detector/GeometryIdGenerator.hpp" +#include "Acts/Detector/PortalGenerators.hpp" +#include "Acts/Geometry/CuboidVolumeBounds.hpp" +#include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrapezoidVolumeBounds.hpp" +#include "Acts/Navigation/InternalNavigation.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Acts::GeoModel { + +std::shared_ptr convertVolume( + const GeometryContext& context, const GeoShape* shape, + const std::string& name, const GeoTrf::Transform3D transform) { + auto portalGenerator = Experimental::defaultPortalAndSubPortalGenerator(); + if (shape->typeID() == GeoTube::getClassTypeID()) { + const GeoTube* tube = static_cast(shape); + std::shared_ptr bounds = + std::make_shared(tube->getRMin(), tube->getRMax(), + tube->getZHalfLength()); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else if (shape->typeID() == GeoTubs::getClassTypeID()) { + const GeoTubs* tubs = static_cast(shape); + std::shared_ptr bounds = + std::make_shared(tubs->getRMin(), tubs->getRMax(), + tubs->getZHalfLength(), + tubs->getDPhi() / 2); + GeoTrf::Transform3D newTransform = + transform * GeoTrf::RotateZ3D(tubs->getSPhi() + 0.5 * tubs->getDPhi()); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else if (shape->typeID() == GeoBox::getClassTypeID()) { + const GeoBox* box = static_cast(shape); + std::shared_ptr bounds = + std::make_shared(box->getXHalfLength(), + box->getYHalfLength(), + box->getZHalfLength()); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else if (shape->typeID() == GeoSimplePolygonBrep::getClassTypeID()) { + const GeoSimplePolygonBrep* brep = + static_cast(shape); + double xmin{0}, xmax{0}, ymin{0}, ymax{0}, zmin{0}, zmax{0}; + brep->extent(xmin, ymin, zmin, xmax, ymax, zmax); + std::shared_ptr bounds = + std::make_shared( + (xmax - xmin) / 2, (ymax - ymin) / 2, (zmax - zmin) / 2); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else if (shape->typeID() == GeoTrd::getClassTypeID()) { + const GeoTrd* trd = static_cast(shape); + double x1 = trd->getXHalfLength1(); + double x2 = trd->getXHalfLength2(); + double y1 = trd->getYHalfLength1(); + double y2 = trd->getYHalfLength2(); + double z = trd->getZHalfLength(); + if (y1 == y2) { + if (x1 <= x2) { + // y axis in ACTS is z axis in geomodel + std::shared_ptr bounds = + std::make_shared(x1, x2, z, y1); + constexpr double rotationAngle = M_PI / 2; + GeoTrf::Transform3D newTransform = + transform * GeoTrf::RotateX3D(rotationAngle); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else { + std::shared_ptr bounds = + std::make_shared(x2, x1, z, y1); + constexpr double rotationAngle = M_PI; + GeoTrf::Transform3D newTransform = transform * + GeoTrf::RotateY3D(rotationAngle) * + GeoTrf::RotateZ3D(rotationAngle); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } + } else if (x1 == x2) { + if (y1 < y2) { + std::shared_ptr bounds = + std::make_shared(y1, y2, z, x1); + auto rotationAngle = M_PI / 2; + GeoTrf::Transform3D newTransform = transform * + GeoTrf::RotateZ3D(rotationAngle) * + GeoTrf::RotateX3D(rotationAngle); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else { + std::shared_ptr bounds = + std::make_shared(y2, y1, z, x1); + auto rotationAngle = M_PI; + GeoTrf::Transform3D newTransform = + transform * GeoTrf::RotateX3D(rotationAngle) * + GeoTrf::RotateZ3D(rotationAngle / 2) * + GeoTrf::RotateX3D(rotationAngle / 2); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } + } else { + throw std::runtime_error("FATAL: Translating GeoTrd to ACTS failed"); + } + } else if (shape->typeID() == GeoShapeUnion::getClassTypeID()) { + const GeoShapeUnion* unionShape = static_cast(shape); + double xmin{0}, xmax{0}, ymin{0}, ymax{0}, zmin{0}, zmax{0}; + unionShape->extent(xmin, ymin, zmin, xmax, ymax, zmax); + std::shared_ptr bounds = + std::make_shared( + (xmax - xmin) / 2, (ymax - ymin) / 2, (zmax - zmin) / 2); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else if (shape->typeID() == GeoShapeSubtraction::getClassTypeID()) { + // Go down the left side (opA) of the subtraction until we reach a normal + // shape + const GeoShapeSubtraction* subtractionShape = + static_cast(shape); + const GeoShape* shapeA = subtractionShape->getOpA(); + return convertVolume(context, shapeA, name, transform); + } else if (shape->typeID() == GeoPcon::getClassTypeID()) { + // Will change in future, get bounding box for now + double xmin{0}, xmax{0}, ymin{0}, ymax{0}, zmin{0}, zmax{0}; + const GeoPcon* pcon = static_cast(shape); + pcon->extent(xmin, ymin, zmin, xmax, ymax, zmax); + std::shared_ptr bounds = + std::make_shared( + (xmax - xmin) / 2, (ymax - ymin) / 2, (zmax - zmin) / 2); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } + if (shape->typeID() == GeoShapeShift::getClassTypeID()) { + const GeoShapeShift* shiftShape = static_cast(shape); + const GeoShape* shapeOp = shiftShape->getOp(); + GeoTrf::Transform3D newTransform = transform * shiftShape->getX(); + return convertVolume(context, shapeOp, name, newTransform); + } + throw std::runtime_error("FATAL: Unsupported GeoModel shape"); +} + +} // namespace Acts::GeoModel