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) {
40 fields_map = std::make_shared<gFieldMap>();
41 fields_manager = std::make_shared<gFieldMgrMap>();
50 for (
auto& field_definition : field_definition_array) {
51 std::string name = field_definition.name;
55 if (!required_fields.empty() && required_fields.find(name) == required_fields.end()) {
56 log->
info(1,
"Field <", name,
"> is not used by any volume: skipping plugin and map load.");
63 if (fields_map->find(name) == fields_map->end()) {
66 field_definition.gfieldPluginName(), gopts));
69 fields_map->at(name)->load_field_definitions(field_definition);
72 fields_manager->emplace(name, fields_map->at(name)->create_FieldManager());
76 const double max_field_step = configured_max_field_step(gopts);
77 if (max_field_step > 0.0) {
78 G4TransportationManager::GetTransportationManager()
79 ->GetPropagatorInField()
80 ->SetLargestAcceptableStep(max_field_step);
81 log->
info(1,
"Maximum acceptable field step set to ", max_field_step / CLHEP::mm,
" mm.");
86 const std::shared_ptr<GOptions>& gopts,
double& field_polarity,
87 std::shared_ptr<GLogger> caller_log) {
88 if (gopts ==
nullptr) {
return nullptr; }
91 const std::string no_field_value = gopts->getScalarString(
NO_FIELD_OPTION);
93 if (caller_log !=
nullptr) {
95 ": direct field probes disabled.");
104 if (is_unset_field_name(field_name)) {
return nullptr; }
107 if (field_definition.name != field_name) {
continue; }
109 const auto torus_scale_it = field_definition.field_parameters.find(
"torus_scale");
110 if (torus_scale_it != field_definition.field_parameters.end()) {
112 field_polarity = std::stod(torus_scale_it->second) < 0.0 ? -1.0 : 1.0;
113 }
catch (
const std::exception&) {
114 if (caller_log !=
nullptr) {
115 caller_log->warning(
"Could not parse torus_scale <", torus_scale_it->second,
116 "> for field polarity; using +1.");
118 field_polarity = 1.0;
124 auto magneto = std::make_unique<GMagneto>(gopts, std::set<std::string>{field_name});
125 if (magneto->isField(field_name)) {
126 if (caller_log !=
nullptr) {
127 caller_log->info(1,
"Using magnetic field <", field_name,
128 "> for direct probes with torus polarity ", field_polarity);
130 return magneto->getField(field_name);
133 if (caller_log !=
nullptr) {
134 caller_log->warning(
"Global field <", field_name,
135 "> is configured but was not available for direct probes.");
141 const std::shared_ptr<GField>& magnetic_field,
const G4ThreeVector&
position) {
142 using namespace CLHEP;
144 if (magnetic_field ==
nullptr) {
return 0.0; }
147 double bfield[3] = {0.0, 0.0, 0.0};
148 magnetic_field->GetFieldValue(point, bfield);
150 return std::sqrt(bfield[0] * bfield[0] + bfield[1] * bfield[1] + bfield[2] * bfield[2]) / tesla;
154 std::vector<std::string> names;
155 names.reserve(fields_map->size());
156 for (
const auto& [name, field] : *fields_map) { names.push_back(name); }
157 std::sort(names.begin(), names.end());
std::shared_ptr< GLogger > log
Abstract base class representing a magnetic field.
void info(int level, Args &&... args) const
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
#define NO_FIELD_ALL
Special NO_FIELD_OPTION value that resets all fields, including GLOBAL_FIELD_OPTION.
#define NO_FIELD_OPTION
Command-line option name used to reset (remove) field associations.
#define GLOBAL_FIELD_OPTION
Command-line option name used to associate a field with the ROOT world volume.
#define MAX_FIELD_STEP_OPTION
Command-line option name used to set the global maximum acceptable field step.
#define UNINITIALIZEDSTRINGQUANTITY
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)