Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-14 09:34:11

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 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Material/GridSurfaceMaterial.hpp"
0012 #include "Acts/Material/Material.hpp"
0013 #include "Acts/Material/MaterialSlab.hpp"
0014 #include "Acts/Material/MergedMaterialMarker.hpp"
0015 #include "Acts/Utilities/AxisDefinitions.hpp"
0016 #include "Acts/Utilities/Diagnostics.hpp"
0017 #include "Acts/Utilities/IAxis.hpp"
0018 #include "ActsPlugins/Json/GridJsonConverter.hpp"
0019 #include "ActsPlugins/Json/MaterialJsonConverter.hpp"
0020 #include "ActsPlugins/Json/SurfaceMaterialJsonConverter.hpp"
0021 
0022 #include <memory>
0023 #include <numbers>
0024 #include <stdexcept>
0025 #include <variant>
0026 #include <vector>
0027 
0028 #include <nlohmann/json.hpp>
0029 
0030 // These tests intentionally exercise the deprecated material format.
0031 ACTS_PUSH_IGNORE_DEPRECATED()
0032 
0033 using namespace Acts;
0034 
0035 namespace ActsTests {
0036 
0037 BOOST_AUTO_TEST_SUITE(JsonSuite)
0038 
0039 BOOST_AUTO_TEST_CASE(IndexedSurfaceMaterial2DTests) {
0040   std::vector<MaterialSlab> material;
0041   material.emplace_back(Material::Vacuum(), 1.0);  // vacuum
0042   material.emplace_back(Material::fromMolarDensity(1.0, 2.0, 3.0, 4.0, 5.0),
0043                         1.0);
0044   material.emplace_back(
0045       Material::fromMolarDensity(11.0, 12.0, 13.0, 14.0, 15.0), 1.0);
0046   material.emplace_back(
0047       Material::fromMolarDensity(21.0, 22.0, 23.0, 24.0, 25.0), 1.0);
0048 
0049   // 2 bins in z, 4 bins in phi
0050   auto axisZ = IAxis::createEquidistant(AxisBoundaryType::Bound, -1.0, 1.0, 2);
0051   auto axisPhi = IAxis::createEquidistant(
0052       AxisBoundaryType::Closed, -std::numbers::pi, std::numbers::pi, 4);
0053 
0054   std::vector<std::vector<std::size_t>> indexPayload = {
0055       std::vector<std::size_t>{1u, 1u, 0u, 2u},
0056       std::vector<std::size_t>{0u, 3u, 3u, 0u}};
0057 
0058   // Create the indexed material grid
0059   auto ism = GridSurfaceMaterial::createIndexed(*axisZ, *axisPhi, material,
0060                                                 indexPayload);
0061 
0062   nlohmann::json jMaterial = SurfaceMaterialJsonConverter::toJson(*ism);
0063 
0064   // Run a few tests
0065   BOOST_CHECK_EQUAL(jMaterial["type"], "grid");
0066   BOOST_CHECK_EQUAL(jMaterial["accessor"]["type"], "indexed");
0067   BOOST_CHECK(!jMaterial.contains("global_to_grid_local"));
0068   BOOST_CHECK(!jMaterial.contains("bound_to_grid_local"));
0069 
0070   // Read it back in
0071   auto ismRead = SurfaceMaterialJsonConverter::fromJson(jMaterial);
0072   BOOST_REQUIRE(ismRead != nullptr);
0073 
0074   // Check if it's the right type - the reader always resolves "grid" json
0075   // into the concrete GridSurfaceMaterial class
0076   const auto* ismReadTyped =
0077       dynamic_cast<const GridSurfaceMaterial*>(ismRead.get());
0078   BOOST_REQUIRE(ismReadTyped != nullptr);
0079 
0080   Vector2 l0(-0.5, -std::numbers::pi * 0.75);
0081   BOOST_CHECK_EQUAL(ismReadTyped->materialSlab(l0).material().X0(), 1.);
0082 
0083   Vector2 l1(0.5, std::numbers::pi / 4.);
0084   BOOST_CHECK_EQUAL(ismReadTyped->materialSlab(l1).material().X0(), 21.);
0085 
0086   Vector2 l2(-0.5, std::numbers::pi / 4.);
0087   BOOST_CHECK(ismReadTyped->materialSlab(l2).material().isVacuum());
0088 
0089   // Check the storage is indexed and the material is filled
0090   const auto& indexed =
0091       std::get<GridSurfaceMaterial::Indexed>(ismReadTyped->storage());
0092 
0093   BOOST_REQUIRE(indexed.material.size() == 4);
0094   BOOST_CHECK(indexed.material[0].material().isVacuum());
0095   BOOST_CHECK_EQUAL(indexed.material[1].material().X0(), 1.);
0096   BOOST_CHECK_EQUAL(indexed.material[2].material().X0(), 11.);
0097   BOOST_CHECK_EQUAL(indexed.material[3].material().X0(), 21.);
0098 }
0099 
0100 BOOST_AUTO_TEST_CASE(GridSurfaceMaterialDirectStorageRoundTrip) {
0101   // Direct-storage grid material JSON I/O: writer and reader both work
0102   // generically off GridSurfaceMaterial::storage(), with no
0103   // BoundToGridLocal/GlobalToGridLocal concept involved - local lookup is
0104   // always (loc0, loc1) directly onto the grid axes.
0105   std::vector<std::vector<MaterialSlab>> material2x2;
0106   std::vector<MaterialSlab> materialRow0;
0107   materialRow0.emplace_back(Material::Vacuum(), 0.0);  // vacuum
0108   materialRow0.emplace_back(Material::fromMolarDensity(1.0, 2.0, 3.0, 4.0, 5.0),
0109                             1.0);
0110   std::vector<MaterialSlab> materialRow1;
0111   materialRow1.emplace_back(
0112       Material::fromMolarDensity(11.0, 12.0, 13.0, 14.0, 15.0), 2.0);
0113   materialRow1.emplace_back(
0114       Material::fromMolarDensity(21.0, 22.0, 23.0, 24.0, 25.0), 3.0);
0115   material2x2.push_back(std::move(materialRow0));
0116   material2x2.push_back(std::move(materialRow1));
0117 
0118   auto axisX = IAxis::createEquidistant(AxisBoundaryType::Bound, 0.0, 2.0, 2);
0119   auto axisY = IAxis::createEquidistant(AxisBoundaryType::Bound, 0.0, 2.0, 2);
0120 
0121   auto gsm = GridSurfaceMaterial::createDirect(*axisX, *axisY, material2x2);
0122   BOOST_REQUIRE(gsm != nullptr);
0123 
0124   nlohmann::json jMaterial = SurfaceMaterialJsonConverter::toJson(*gsm);
0125 
0126   BOOST_CHECK_EQUAL(jMaterial["type"], "grid");
0127   BOOST_CHECK_EQUAL(jMaterial["accessor"]["type"], "direct");
0128   BOOST_REQUIRE(jMaterial["accessor"].contains("grid"));
0129   BOOST_CHECK(jMaterial["accessor"]["grid"].contains("axes"));
0130   BOOST_CHECK(jMaterial["accessor"]["grid"].contains("data"));
0131   BOOST_CHECK(!jMaterial.contains("global_to_grid_local"));
0132   BOOST_CHECK(!jMaterial.contains("bound_to_grid_local"));
0133 
0134   // Read it back in
0135   auto gsmRead = SurfaceMaterialJsonConverter::fromJson(jMaterial);
0136   BOOST_REQUIRE(gsmRead != nullptr);
0137 
0138   const auto* gsmReadTyped =
0139       dynamic_cast<const GridSurfaceMaterial*>(gsmRead.get());
0140   BOOST_REQUIRE(gsmReadTyped != nullptr);
0141 
0142   BOOST_CHECK(
0143       gsmReadTyped->materialSlab(Vector2{0.5, 0.5}).material().isVacuum());
0144   BOOST_CHECK_EQUAL(
0145       gsmReadTyped->materialSlab(Vector2{0.5, 1.5}).material().X0(), 1.);
0146   BOOST_CHECK_EQUAL(
0147       gsmReadTyped->materialSlab(Vector2{1.5, 0.5}).material().X0(), 11.);
0148   BOOST_CHECK_EQUAL(
0149       gsmReadTyped->materialSlab(Vector2{1.5, 1.5}).material().X0(), 21.);
0150 }
0151 
0152 BOOST_AUTO_TEST_CASE(MergedMaterialMarkerRoundTrip) {
0153   // The marker left behind by a lossy portal merge must survive a JSON
0154   // round-trip so it can be picked up by downstream tooling.
0155   MergedMaterialMarker marker;
0156 
0157   nlohmann::json jMaterial = SurfaceMaterialJsonConverter::toJson(marker);
0158   BOOST_CHECK_EQUAL(jMaterial["type"], "merged-material-marker");
0159 
0160   auto markerRead = SurfaceMaterialJsonConverter::fromJson(jMaterial);
0161   BOOST_REQUIRE(markerRead != nullptr);
0162   BOOST_CHECK(dynamic_cast<const MergedMaterialMarker*>(markerRead.get()) !=
0163               nullptr);
0164 }
0165 
0166 BOOST_AUTO_TEST_SUITE_END()
0167 
0168 }  // namespace ActsTests
0169 
0170 ACTS_POP_IGNORE_DEPRECATED()