Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-15 08:21:56

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