Skip to content

Commit

Permalink
refactor!: Refactor MaterialSlab combination (#2783)
Browse files Browse the repository at this point in the history
IMO combining material is outside the scope of a constructor for `MaterialSlab` and it can be useful to only combine two
  • Loading branch information
andiwand authored Dec 11, 2023
1 parent f7106bc commit cf30700
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 16 deletions.
25 changes: 18 additions & 7 deletions Core/include/Acts/Material/MaterialSlab.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ namespace Acts {
/// @see Material for a description of the available parameters.
class MaterialSlab {
public:
/// Combine material properties of two layers by averaging them.
///
/// @param layerA Input layer A to average over.
/// @param layerB Input layer B to average over.
///
/// @return The resulting object has the combined thickness of all layers but just
/// one set of appropriately averaged material constants.
static MaterialSlab averageLayers(const MaterialSlab& layerA,
const MaterialSlab& layerB);

/// Combine material properties of multiple layers by averaging them.
///
/// @param layers Input layers to average over.
///
/// @return The resulting object has the combined thickness of all layers but just
/// one set of appropriately averaged material constants.
static MaterialSlab averageLayers(const std::vector<MaterialSlab>& layers);

/// Construct vacuum without thickness.
MaterialSlab() = default;
/// Construct vacuum with thickness.
Expand All @@ -33,13 +51,6 @@ class MaterialSlab {
/// @param material is the material description
/// @param thickness is the thickness of the material
MaterialSlab(const Material& material, float thickness);
/// Construct by averaging the material properties over multiple layers.
///
/// @param layers Input layers to average over.
///
/// The resulting object has the combined thickness of all layers but just
/// one set of appropriately averaged material constants.
MaterialSlab(const std::vector<MaterialSlab>& layers);
~MaterialSlab() = default;

MaterialSlab(MaterialSlab&&) = default;
Expand Down
29 changes: 21 additions & 8 deletions Core/src/Material/MaterialSlab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@
#include "Acts/Material/detail/AverageMaterials.hpp"

#include <limits>
#include <numeric>
#include <ostream>
#include <stdexcept>

namespace Acts {

namespace {
static constexpr auto eps = 2 * std::numeric_limits<float>::epsilon();
}

Acts::MaterialSlab::MaterialSlab(float thickness) : m_thickness(thickness) {}
MaterialSlab::MaterialSlab(float thickness) : m_thickness(thickness) {}

Acts::MaterialSlab::MaterialSlab(const Material& material, float thickness)
MaterialSlab::MaterialSlab(const Material& material, float thickness)
: m_material(material),
m_thickness(thickness),
m_thicknessInX0((eps < material.X0()) ? (thickness / material.X0()) : 0),
Expand All @@ -28,8 +33,13 @@ Acts::MaterialSlab::MaterialSlab(const Material& material, float thickness)
}
}

Acts::MaterialSlab::MaterialSlab(const std::vector<MaterialSlab>& layers)
: MaterialSlab() {
MaterialSlab MaterialSlab::averageLayers(const MaterialSlab& layerA,
const MaterialSlab& layerB) {
return detail::combineSlabs(layerA, layerB);
}

MaterialSlab MaterialSlab::averageLayers(
const std::vector<MaterialSlab>& layers) {
// NOTE 2020-08-26 msmk
// the reduce work best (in the numerical stability sense) if the input
// layers are sorted by thickness/mass density. then, the later terms
Expand All @@ -38,12 +48,14 @@ Acts::MaterialSlab::MaterialSlab(const std::vector<MaterialSlab>& layers)
// but I am not sure if this is actually a problem.
// NOTE yes, this loop is exactly like std::reduce which apparently does not
// exist on gcc 8 although it is required by C++17.
MaterialSlab result;
for (const auto& layer : layers) {
*this = detail::combineSlabs(*this, layer);
result = detail::combineSlabs(result, layer);
}
return result;
}

void Acts::MaterialSlab::scaleThickness(float scale) {
void MaterialSlab::scaleThickness(float scale) {
if (scale < 0) {
throw std::runtime_error("scale < 0");
}
Expand All @@ -53,8 +65,9 @@ void Acts::MaterialSlab::scaleThickness(float scale) {
m_thicknessInL0 *= scale;
}

std::ostream& Acts::operator<<(std::ostream& os,
const MaterialSlab& materialSlab) {
std::ostream& operator<<(std::ostream& os, const MaterialSlab& materialSlab) {
os << materialSlab.material() << "|t=" << materialSlab.thickness();
return os;
}

} // namespace Acts
2 changes: 1 addition & 1 deletion Tests/UnitTests/Core/Material/MaterialSlabTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ BOOST_AUTO_TEST_CASE(construct_compound) {
MaterialSlab b(Material::fromMolarDensity(2., 4., 6., 8., 10.), 2.);
MaterialSlab c(Material::fromMolarDensity(4., 8., 12., 16., 20.), 3.);
std::vector<MaterialSlab> components = {a, b, c};
MaterialSlab abc(components);
MaterialSlab abc = MaterialSlab::averageLayers(components);

// consistency checks
CHECK_CLOSE_REL(abc.thickness() / abc.material().X0(), abc.thicknessInX0(),
Expand Down

0 comments on commit cf30700

Please sign in to comment.