Skip to content

Commit

Permalink
Add sense evaluator for testing (#1168)
Browse files Browse the repository at this point in the history
  • Loading branch information
sethrj committed Apr 3, 2024
1 parent 5edf749 commit 4dd382f
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/orange/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ list(APPEND SOURCES
orangeinp/detail/NodeSimplifier.cc
orangeinp/detail/PostfixLogicBuilder.cc
orangeinp/detail/ProtoMap.cc
orangeinp/detail/SenseEvaluator.cc
orangeinp/detail/TransformInserter.cc
orangeinp/detail/VolumeBuilder.cc
surf/ConeAligned.cc
Expand Down
18 changes: 18 additions & 0 deletions src/orange/OrangeTypes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,24 @@ char const* to_cstring(TransformType value)
return to_cstring_impl(value);
}

//---------------------------------------------------------------------------//
/*!
* Get a string corresponding to a signed sense.
*/
char const* to_cstring(SignedSense s)
{
switch (s)
{
case SignedSense::inside:
return "inside";
case SignedSense::on:
return "on";
case SignedSense::outside:
return "outside";
}
return "<invalid>";
}

//---------------------------------------------------------------------------//
/*!
* Get a string corresponding to a transform type.
Expand Down
13 changes: 13 additions & 0 deletions src/orange/OrangeTypes.hh
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,16 @@ CELER_CONSTEXPR_FUNCTION Sense to_sense(bool s)
return static_cast<Sense>(!static_cast<bool>(orig));
}

//---------------------------------------------------------------------------//
/*!
* Change the sense across a surface.
*/
[[nodiscard]] CELER_CONSTEXPR_FUNCTION SignedSense flip_sense(SignedSense orig)
{
using IntT = std::underlying_type_t<SignedSense>;
return static_cast<SignedSense>(-static_cast<IntT>(orig));
}

//---------------------------------------------------------------------------//
/*!
* Change whether a boundary crossing is reentrant or exiting.
Expand Down Expand Up @@ -447,6 +457,9 @@ char const* to_cstring(SurfaceType);
// Get a string corresponding to a transform type
char const* to_cstring(TransformType);

// Get a string corresponding to a signed sense
char const* to_cstring(SignedSense);

// Get a string corresponding to a surface state
inline char const* to_cstring(SurfaceState s)
{
Expand Down
2 changes: 1 addition & 1 deletion src/orange/orangeinp/detail/InfixStringBuilder.hh
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class InfixStringBuilder
{
public:
// Construct with tree and a stream to write to
explicit inline InfixStringBuilder(CsgTree const& tree, std::ostream* os);
inline InfixStringBuilder(CsgTree const& tree, std::ostream* os);

//! Build from a node ID
inline void operator()(NodeId const& n);
Expand Down
1 change: 0 additions & 1 deletion src/orange/orangeinp/detail/InternalSurfaceFlagger.hh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <vector>

#include "corecel/cont/VariantUtils.hh"
#include "orange/surf/VariantSurface.hh"

#include "../CsgTree.hh"
#include "../CsgTypes.hh"
Expand Down
92 changes: 92 additions & 0 deletions src/orange/orangeinp/detail/SenseEvaluator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file orange/orangeinp/detail/SenseEvaluator.cc
//---------------------------------------------------------------------------//
#include "SenseEvaluator.hh"

namespace celeritas
{
namespace orangeinp
{
namespace detail
{
//---------------------------------------------------------------------------//
/*!
* Evaluate from a node ID.
*/
SignedSense SenseEvaluator::operator()(NodeId const& n) const
{
return visit_node_(*this, n);
}

//---------------------------------------------------------------------------//
/*!
* Evaluate a surface.
*/
SignedSense SenseEvaluator::operator()(Surface const& s) const
{
CELER_EXPECT(s.id < surfaces_.size());

auto result = std::visit(
[&pos = this->pos_](auto const& surf) { return surf.calc_sense(pos); },
surfaces_[s.id.get()]);

// TODO: "inside" wrt a surface (i.e. negative quadric) is "false", so we
// have to flip the result
static_assert(Sense::inside == to_sense(false));
return flip_sense(result);
}

//---------------------------------------------------------------------------//
/*!
* Redirect to an aliased node.
*/
SignedSense SenseEvaluator::operator()(Aliased const& n) const
{
return (*this)(n.node);
}

//---------------------------------------------------------------------------//
/*!
* Negate the result of a node.
*/
SignedSense SenseEvaluator::operator()(Negated const& n) const
{
return flip_sense((*this)(n.node));
}

//---------------------------------------------------------------------------//
/*!
* Visit daughter nodes to evaluate the combined sense.
*/
SignedSense SenseEvaluator::operator()(Joined const& j) const
{
CELER_ASSUME(j.op == op_and || j.op == op_or);

// Only keep testing if this sense results:
// short circuit for the other sense, short circuit for being *on* a
// surface too
auto const maybe
= (j.op == op_and ? SignedSense::inside : SignedSense::outside);

SignedSense result{};

for (NodeId const& d : j.nodes)
{
result = (*this)(d);
if (result != maybe)
{
break;
}
}

return result;
}

//---------------------------------------------------------------------------//
} // namespace detail
} // namespace orangeinp
} // namespace celeritas
85 changes: 85 additions & 0 deletions src/orange/orangeinp/detail/SenseEvaluator.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file orange/orangeinp/detail/SenseEvaluator.hh
//---------------------------------------------------------------------------//
#pragma once

