9#include <gemc/guts/gutsConventions.h>
10#include <gemc/guts/gutilities.h>
13#include <CLHEP/Units/SystemOfUnits.h>
20#include "G4TransportationManager.hh"
21#include "G4PropagatorInField.hh"
25bool is_unset_field_name(
const std::string& name) {
29double configured_max_field_step(
const std::shared_ptr<GOptions>& gopts) {
41 fields_map = std::make_shared<gFieldMap>();
42 fields_manager = std::make_shared<gFieldMgrMap>();
51 for (
auto& field_definition : field_definition_array) {
52 std::string name = field_definition.name;
56 if (!required_fields.empty() && required_fields.find(name) == required_fields.end()) {
57 log->info(1,
"Field <", name,
"> is not used by any volume: skipping plugin and map load.");
61 log->info(1, field_definition);
64 if (fields_map->find(name) == fields_map->end()) {
67 field_definition.gfieldPluginName(), gopts));
70 fields_map->at(name)->load_field_definitions(field_definition);
73 fields_manager->emplace(name, fields_map->at(name)->create_FieldManager());
77 const double max_field_step = configured_max_field_step(gopts);
78 if (max_field_step > 0.0) {
79 G4TransportationManager::GetTransportationManager()
80 ->GetPropagatorInField()
81 ->SetLargestAcceptableStep(max_field_step);
82 log->info(1,
"Maximum acceptable field step set to ", max_field_step / CLHEP::mm,
" mm.");
87 const std::shared_ptr<GOptions>& gopts,
double& field_polarity,
88 std::shared_ptr<GLogger> caller_log) {
89 if (gopts ==
nullptr) {
return nullptr; }
94 if (caller_log !=
nullptr) {
96 ": direct field probes disabled.");
105 if (!field_name || is_unset_field_name(*field_name)) {
return nullptr; }
108 if (field_definition.name != *field_name) {
continue; }
110 const auto torus_scale_it = field_definition.field_parameters.find(
"torus_scale");
111 if (torus_scale_it != field_definition.field_parameters.end()) {
113 field_polarity = std::stod(torus_scale_it->second) < 0.0 ? -1.0 : 1.0;
114 }
catch (
const std::exception&) {
115 if (caller_log !=
nullptr) {
116 caller_log->warning(
"Could not parse torus_scale <", torus_scale_it->second,
117 "> for field polarity; using +1.");
119 field_polarity = 1.0;
125 auto magneto = std::make_unique<GMagneto>(gopts, std::set<std::string>{*field_name});
126 if (magneto->isField(*field_name)) {
127 if (caller_log !=
nullptr) {
128 caller_log->info(1,
"Using magnetic field <", *field_name,
129 "> for direct probes with torus polarity ", field_polarity);
131 return magneto->getField(*field_name);
134 if (caller_log !=
nullptr) {
135 caller_log->warning(
"Global field <", *field_name,
136 "> is configured but was not available for direct probes.");
142 const std::shared_ptr<GField>& magnetic_field,
const G4ThreeVector& position) {
143 using namespace CLHEP;
145 if (magnetic_field ==
nullptr) {
return 0.0; }
147 const double point[3] = {position.x(), position.y(), position.z()};
148 double bfield[3] = {0.0, 0.0, 0.0};
149 magnetic_field->GetFieldValue(point, bfield);
151 return std::sqrt(bfield[0] * bfield[0] + bfield[1] * bfield[1] + bfield[2] * bfield[2]) / tesla;
155 std::vector<std::string> names;
156 names.reserve(fields_map->size());
157 for (
const auto& [name, field] : *fields_map) { names.push_back(name); }
158 std::sort(names.begin(), names.end());
GBase(const std::shared_ptr< GOptions > &gopt, std::string logger_name="")
std::shared_ptr< GLogger > log
Abstract base class representing a magnetic field.
GMagneto(const std::shared_ptr< GOptions > &gopts, const std::set< std::string > &required_fields={})
Construct and initialize the magnetic field registry.
static double magnetic_field_magnitude_tesla(const std::shared_ptr< GField > &magnetic_field, const G4ThreeVector &position)
Return the magnetic-field magnitude at a position in Tesla.
std::vector< std::string > getFieldNames() const
Return the configured field names.
static std::shared_ptr< GField > initialize_magnetic_field(const std::shared_ptr< GOptions > &gopts, double &field_polarity, std::shared_ptr< GLogger > caller_log=nullptr)
Load the configured global magnetic field for code that needs direct field probes.
std::shared_ptr< T > LoadAndRegisterObjectFromLibrary(std::string_view name, const std::shared_ptr< GOptions > &gopts)
constexpr const char * GMAGNETO_LOGGER
constexpr char NO_FIELD_ALL[]
Special gfields::NO_FIELD_OPTION value that resets all fields, including gfields::GLOBAL_FIELD_OPTION...
constexpr char NO_FIELD_OPTION[]
Command-line option name used to reset (remove) field associations.
constexpr char MAX_FIELD_STEP_OPTION[]
Command-line option name used to set the global maximum acceptable field step.
constexpr char GLOBAL_FIELD_OPTION[]
Command-line option name used to associate a field with the ROOT world volume.
std::vector< GFieldDefinition > get_GFieldDefinition(const std::shared_ptr< GOptions > &gopts)
Build the list of field definitions from the provided options.
double getG4Number(const string &v, bool warnIfNotUnit=false)
constexpr char SERIALIZED_NULL_TOKEN[]