Skip to content
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 a hack to override ORANGE max intersections/faces #1430

Merged
merged 10 commits into from
Oct 1, 2024
27 changes: 25 additions & 2 deletions app/celer-g4/GlobalSetup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "corecel/io/Logger.hh"
#include "corecel/io/StringUtils.hh"
#include "corecel/sys/Device.hh"
#include "corecel/sys/Environment.hh"
#include "celeritas/ext/RootFileManager.hh"
#include "celeritas/field/RZMapFieldInput.hh"
#include "accel/ExceptionConverter.hh"
Expand Down Expand Up @@ -132,6 +133,30 @@ void GlobalSetup::ReadInput(std::string const& filename)
CELER_ASSERT(instream);
nlohmann::json::parse(*instream).get_to(input_);

if (input_.cuda_stack_size != RunInput::unspecified)
{
options_->cuda_stack_size = input_.cuda_stack_size;
}
if (input_.cuda_heap_size != RunInput::unspecified)
{
options_->cuda_heap_size = input_.cuda_heap_size;
}
celeritas::environment().merge(input_.environ);

if constexpr (CELERITAS_CORE_GEO == CELERITAS_CORE_GEO_ORANGE)
{
static char const fi_hack_envname[] = "ORANGE_FORCE_INPUT";
auto const& filename = celeritas::getenv(fi_hack_envname);
if (!filename.empty())
{
CELER_LOG(warning)
<< "Using a temporary, unsupported, and dangerous hack to "
"override the ORANGE geometry file: "
<< fi_hack_envname << "='" << filename << "'";
options_->geometry_file = filename;
}
}

// Output options
options_->output_file = input_.output_file;
options_->physics_output_file = input_.physics_output_file;
Expand Down Expand Up @@ -164,8 +189,6 @@ void GlobalSetup::ReadInput(std::string const& filename)
options_->sd.enabled = input_.sd_type != SensitiveDetectorType::none;
options_->slot_diagnostic_prefix = input_.slot_diagnostic_prefix;

options_->cuda_stack_size = input_.cuda_stack_size;
options_->cuda_heap_size = input_.cuda_heap_size;
options_->action_times = input_.action_times;
options_->default_stream = input_.default_stream;
options_->track_order = input_.track_order;
Expand Down
13 changes: 11 additions & 2 deletions app/celer-g4/RunInput.hh
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,18 @@
#include "corecel/Types.hh"
#include "corecel/cont/Array.hh"
#include "corecel/sys/Device.hh"
#include "corecel/sys/Environment.hh"
#include "celeritas/ext/GeantPhysicsOptions.hh"
#include "celeritas/field/FieldDriverOptions.hh"
#include "celeritas/phys/PrimaryGeneratorOptions.hh"

#ifdef _WIN32
# include <cstdlib>
# ifdef environ
# undef environ
# endif
#endif