#include "corecel/cont/VariantUtils.hh"
#include "orange/OrangeTypes.hh"
#include "orange/surf/VariantSurface.hh"

#include "../CsgTree.hh"

namespace celeritas
{
namespace orangeinp
{
namespace detail
{
//---------------------------------------------------------------------------//
/*!
* Evalate whether a point is inside a CSG tree node.
*
* This is a construction-time helper that combines \c SenseCalculator with \c
* LogicEvaluator. Its intended use is primarily for testing.
*/
class SenseEvaluator
{
public:
//!@{
//! \name Type aliases
using result_type = SignedSense;
using VecSurface = std::vector<VariantSurface>;
//!@}

public:
// Construct with a CSG tree, surfaces, and a point
inline SenseEvaluator(CsgTree const& tree,
VecSurface const& surfaces,
Real3 const& pos);

//! Visit from a node ID
result_type operator()(NodeId const& n) const;

//!@{
//! \name Visit a node directly
//! Point is always inside
result_type operator()(True const&) const { return SignedSense::inside; }
//! Point is always outside
result_type operator()(False const&) const { return SignedSense::outside; }
// Evaluate a surface
result_type operator()(Surface const&) const;
// Redirect an alias
result_type operator()(Aliased const&) const;
// Negate the daughter result
result_type operator()(Negated const&) const;
// Visit daughter nodes using short circuit logic
result_type operator()(Joined const&) const;
//!@}

private:
ContainerVisitor<CsgTree const&, NodeId> visit_node_;
VecSurface const& surfaces_;
Real3 pos_;
};

//---------------------------------------------------------------------------//
// INLINE DEFINITIONS
//---------------------------------------------------------------------------//
/*!
* Construct with a CSG tree and the position to test.
*/
SenseEvaluator::SenseEvaluator(CsgTree const& tree,
VecSurface const& surfaces,
Real3 const& pos)
: visit_node_{tree}, surfaces_{surfaces}, pos_{pos}
{
}

//---------------------------------------------------------------------------//
} // namespace detail
} // namespace orangeinp
} // namespace celeritas
25 changes: 25 additions & 0 deletions test/orange/orangeinp/ConvexRegion.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@
#include "orange/orangeinp/CsgTreeUtils.hh"
#include "orange/orangeinp/detail/ConvexSurfaceState.hh"
#include "orange/orangeinp/detail/CsgUnitBuilder.hh"
#include "orange/orangeinp/detail/SenseEvaluator.hh"

#include "CsgTestUtils.hh"
#include "celeritas_test.hh"

namespace celeritas
{
//---------------------------------------------------------------------------//
std::ostream& operator<<(std::ostream& os, SignedSense s)
{
return (os << to_cstring(s));
}

namespace orangeinp
{
namespace test
Expand All @@ -39,6 +46,7 @@ class ConvexRegionTest : public ::celeritas::test::Test
std::vector<std::string> surfaces;
BBox interior;
BBox exterior;
NodeId node_id;

void print_expected() const;
};
Expand All @@ -52,6 +60,13 @@ class ConvexRegionTest : public ::celeritas::test::Test
return this->test(r, NoTransformation{});
}

SignedSense calc_sense(NodeId n, Real3 const& pos)
{
CELER_EXPECT(n < unit_.tree.size());
detail::SenseEvaluator eval_sense(unit_.tree, unit_.surfaces, pos);
return eval_sense(n);
}

private:
Unit unit_;
UnitBuilder unit_builder_{&unit_, Tol::from_relative(1e-4)};
Expand All @@ -78,6 +93,7 @@ auto ConvexRegionTest::test(ConvexRegionInterface const& r,
TestResult result;
result.node = build_infix_string(unit_.tree, node_id);
result.surfaces = surface_strings(unit_);
result.node_id = node_id;

// Combine the bounding zones
auto merged_bzone = calc_merged_bzone(css);
Expand Down Expand Up @@ -139,6 +155,15 @@ TEST_F(BoxTest, standard)

EXPECT_EQ(expected_node, result.node);
EXPECT_VEC_EQ(expected_surfaces, result.surfaces);

EXPECT_EQ(SignedSense::inside,
this->calc_sense(result.node_id, Real3{0, 0, 0}));
EXPECT_EQ(SignedSense::on,
this->calc_sense(result.node_id, Real3{1, 0, 0}));
EXPECT_EQ(SignedSense::outside,
this->calc_sense(result.node_id, Real3{0, 3, 0}));
EXPECT_EQ(SignedSense::outside,
this->calc_sense(result.node_id, Real3{0, 0, -4}));
}

//---------------------------------------------------------------------------//
Expand Down

0 comments on commit 4dd382f

Please sign in to comment.