Skip to content

Commit

Permalink
Add find_solid with implicit downcast and validity check
Browse files Browse the repository at this point in the history
The `find_solid` that already exists, returns `G4VSolid*`. Sometimes you
want to access more specific methods which are only available in the
concrete subtypes, which requires a downcast and a pointer validity
check. This template absolves the user from writing lots of boilerplate.

Closes #151
  • Loading branch information
jacg committed Oct 31, 2023
2 parents 27b17ee + 23bafdb commit addeba9
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 2 deletions.
5 changes: 4 additions & 1 deletion doc/src/reference/headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ As your program grows and is split into multiple files, and you gain more experi

+ `<n4-main.hh>`

Groups together utilities that are required to write the `main` function of a `nain4` application. These are also available via the separate headers:
Groups together utilities that are required to write the `main` function of a `nain4` application. These are also available via the separate headers:
+ `<n4-run-manager.hh>`: `nain4` interface for configuring the Geant4 run manager
+ `<n4-mandatory.hh>`: `nain4` utilities for concise implementation of the user-defined classes that must be registered with the run manager

Expand Down Expand Up @@ -44,3 +44,6 @@ As your program grows and is split into multiple files, and you gain more experi
Utilities to help with writing automated tests for `nain4` applications. These are also available via the separate headers:
+ `<n4-defaults.hh>`: ready-made dummy application components
+ `<n4-geometry-iterators.hh>`: iterating over all sub-elements of a geometry

+ Other headers
+ `<n4-exceptions.hh>`: exceptions relating to situations arising in nain4 code
1 change: 1 addition & 0 deletions nain4/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ nain4_includes = [ 'n4-all.hh'
, 'n4-boolean-shape.hh'
, 'n4-constants.hh'
, 'n4-defaults.hh'
, 'n4-exceptions.hh'
, 'n4-geometry-iterators.hh'
, 'n4-geometry.hh'
, 'n4-inspect.hh'
Expand Down
1 change: 1 addition & 0 deletions nain4/src/n4-all.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <n4-main.hh>
#include <n4-exceptions.hh>
#include <n4-geometry.hh>
#include <n4-utils.hh>
#include <n4-testing.hh>
41 changes: 41 additions & 0 deletions nain4/src/n4-exceptions.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include <exception>
#include <string>

namespace nain4 {
namespace exceptions {

#define WRAP(NAME, FROM, MESSAGE) \
"\n\n" \
"########################################################\n" \
"[n4::exceptions::" + NAME + "]\n\n" \
"[raised by " + FROM + "]: " + MESSAGE + "\n" \
"########################################################\n" \
"\n\n"

struct exception : std::exception {
exception(const std::string& name, const std::string& from, const std::string& message)
: message(WRAP(name, from, message)) {}
const char* what() const noexcept { return message.c_str();}

private:
std::string message;
};

#define EXCEPTION(NAME) \
struct NAME : exception { \
NAME(const std::string& from, const std::string& message) \
: exception(#NAME, from, message) {} \
};

EXCEPTION(not_found)
EXCEPTION(bad_cast)

#undef N4_EXCEPTION
#undef WRAP

} // namespace exceptions
} // namespace nain4

namespace n4{ using namespace nain4; }
17 changes: 17 additions & 0 deletions nain4/src/n4-inspect.hh
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#pragma once

#include <n4-exceptions.hh>
#include <n4-run-manager.hh>

#include <G4LogicalVolumeStore.hh>
#include <G4PhysicalVolumeStore.hh>
#include <G4SolidStore.hh>
#include <G4ParticleTable.hh>
#include <stdexcept>
#include <typeinfo>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
Expand All @@ -26,6 +29,20 @@ IA event_number () { return n4::run_manager::get().here_be_dragons() -> G
#undef NAME
#undef NAME_VRB

template<class DOWN>
const DOWN* find_solid(const G4String& name) {

auto found = find_solid(name);
if (!found) {
throw n4::exceptions::not_found("find_solid", "solid " + name + " not found");
}
auto down = dynamic_cast<const DOWN*>(find_solid(name));
if (!down) {
throw n4::exceptions::bad_cast("find_solid", "solid " + name + " cannot be downcast to " + typeid(DOWN).name());
}
return down;
}

// Remove all, logical/physical volumes, solids and assemblies.
inline void clear_geometry() { G4RunManager::GetRunManager() -> ReinitializeGeometry(true); }

Expand Down
24 changes: 23 additions & 1 deletion nain4/test/test-nain4.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <n4-defaults.hh>
#include <n4-exceptions.hh>
#include <n4-shape.hh>
#include <n4-boolean-shape.hh>
#include <n4-utils.hh>
Expand Down Expand Up @@ -37,6 +38,7 @@

#include <cmath>
#include <numeric>
#include <stdexcept>
#include <type_traits>

#pragma GCC diagnostic push
Expand Down Expand Up @@ -1154,9 +1156,29 @@ TEST_CASE("nain find particle", "[nain][find][particle]") {
auto convenient = nain4::find_particle(name);
CHECK(convenient == pita);
CHECK(convenient == solid);
}
}

TEST_CASE("nain find solid downcast", "[nain][find][solid]") {
auto box = n4::box ("box" ).cube(1) .solid();
auto tubs = n4::tubs("tubs").r(1).z(2).solid();

auto found_box = n4::find_solid<G4Box >("box" );
auto found_tubs = n4::find_solid<G4Tubs>("tubs");

CHECK(found_box == box );
CHECK(found_tubs == tubs);
}


TEST_CASE("nain find solid downcast not found", "[nain][find][solid]") {
REQUIRE_THROWS_AS(n4::find_solid<G4Box>("does_not_exist"), n4::exceptions::not_found);
}

TEST_CASE("nain find solid downcast bad cast", "[nain][find][solid]") {
n4::box("box").cube(1).solid();
REQUIRE_THROWS_AS(n4::find_solid<G4Tubs>("box"), n4::exceptions::bad_cast);
}

TEST_CASE("nain clear_geometry", "[nain][clear_geometry]") {
default_run_manager().run();

Expand Down

0 comments on commit addeba9

Please sign in to comment.