namespace celeritas
{
namespace app
Expand Down Expand Up @@ -54,8 +62,9 @@ struct RunInput
static constexpr size_type unspecified{static_cast<size_type>(-1)};

// Global environment
size_type cuda_stack_size{};
size_type cuda_heap_size{};
size_type cuda_stack_size{unspecified};
size_type cuda_heap_size{unspecified};
Environment environ; //!< Supplement existing env variables

// Problem definition
std::string geometry_file; //!< Path to GDML file
Expand Down
11 changes: 9 additions & 2 deletions app/celer-g4/RunInputIO.json.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "corecel/io/Logger.hh"
#include "corecel/io/StringEnumMapper.hh"
#include "corecel/sys/Environment.hh"
#include "corecel/sys/EnvironmentIO.json.hh"
#include "celeritas/TypesIO.json.hh"
#include "celeritas/ext/GeantPhysicsOptionsIO.json.hh"
#include "celeritas/field/FieldDriverOptionsIO.json.hh"
Expand Down Expand Up @@ -72,6 +73,10 @@ void from_json(nlohmann::json const& j, RunInput& v)
// Check version (if available)
check_format(j, "celer-g4");

RI_LOAD_OPTION(cuda_heap_size);
RI_LOAD_OPTION(cuda_stack_size);
RI_LOAD_OPTION(environ);

RI_LOAD_REQUIRED(geometry_file);
RI_LOAD_OPTION(event_file);

Expand Down Expand Up @@ -171,6 +176,10 @@ void to_json(nlohmann::json& j, RunInput const& v)
// Save version and format type
save_format(j, "celer-g4");

RI_SAVE_OPTION(cuda_stack_size);
RI_SAVE_OPTION(cuda_heap_size);
RI_SAVE(environ);

RI_SAVE(geometry_file);
RI_SAVE_OPTION(event_file);

Expand All @@ -183,8 +192,6 @@ void to_json(nlohmann::json& j, RunInput const& v)
RI_SAVE_OPTION(max_steps);
RI_SAVE(initializer_capacity);
RI_SAVE(secondary_stack_factor);
RI_SAVE_OPTION(cuda_stack_size);
RI_SAVE_OPTION(cuda_heap_size);
RI_SAVE(action_times);
RI_SAVE(default_stream);
RI_SAVE(auto_flush);
Expand Down
22 changes: 20 additions & 2 deletions app/celer-sim/Runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,26 @@ void Runner::build_core_params(RunnerInput const& inp,
params.output_reg = std::move(outreg);

// Load geometry: use existing world volume or reload from geometry file
params.geometry = g4world ? std::make_shared<GeoParams>(g4world)
: std::make_shared<GeoParams>(inp.geometry_file);
params.geometry = [&geo_file = inp.geometry_file, g4world] {
if constexpr (CELERITAS_CORE_GEO == CELERITAS_CORE_GEO_ORANGE)
{
static char const fi_hack_envname[] = "ORANGE_FORCE_INPUT";
auto const& filename = celeritas::getenv(fi_hack_envname);
if (!filename.empty())
{
CELER_LOG(warning)
<< "Using a temporary, unsupported, and dangerous hack to "
"override the ORANGE geometry file: "
<< fi_hack_envname << "='" << filename << "'";
return std::make_shared<GeoParams>(filename);
}
}
if (g4world)
{
return std::make_shared<GeoParams>(g4world);
}
return std::make_shared<GeoParams>(geo_file);
}();

if (!params.geometry->supports_safety())
{
Expand Down
6 changes: 5 additions & 1 deletion src/orange/OrangeInputIO.json.cc
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,11 @@ void from_json(nlohmann::json const& j, UnitInput& value)
*/
void to_json(nlohmann::json& j, UnitInput const& value)
{
CELER_EXPECT(value);
if (!value)
{
CELER_LOG(warning) << "Unit '" << value.label
<< "' is not in a valid state";
}

j["_type"] = "unit";
j["md"]["name"] = value.label;
Expand Down
88 changes: 81 additions & 7 deletions src/orange/detail/UnitInserter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <algorithm>
#include <iostream>
#include <regex>
#include <set>
#include <vector>

Expand All @@ -19,7 +20,9 @@
#include "corecel/cont/Span.hh"
#include "corecel/data/Collection.hh"
#include "corecel/data/Ref.hh"
#include "corecel/io/Logger.hh"
#include "corecel/math/Algorithms.hh"
#include "corecel/sys/Environment.hh"

#include "UniverseInserter.hh"
#include "../OrangeInput.hh"
Expand Down Expand Up @@ -159,12 +162,14 @@ std::vector<Label> make_volume_labels(UnitInput& inp)
}

//---------------------------------------------------------------------------//
//! Create a bounding box bumper for a given tolerance.
//
// This bumper will convert *to* fast real type *from* regular
// real type. It conservatively expand to twice the potential bump distance
// from a boundary so that the bbox will enclose the point even after a
// potential bump.
/*!
* Create a bounding box bumper for a given tolerance.
*
* This bumper will convert *to* fast real type *from* regular
* real type. It conservatively expand to twice the potential bump distance
* from a boundary so that the bbox will enclose the point even after a
* potential bump.
*/
BoundingBoxBumper<fast_real_type, real_type> make_bumper(Tolerance<> const& tol)
{
Tolerance<real_type> bbox_tol;
Expand All @@ -174,6 +179,57 @@ BoundingBoxBumper<fast_real_type, real_type> make_bumper(Tolerance<> const& tol)
return BoundingBoxBumper<fast_real_type, real_type>(std::move(bbox_tol));
}

struct ForceMax
{
size_type faces = std::numeric_limits<size_type>::max();
size_type intersections = std::numeric_limits<size_type>::max();
};

static char const mfi_hack_envname[] = "ORANGE_MAX_FACE_INTERSECT";

//---------------------------------------------------------------------------//
/*!
* Force maximum faces/intersections.
*
* This is if we know the "automatic" value is wrong, specifically if all
* complicated/background cells are unreachable.
*
* See https://github.com/celeritas-project/celeritas/issues/1334 .
*/
ForceMax const& forced_scalar_max()
{
static ForceMax const result = [] {
std::string mfi = celeritas::getenv(mfi_hack_envname);
if (mfi.empty())
{
return ForceMax{};
}
CELER_LOG(warning)
<< "Using a temporary, unsupported, and dangerous hack to "
"override maximum faces and intersections in ORANGE: "
<< mfi_hack_envname << "='" << mfi << "'";

ForceMax result;
static std::regex const mfi_regex{R"re(^(\d+),(\d+)$)re"};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the context of this being a presumably temporary hack I don't know if this matters, but it the regex validation is complex enough to get its own function in anonymous namespace.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this option shouldn't live long (the "cheat" itself isn't tested anywhere except by me manually for our regression problems). The regex ^(\d+),(\d+)$ isn't that complicated (whole text, capture two nonnegative integers separated by a comma) but perhaps it's harder to read because of the literal R"re()re" string.

std::smatch mfi_match;
CELER_VALIDATE(std::regex_match(mfi, mfi_match, mfi_regex),
<< "invalid pattern for " << mfi_hack_envname);
auto get = [](char const* type, auto const& submatch) {
auto&& s = submatch.str();
auto updated = std::stoi(s);
CELER_VALIDATE(updated > 0,
<< "invalid maximum " << type << ": " << updated);
CELER_LOG(warning)
<< "Forcing maximum " << type << " to " << updated;
return static_cast<size_type>(updated);
};
result.faces = get("faces", mfi_match[0]);
result.intersections = get("intersections", mfi_match[1]);
return result;
}();
return result;
}

//---------------------------------------------------------------------------//
} // namespace

Expand Down Expand Up @@ -340,12 +396,13 @@ VolumeRecord UnitInserter::insert_volume(SurfacesRecord const& surf_record,
max_intersections += visit_surface(NumIntersectionGetter{}, sid);
}

static logic_int const nowhere_logic[] = {logic::ltrue, logic::lnot};

auto input_logic = make_span(v.logic);
if (v.zorder == ZOrder::background)
{
// "Background" volumes should not be explicitly reachable by logic or
// BIH
static logic_int const nowhere_logic[] = {logic::ltrue, logic::lnot};
CELER_EXPECT(std::equal(input_logic.begin(),
input_logic.end(),
std::begin(nowhere_logic),
Expand All @@ -369,6 +426,23 @@ VolumeRecord UnitInserter::insert_volume(SurfacesRecord const& surf_record,
output.flags |= VolumeRecord::Flags::simple_safety;
}

if (output.max_intersections > forced_scalar_max().intersections
|| output.faces.size() > forced_scalar_max().faces)
{
CELER_LOG(warning) << "Max intersections (" << output.max_intersections
<< ") and/or faces (" << output.faces.size()
<< ") exceed limits of '" << mfi_hack_envname
<< " in volume '" << v.label
<< "': replacing with unreachable volume";

output.faces = {};
output.logic = logic_ints_.insert_back(std::begin(nowhere_logic),
std::end(nowhere_logic));
output.max_intersections = 0;
output.flags = VolumeRecord::implicit_vol
| VolumeRecord::Flags::simple_safety;
}

// Calculate the maximum stack depth of the volume definition
int max_depth = calc_max_depth(input_logic);
CELER_VALIDATE(max_depth > 0,
Expand Down
2 changes: 1 addition & 1 deletion test/orange/OrangeGeoTestBase.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ void OrangeGeoTestBase::build_geometry(std::string const& filename)
= std::make_unique<Params>(this->test_data_path("orange", filename));

static std::string const expected_log_levels[] = {"info"};
EXPECT_VEC_EQ(expected_log_levels, scoped_log_.levels());
EXPECT_VEC_EQ(expected_log_levels, scoped_log_.levels()) << scoped_log_;
ASSERT_TRUE(this->geometry());
}

Expand Down
Loading