Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:52

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 // This file contains systematic tests to verify the local->global->local
0010 // transformation roundtrip for all available surfaces with a large range of
0011 // possible parameters.
0012 
0013 #include <boost/test/data/test_case.hpp>
0014 #include <boost/test/unit_test.hpp>
0015 
0016 #include "Acts/Definitions/Algebra.hpp"
0017 #include "Acts/Definitions/Common.hpp"
0018 #include "Acts/Geometry/GeometryContext.hpp"
0019 #include "Acts/Surfaces/ConeSurface.hpp"
0020 #include "Acts/Surfaces/CurvilinearSurface.hpp"
0021 #include "Acts/Surfaces/CylinderSurface.hpp"
0022 #include "Acts/Surfaces/DiscSurface.hpp"
0023 #include "Acts/Surfaces/PerigeeSurface.hpp"
0024 #include "Acts/Surfaces/PlaneSurface.hpp"
0025 #include "Acts/Surfaces/StrawSurface.hpp"
0026 #include "Acts/Surfaces/Surface.hpp"
0027 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0028 #include "Acts/Utilities/Result.hpp"
0029 #include "Acts/Utilities/UnitVectors.hpp"
0030 
0031 #include <cmath>
0032 #include <limits>
0033 #include <numbers>
0034 
0035 namespace {
0036 
0037 namespace bdata = boost::unit_test::data;
0038 using namespace Acts;
0039 
0040 constexpr auto eps = 8 * std::numeric_limits<double>::epsilon();
0041 const GeometryContext geoCtx;
0042 
0043 void runTest(const Surface& surface, double l0, double l1, double phi,
0044              double theta) {
0045   const Vector3 dir = makeDirectionFromPhiTheta(phi, theta);
0046 
0047   // convert local-to-global
0048   Vector3 sentinel = Vector3::Random();
0049   Vector3 pos = surface.localToGlobal(geoCtx, Vector2(l0, l1), dir);
0050   BOOST_CHECK_MESSAGE(pos != sentinel, "Position was not changed");
0051   BOOST_CHECK_MESSAGE(
0052       std::isfinite(pos[0]),
0053       "Position " << pos.transpose() << " contains non-finite entries");
0054   BOOST_CHECK_MESSAGE(
0055       std::isfinite(pos[1]),
0056       "Position " << pos.transpose() << " contains non-finite entries");
0057   BOOST_CHECK_MESSAGE(
0058       std::isfinite(pos[2]),
0059       "Position " << pos.transpose() << " contains non-finite entries");
0060   BOOST_CHECK_MESSAGE(
0061       surface.isOnSurface(geoCtx, pos, dir),
0062       "Position " << pos.transpose() << " is not on the surface");
0063 
0064   // convert global-to-local
0065   auto lpResult = surface.globalToLocal(geoCtx, pos, dir);
0066   BOOST_CHECK(lpResult.ok());
0067   CHECK_CLOSE_OR_SMALL(lpResult.value()[ePos0], l0, eps, eps);
0068   CHECK_CLOSE_OR_SMALL(lpResult.value()[ePos1], l1, eps, eps);
0069 }
0070 
0071 // test datasets
0072 
0073 // local positions
0074 const auto posAngle = bdata::xrange(-std::numbers::pi, std::numbers::pi, 0.25);
0075 const auto posPositiveNonzero = bdata::xrange(0.25, 1., 0.25);
0076 const auto posPositive = bdata::make(0.) + posPositiveNonzero;
0077 const auto posSymmetric = bdata::xrange(-1., 1., 0.25);
0078 // direction angles
0079 const auto phis =
0080     bdata::xrange(-std::numbers::pi, std::numbers::pi, std::numbers::pi / 4.);
0081 const auto thetasNoForwardBackward = bdata::xrange(
0082     std::numbers::pi / 4., std::numbers::pi, std::numbers::pi / 4.);
0083 const auto thetas =
0084     bdata::make({0., std::numbers::pi}) + thetasNoForwardBackward;
0085 
0086 // different surfaces
0087 // parameters must be chosen such that all possible local positions (as defined
0088 // in the datasets above) represent valid points on the surface.
0089 const auto cones = bdata::make({
0090     Surface::makeShared<ConeSurface>(Transform3::Identity(),
0091                                      0.5 /* opening angle */),
0092 });
0093 const auto cylinders = bdata::make({
0094     Surface::makeShared<CylinderSurface>(Transform3::Identity(),
0095                                          10. /* radius */, 100 /* half z */),
0096 });
0097 const auto discs = bdata::make({
0098     Surface::makeShared<DiscSurface>(Transform3::Identity(), 0 /* radius min */,
0099                                      100 /* radius max */),
0100 });
0101 const auto perigees = bdata::make({
0102     Surface::makeShared<PerigeeSurface>(Vector3(0, 0, -1.5)),
0103 });
0104 const auto planes = bdata::make({
0105     CurvilinearSurface(Vector3(1, 2, 3), Vector3::UnitX()).planeSurface(),
0106     CurvilinearSurface(Vector3(-2, -3, -4), Vector3::UnitY()).planeSurface(),
0107     CurvilinearSurface(Vector3(3, -4, 5), Vector3::UnitZ()).planeSurface(),
0108 });
0109 const auto straws = bdata::make({
0110     Surface::makeShared<StrawSurface>(Transform3::Identity(), 2. /* radius */,
0111                                       200. /* half z */),
0112 });
0113 
0114 }  // namespace
0115 
0116 BOOST_AUTO_TEST_SUITE(SurfaceLocalToGlobalRoundtrip)
0117 
0118 BOOST_DATA_TEST_CASE(ConeSurface,
0119                      cones* posAngle* posPositiveNonzero* phis* thetas, surface,
0120                      lphi, lz, phi, theta) {
0121   // TODO extend lz to zero after fixing the transform implementation
0122   // local parameter r*phi has limits that depend on the z position
0123   const auto r = lz * surface->bounds().tanAlpha();
0124   // local coordinates are singular at z = 0 -> normalize local phi
0125   runTest(*surface, (0 < lz) ? (r * lphi) : 0., lz, phi, theta);
0126 }
0127 
0128 BOOST_DATA_TEST_CASE(CylinderSurface,
0129                      cylinders* posSymmetric* posSymmetric* phis* thetas,
0130                      surface, lrphi, lz, phi, theta) {
0131   runTest(*surface, lrphi, lz, phi, theta);
0132 }
0133 
0134 BOOST_DATA_TEST_CASE(DiscSurface, discs* posPositive* posAngle* phis* thetas,
0135                      surface, lr, lphi, phi, theta) {
0136   // local coordinates are singular at r = 0 -> normalize local phi
0137   runTest(*surface, lr, (0 < lr) ? lphi : 0., phi, theta);
0138 }
0139 
0140 BOOST_DATA_TEST_CASE(
0141     PerigeeSurface,
0142     perigees* posSymmetric* posSymmetric* phis* thetasNoForwardBackward,
0143     surface, d0, z0, phi, theta) {
0144   // TODO extend theta to forward/back extreme cases fixing the transform
0145   runTest(*surface, d0, z0, phi, theta);
0146 }
0147 
0148 BOOST_DATA_TEST_CASE(PlaneSurface,
0149                      planes* posSymmetric* posSymmetric* phis* thetas, surface,
0150                      l0, l1, phi, theta) {
0151   runTest(*surface, l0, l1, phi, theta);
0152 }
0153 
0154 BOOST_DATA_TEST_CASE(
0155     StrawSurface,
0156     straws* posSymmetric* posSymmetric* phis* thetasNoForwardBackward, surface,
0157     lr, lz, phi, theta) {
0158   // TODO extend theta to forward/back extreme cases fixing the transform
0159   runTest(*surface, lr, lz, phi, theta);
0160 }
0161 
0162 BOOST_AUTO_TEST_SUITE_END()