-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ORANGE surface construction components #1001
Changes from 12 commits
ccc5260
4a969d0
09663d4
569dff8
3e35e08
cf0867f
b8b1540
7cf24ad
5fb9a8d
974d1e4
e75f7d4
0a74894
4ae231c
630f1c4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
//----------------------------------*-C++-*----------------------------------// | ||
// Copyright 2023 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/construct/detail/LocalSurfaceInserter.cc | ||
//---------------------------------------------------------------------------// | ||
#include "LocalSurfaceInserter.hh" | ||
|
||
namespace celeritas | ||
{ | ||
namespace detail | ||
{ | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct with defaults. | ||
*/ | ||
LocalSurfaceInserter::LocalSurfaceInserter(VecSurface* v, | ||
Tolerance<> const& tol) | ||
: surfaces_{v}, soft_surface_equal_{tol} | ||
{ | ||
CELER_EXPECT(surfaces_); | ||
CELER_EXPECT(surfaces_->empty()); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Look for duplicate surfaces and store equivalency relationship. | ||
*/ | ||
LocalSurfaceId | ||
LocalSurfaceInserter::merge_impl(LocalSurfaceId source, LocalSurfaceId target) | ||
{ | ||
CELER_EXPECT(source < surfaces_->size()); | ||
CELER_EXPECT(target < source); | ||
|
||
if (auto iter = merged_.find(target); iter != merged_.end()) | ||
{ | ||
// Surface was already merged with another: chain them | ||
target = iter->second; | ||
CELER_ENSURE(target < source); | ||
} | ||
|
||
merged_.emplace(source, target); | ||
return target; | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
} // namespace detail | ||
} // namespace celeritas |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
//----------------------------------*-C++-*----------------------------------// | ||
// Copyright 2023 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/construct/detail/LocalSurfaceInserter.hh | ||
//---------------------------------------------------------------------------// | ||
#pragma once | ||
|
||
#include <algorithm> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
#include "orange/OrangeTypes.hh" | ||
#include "orange/surf/SoftSurfaceEqual.hh" | ||
#include "orange/surf/VariantSurface.hh" | ||
|
||
namespace celeritas | ||
{ | ||
namespace detail | ||
{ | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Merge local surfaces as they're being built. | ||
* | ||
* This will \em sometimes will return the ID of a previously inserted surface, | ||
* and \em sometimes will push the surface onto the vector of existing ones. | ||
* | ||
* There are three cases to consider: | ||
* - The new surface is entirely unique: we insert and return the new ID. | ||
* - The surface is soft equivalent but not exactly like an existing surface: | ||
* we insert but return an existing ID. | ||
* - The surface is exactly the same: we do \em not insert, and return existing | ||
* id. | ||
* | ||
* The second case adds the surface so that multiple nearby surfaces can be | ||
* \em chained together, even if the tolerance between the furthest apart is | ||
* greater than the soft equivalence tolerance. | ||
*/ | ||
class LocalSurfaceInserter | ||
{ | ||
public: | ||
//!@{ | ||
//! \name Type aliases | ||
using VecSurface = std::vector<VariantSurface>; | ||
//!@} | ||
|
||
public: | ||
// Construct with tolerance and a pointer to the surfaces vector | ||
LocalSurfaceInserter(VecSurface* v, Tolerance<> const& tol); | ||
|
||
// Construct a surface with deduplication | ||
template<class S> | ||
inline LocalSurfaceId operator()(S const& surface); | ||
|
||
private: | ||
using MapSurfId = std::unordered_map<LocalSurfaceId, LocalSurfaceId>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
VecSurface* surfaces_; | ||
SoftSurfaceEqual soft_surface_equal_; | ||
ExactSurfaceEqual exact_surface_equal_; | ||
MapSurfId merged_; | ||
|
||
LocalSurfaceId merge_impl(LocalSurfaceId source, LocalSurfaceId target); | ||
}; | ||
|
||
//---------------------------------------------------------------------------// | ||
// INLINE DEFINITIONS | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a surface with deduplication. | ||
*/ | ||
template<class S> | ||
LocalSurfaceId LocalSurfaceInserter::operator()(S const& source) | ||
{ | ||
VecSurface& all_surf = *surfaces_; | ||
|
||
// Test for soft equality against all existing surfaces | ||
auto is_soft_equal = [this, &source](VariantSurface const& vtarget) { | ||
if (S const* target = std::get_if<S>(&vtarget)) | ||
{ | ||
return soft_surface_equal_(source, *target); | ||
} | ||
return false; | ||
}; | ||
|
||
// TODO: instead of linear search (making overall unit insertion | ||
// quadratic!) accelerate by mapping surfaces into a hash and comparing all | ||
// neighboring hash cells | ||
auto iter = std::find_if(all_surf.begin(), all_surf.end(), is_soft_equal); | ||
if (iter == all_surf.end()) | ||
{ | ||
// Surface is completely unique | ||
LocalSurfaceId result(all_surf.size()); | ||
all_surf.emplace_back(std::in_place_type<S>, source); | ||
return result; | ||
} | ||
|
||
// Surface is soft equivalent to an existing surface at this index | ||
LocalSurfaceId target_id{static_cast<size_type>(iter - all_surf.begin())}; | ||
|
||
CELER_ASSUME(std::holds_alternative<S>(*iter)); | ||
if (exact_surface_equal_(source, std::get<S>(*iter))) | ||
{ | ||
// Surfaces are *exactly* equal: don't insert | ||
CELER_ENSURE(target_id < all_surf.size()); | ||
return target_id; | ||
} | ||
|
||
// Surface is a little bit different, so we still need to insert it | ||
// to chain duplicates | ||
LocalSurfaceId source_id(all_surf.size()); | ||
all_surf.emplace_back(std::in_place_type<S>, source); | ||
|
||
// Store the equivalency relationship and potentially chain equivalent | ||
// surfaces | ||
return this->merge_impl(source_id, target_id); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
} // namespace detail | ||
} // namespace celeritas |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
//----------------------------------*-C++-*----------------------------------// | ||
// Copyright 2023 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/surf/FaceNamer.cc | ||
//---------------------------------------------------------------------------// | ||
#include "corecel/Assert.hh" | ||
|
||
#include "FaceNamer.hh" | ||
#include "VariantSurface.hh" | ||
|
||
namespace celeritas | ||
{ | ||
namespace | ||
{ | ||
//---------------------------------------------------------------------------// | ||
constexpr char to_pm(Sense s) | ||
{ | ||
return s == Sense::inside ? 'p' : 'm'; | ||
} | ||
|
||
#define ORANGE_INSTANTIATE_OP(IN) \ | ||
template std::string FaceNamer::Impl::operator()(IN<Axis::x> const&) \ | ||
const; \ | ||
template std::string FaceNamer::Impl::operator()(IN<Axis::y> const&) \ | ||
const; \ | ||
template std::string FaceNamer::Impl::operator()(IN<Axis::z> const&) const | ||
|
||
//---------------------------------------------------------------------------// | ||
} // namespace | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Apply to a surface with unknown type. | ||
*/ | ||
std::string FaceNamer::operator()(Sense s, VariantSurface const& surf) | ||
{ | ||
CELER_ASSUME(!surf.valueless_by_exception()); | ||
return std::visit(Impl{&state_, s}, surf); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
// IMPL DEFINITIONS | ||
//---------------------------------------------------------------------------// | ||
template<Axis T> | ||
std::string FaceNamer::Impl::operator()(PlaneAligned<T> const&) const | ||
{ | ||
return {to_pm(sense_), to_char(T)}; | ||
} | ||
|
||
//! \cond | ||
ORANGE_INSTANTIATE_OP(PlaneAligned); | ||
//! \endcond | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a name for a axis-aligned cylinder. | ||
*/ | ||
template<Axis T> | ||
std::string FaceNamer::Impl::operator()(CylCentered<T> const&) const | ||
{ | ||
return {'c', to_char(T)}; | ||
} | ||
|
||
//! \cond | ||
ORANGE_INSTANTIATE_OP(CylCentered); | ||
//! \endcond | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a name for a sphere. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. centered sphere |
||
*/ | ||
std::string FaceNamer::Impl::operator()(SphereCentered const&) const | ||
{ | ||
return "s"; | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a name for a axis-aligned cylinder. | ||
*/ | ||
template<Axis T> | ||
std::string FaceNamer::Impl::operator()(CylAligned<T> const&) const | ||
{ | ||
return {'c', to_char(T)}; | ||
} | ||
|
||
//! \cond | ||
ORANGE_INSTANTIATE_OP(CylAligned); | ||
//! \endcond | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a name for a general plane. | ||
*/ | ||
std::string FaceNamer::Impl::operator()(Plane const&) const | ||
{ | ||
return "p" + std::to_string(state_->num_planes_++); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a name for a sphere. | ||
*/ | ||
std::string FaceNamer::Impl::operator()(Sphere const&) const | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are sphere and centered sphere supposed to have the same name? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's how it is in the current SCALE builder. I can't think of any shape that has anything but a single sphere... |
||
{ | ||
return "s"; | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a name for a cone. | ||
*/ | ||
template<Axis T> | ||
std::string FaceNamer::Impl::operator()(ConeAligned<T> const&) const | ||
{ | ||
return {'k', to_char(T)}; | ||
} | ||
|
||
//! \cond | ||
ORANGE_INSTANTIATE_OP(ConeAligned); | ||
//! \endcond | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a name for a simple quadric. | ||
*/ | ||
std::string FaceNamer::Impl::operator()(SimpleQuadric const&) const | ||
{ | ||
return "sq"; | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a name for a quadric. | ||
*/ | ||
std::string FaceNamer::Impl::operator()(GeneralQuadric const&) const | ||
{ | ||
return "gq"; | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
} // namespace celeritas |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the purpose of the em-dashes above, but not in this paragraph.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
em
is the<em>
html tag aka "emphasis" (i.e., italicized).