/* * Copyright (C) 2018 Université Clermont Auvergne, CNRS/IN2P3, LPC * Author: Valentin NIESS (niess@in2p3.fr) * * A Geant4 particle source of atmospheric muons using GOUPIL * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see */ #include #include #include "IGoupilSettings.hh" #include "G4ExceptionHandler.hh" #include "G4UIcmdWithABool.hh" #include "G4UIcmdWithADoubleAndUnit.hh" #include "G4UIcmdWithAnInteger.hh" #include "G4UIcmdWithAString.hh" #include "G4UIdirectory.hh" #include "G4PhysicalConstants.hh" #include "G4UnitsTable.hh" static std::list gDirectories; static std::list gCommands; /* Configuration settings */ static struct { struct { G4String file; G4int level; } verbose; G4bool chargeRandomisation; struct { G4double latitude; G4double longitude; G4double altitude; G4int flag; } earthLocation; struct { G4double alpha; G4double beta; G4double gamma; } worldOrientation; struct { G4String model; struct { G4int year; G4int month; G4int day; } date; } geomagnet; struct { G4double height; G4String model; } primary; struct { IGoupilTopography layers; std::map data; IGoupilTopographyData * dataLast; G4double bottom; G4String reference; } topography; } gSettings; /* Instanciate the single instance of the settings proxy */ static IGoupilSettings * gInstance = IGoupilSettings::GetInstance(); /* List of operations for processors */ namespace Operation { enum Value { Initialise, Get, Set }; } /* Generic processor interface for a parameter */ typedef void Processor( Operation::Value, G4UImessenger *, G4String *); /* Base class adding a generic processor */ struct ProcessorWrapper { Processor * Process; }; /* Extend a class with a generic processor */ template struct Wrap: public ProcessorWrapper, T { Wrap(const char * path, G4UImessenger * msg, Processor * process) : T(path, msg) { this->Process = process; } }; /* Helper function for adding a new command */ template static T * addCommand(G4UImessenger * messenger, const char * path, Processor * process) { Wrap * cmd = new Wrap(path, messenger, process); gCommands.push_back(cmd); return cmd; } /* Helper function for adding a new directory */ static void addDirectory(const char * path, const char * guidance) { G4UIdirectory * dir = new G4UIdirectory(path); dir->SetGuidance(guidance); gDirectories.push_back(dir); } /* Processor for the verbose level */ static void ProcessVerboseLevel( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAnInteger * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/verbose/level", &ProcessVerboseLevel); cmd->SetParameterName("verboseLevel", false); cmd->SetGuidance( "Control the verbose level of the GOUPIL sampling"); G4int defaultValue = 0; cmd->SetDefaultValue(defaultValue); gSettings.verbose.level = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString(gSettings.verbose.level); } else if (op == Operation::Set) { IGoupilSettings::SetVerboseLevel( cmd->GetNewIntValue(value->c_str())); } } G4int IGoupilSettings::GetVerboseLevel() { return gSettings.verbose.level; } void IGoupilSettings::SetVerboseLevel(G4int level) { gSettings.verbose.level = level; } /* Processor for the verbose output file */ static void ProcessVerboseFile( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAString * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/verbose/file", &ProcessVerboseFile); cmd->SetParameterName("verboseFile", false); cmd->SetGuidance( "Set the file where to verbose the GOUPIL sampling"); G4String defaultValue = ""; cmd->SetDefaultValue(defaultValue); gSettings.verbose.file = defaultValue; } else if (op == Operation::Get) { *value = gSettings.verbose.file; } else if (op == Operation::Set) { IGoupilSettings::SetVerboseFile(*value); } } const G4String& IGoupilSettings::GetVerboseFile() { return gSettings.verbose.file; } void IGoupilSettings::SetVerboseFile(G4String file) { gSettings.verbose.file = file; } /* Procesor for the charge randomisation parameter */ static void ProcessChargeRandomisation( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithABool * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/chargeRandomisation", &ProcessChargeRandomisation); cmd->SetParameterName("chargeRandomisation", false); G4bool defaultValue = true; cmd->SetDefaultValue(defaultValue); gSettings.chargeRandomisation = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString(gSettings.chargeRandomisation); } else if (op == Operation::Set) { IGoupilSettings::SetChargeRandomisation( cmd->ConvertToBool(value->c_str())); } } G4bool IGoupilSettings::GetChargeRandomisation() { return gSettings.chargeRandomisation; } void IGoupilSettings::SetChargeRandomisation(G4bool value) { gSettings.chargeRandomisation = value; } /* Manage the World latitude */ static void ProcessEarthLocationLatitude( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/earthLocation/latitude", &ProcessEarthLocationLatitude); cmd->SetParameterName("latitude", false); cmd->SetGuidance("Set the latitude of the World origin"); cmd->SetUnitCategory("Angle"); G4double defaultValue = 0.; cmd->SetDefaultValue(defaultValue * CLHEP::deg); gSettings.earthLocation.latitude = defaultValue; gSettings.earthLocation.flag = 0; } else if (op == Operation::Get) { *value = cmd->ConvertToString( gSettings.earthLocation.latitude, "deg"); } else if (op == Operation::Set) { gSettings.earthLocation.latitude = cmd->GetNewDoubleValue(value->c_str()) / CLHEP::deg; gSettings.earthLocation.flag |= 1; } } G4double IGoupilSettings::GetEarthLocationLatitude() { return gSettings.earthLocation.latitude * CLHEP::deg; } /* Manage the World longitude */ static void ProcessEarthLocationLongitude( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/earthLocation/longitude", &ProcessEarthLocationLongitude); cmd->SetParameterName("longitude", false); cmd->SetGuidance("Set the longitude of the World origin"); cmd->SetUnitCategory("Angle"); G4double defaultValue = 0.; cmd->SetDefaultValue(defaultValue * CLHEP::deg); gSettings.earthLocation.longitude = defaultValue; gSettings.earthLocation.flag = 0; } else if (op == Operation::Get) { *value = cmd->ConvertToString( gSettings.earthLocation.longitude, "deg"); } else if (op == Operation::Set) { gSettings.earthLocation.longitude = cmd->GetNewDoubleValue(value->c_str()) / CLHEP::deg; gSettings.earthLocation.flag |= 2; } } G4double IGoupilSettings::GetEarthLocationLongitude() { return gSettings.earthLocation.longitude * CLHEP::deg; } /* Manage the World altitude */ static void ProcessEarthLocationAltitude( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/earthLocation/altitude", &ProcessEarthLocationAltitude); cmd->SetParameterName("altitude", false); cmd->SetGuidance("Set the altitude of the World origin"); cmd->SetUnitCategory("Length"); G4double defaultValue = 0.; cmd->SetDefaultValue(defaultValue * CLHEP::m); gSettings.earthLocation.altitude = defaultValue; gSettings.earthLocation.flag = 0; } else if (op == Operation::Get) { *value = cmd->ConvertToString( gSettings.earthLocation.altitude, "m"); } else if (op == Operation::Set) { gSettings.earthLocation.altitude = cmd->GetNewDoubleValue(value->c_str()) / CLHEP::m; gSettings.earthLocation.flag |= 4; } } G4double IGoupilSettings::GetEarthLocationAltitude() { return gSettings.earthLocation.altitude * CLHEP::m; } void IGoupilSettings::SetEarthLocation(G4double latitude, G4double longitude, G4double altitude) { gSettings.earthLocation.latitude = latitude / CLHEP::deg; gSettings.earthLocation.longitude = longitude / CLHEP::deg; gSettings.earthLocation.altitude = altitude / CLHEP::m; gSettings.earthLocation.flag = (1 | 2 | 4); } G4bool IGoupilSettings::CheckEarthLocation() { return gSettings.earthLocation.flag == (1 | 2 | 4); } /* Manage the World orientation: alpha Euler angle */ static void ProcessWorldOrientationAlpha( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/worldOrientation/alpha", &ProcessWorldOrientationAlpha); cmd->SetParameterName("alpha", false); cmd->SetGuidance( "Set the alpha Euler angle of the World volume"); cmd->SetUnitCategory("Angle"); G4double defaultValue = 0.; cmd->SetDefaultValue(defaultValue * CLHEP::deg); gSettings.worldOrientation.alpha = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString( gSettings.worldOrientation.alpha, "deg"); } else if (op == Operation::Set) { gSettings.worldOrientation.alpha = cmd->GetNewDoubleValue(value->c_str()) / CLHEP::deg; } } G4double IGoupilSettings::GetWorldOrientationAlpha() { return gSettings.worldOrientation.alpha * CLHEP::deg; } /* Manage the World orientation: beta Euler angle */ static void ProcessWorldOrientationBeta( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/worldOrientation/beta", &ProcessWorldOrientationBeta); cmd->SetParameterName("beta", false); cmd->SetGuidance( "Set the beta Euler angle of the World volume"); cmd->SetUnitCategory("Angle"); G4double defaultValue = 0.; cmd->SetDefaultValue(defaultValue * CLHEP::deg); gSettings.worldOrientation.beta = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString( gSettings.worldOrientation.beta, "deg"); } else if (op == Operation::Set) { gSettings.worldOrientation.beta = cmd->GetNewDoubleValue(value->c_str()) / CLHEP::deg; } } G4double IGoupilSettings::GetWorldOrientationBeta() { return gSettings.worldOrientation.beta * CLHEP::deg; } /* Manage the World orientation: gamma Euler angle */ static void ProcessWorldOrientationGamma( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/worldOrientation/gamma", &ProcessWorldOrientationGamma); cmd->SetParameterName("gamma", false); cmd->SetGuidance( "Set the gamma Euler angle of the World volume"); cmd->SetUnitCategory("Angle"); G4double defaultValue = 0.; cmd->SetDefaultValue(defaultValue * CLHEP::deg); gSettings.worldOrientation.gamma = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString( gSettings.worldOrientation.gamma, "deg"); } else if (op == Operation::Set) { gSettings.worldOrientation.gamma = cmd->GetNewDoubleValue(value->c_str()) / CLHEP::deg; } } G4double IGoupilSettings::GetWorldOrientationGamma() { return gSettings.worldOrientation.gamma * CLHEP::deg; } void IGoupilSettings::SetWorldOrientation(G4double alpha, G4double beta, G4double gamma) { gSettings.worldOrientation.alpha = alpha / CLHEP::deg; gSettings.worldOrientation.beta = beta / CLHEP::deg; gSettings.worldOrientation.gamma = gamma / CLHEP::deg; } /* Manage the year of the geomagnet date */ static void ProcessGeomagnetDateYear( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAnInteger * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/geomagnet/date/year", &ProcessGeomagnetDateYear); cmd->SetParameterName("year", false); cmd->SetGuidance("Set the year for the geomagnet date"); G4int defaultValue = 2019; cmd->SetDefaultValue(defaultValue); gSettings.geomagnet.date.year = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString(gSettings.geomagnet.date.year); } else if (op == Operation::Set) { gSettings.geomagnet.date.year = cmd->GetNewIntValue(value->c_str()); } } G4int IGoupilSettings::GetGeomagnetDateYear() { return gSettings.geomagnet.date.year; } /* Manage the month of the geomagnet date */ static void ProcessGeomagnetDateMonth( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAnInteger * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/geomagnet/date/month", &ProcessGeomagnetDateMonth); cmd->SetParameterName("month", false); cmd->SetGuidance("Set the month for the geomagnet date"); G4int defaultValue = 1; cmd->SetDefaultValue(defaultValue); gSettings.geomagnet.date.month = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString(gSettings.geomagnet.date.year); } else if (op == Operation::Set) { gSettings.geomagnet.date.month = cmd->GetNewIntValue(value->c_str()); } } G4int IGoupilSettings::GetGeomagnetDateMonth() { return gSettings.geomagnet.date.month; } /* Manage the day of the geomagnet date */ static void ProcessGeomagnetDateDay( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAnInteger * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/geomagnet/date/day", &ProcessGeomagnetDateDay); cmd->SetParameterName("day", false); cmd->SetGuidance("Set the day for the geomagnet date"); G4int defaultValue = 1; cmd->SetDefaultValue(defaultValue); gSettings.geomagnet.date.day = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString(gSettings.geomagnet.date.year); } else if (op == Operation::Set) { gSettings.geomagnet.date.day = cmd->GetNewIntValue(value->c_str()); } } G4int IGoupilSettings::GetGeomagnetDateDay() { return gSettings.geomagnet.date.day; } void IGoupilSettings::SetGeomagnetDate(G4int year, G4int month, G4int day) { gSettings.geomagnet.date.year = year; gSettings.geomagnet.date.month = month; gSettings.geomagnet.date.day = day; } /* Manage the geomagnetic model */ static void ProcessGeomagnetModel( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAString * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/geomagnet/model", &ProcessGeomagnetModel); cmd->SetParameterName("model", false); cmd->SetGuidance("Set the model for the geomagnetic field"); G4String defaultValue = "IGRF12"; cmd->SetDefaultValue(defaultValue); gSettings.geomagnet.model = defaultValue; } else if (op == Operation::Get) { *value = gSettings.geomagnet.model; } else if (op == Operation::Set) { gSettings.geomagnet.model = *value; } } const G4String & IGoupilSettings::GetGeomagnetModel() { return gSettings.geomagnet.model; } void IGoupilSettings::SetGeomagnetModel(G4String model) { gSettings.geomagnet.model = model; } /* Manage the primary height */ static void ProcessPrimaryHeight( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/primary/height", &ProcessPrimaryHeight); cmd->SetParameterName("height", false); cmd->SetGuidance("Set the height of the primary flux, " "w.r.t. sea level"); cmd->SetUnitCategory("Length"); G4double defaultValue = 0.0; cmd->SetDefaultValue(defaultValue * CLHEP::m); gSettings.primary.height = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString( gSettings.primary.height, "m"); } else if (op == Operation::Set) { gSettings.primary.height = cmd->GetNewDoubleValue(value->c_str()) / CLHEP::m; } } G4double IGoupilSettings::GetPrimaryHeight() { return gSettings.primary.height * CLHEP::m; } void IGoupilSettings::SetPrimaryHeight(G4double height) { gSettings.primary.height = height / CLHEP::m; } /* Manage the primary flux model */ static void ProcessPrimaryModel( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAString * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/primary/model", &ProcessPrimaryModel); cmd->SetParameterName("model", false); cmd->SetGuidance("Set the model for the primary flux"); G4String defaultValue = "GCCLY"; cmd->SetDefaultValue(defaultValue); gSettings.primary.model = defaultValue; } else if (op == Operation::Get) { *value = gSettings.primary.model; } else if (op == Operation::Set) { gSettings.primary.model = *value; } } const G4String & IGoupilSettings::GetPrimaryModel() { return gSettings.primary.model; } void IGoupilSettings::SetPrimaryModel(G4String model) { gSettings.primary.model = model; } /* Manage the topography bottom */ static void ProcessTopographyBottom( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/topography/bottom", &ProcessTopographyBottom); cmd->SetParameterName("bottom", false); cmd->SetGuidance("Set the bottom height of the topography, " "w.r.t. sea level"); cmd->SetUnitCategory("Length"); G4double defaultValue = -11E+03; cmd->SetDefaultValue(defaultValue * CLHEP::m); gSettings.topography.bottom = defaultValue; } else if (op == Operation::Get) { *value = cmd->ConvertToString( gSettings.topography.bottom, "m"); } else if (op == Operation::Set) { gSettings.topography.bottom = cmd->GetNewDoubleValue(value->c_str()) / CLHEP::m; } } G4double IGoupilSettings::GetTopographyBottom() { return gSettings.topography.bottom * CLHEP::m; } void IGoupilSettings::SetTopographyBottom(G4double bottom) { gSettings.topography.bottom = bottom / CLHEP::m; } /* Manage the topography reference layer */ static void ProcessTopographyReference( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAString * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/topography/reference", &ProcessTopographyReference); cmd->SetParameterName("reference", false); cmd->SetGuidance("Set the reference layer of the topography"); G4String defaultValue = ""; cmd->SetDefaultValue(defaultValue); gSettings.topography.reference = defaultValue; } else if (op == Operation::Get) { *value = gSettings.topography.reference; } else if (op == Operation::Set) { gSettings.topography.reference = *value; } } const G4String & IGoupilSettings::GetTopographyReference() { return gSettings.topography.reference; } void IGoupilSettings::SetTopographyReference(G4String reference) { gSettings.topography.reference = reference; } /* Add a topography data set */ static void ProcessTopographyDataNew( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAString * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/topography/data/new", &ProcessTopographyDataNew); cmd->SetParameterName("dataName", false); cmd->SetGuidance("Create a new topography data set"); #define DEFAULT_DATA_NAME "default" gSettings.topography.data[DEFAULT_DATA_NAME] = IGoupilTopographyData(); gSettings.topography.dataLast = &gSettings.topography.data[DEFAULT_DATA_NAME]; gSettings.topography.dataLast->push_back( IGoupilTopographyDatum("", 0.0)); } else if (op == Operation::Get) { *value = "(invalid)"; } else if (op == Operation::Set) { gSettings.topography.data[*value] = IGoupilTopographyData(); gSettings.topography.dataLast = &gSettings.topography.data[*value]; } } /* Add a datum to a topography data set */ static void ProcessTopographyDataDatumNew( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAString * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/topography/data/datum/new", &ProcessTopographyDataDatumNew); cmd->SetParameterName("datumPath", true); cmd->SetGuidance( "Create a new datum for a topography data set"); cmd->SetDefaultValue(""); } else if (op == Operation::Get) { *value = "(invalid)"; } else if (op == Operation::Set) { gSettings.topography.dataLast->push_back( IGoupilTopographyDatum(*value, 0.0)); } } /* Set the offset of a topography datum*/ static void ProcessTopographyDataDatumOffset( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/topography/data/datum/offset", &ProcessTopographyDataDatumOffset); cmd->SetParameterName("datumOffset", false); cmd->SetGuidance( "Set the offset of a topography datum"); cmd->SetUnitCategory("Length"); } else if (op == Operation::Get) { *value = "(invalid)"; } else if (op == Operation::Set) { if (gSettings.topography.dataLast->size() == 0) { gSettings.topography.dataLast->push_back( IGoupilTopographyDatum("", 0.0)); } gSettings.topography.dataLast->back().second = cmd->GetNewDoubleValue(value->c_str()); } } /* Copy the tagged data set to the last layer */ static void CopyData(const G4String & tag) { IGoupilTopographyData * data = &gSettings.topography.data[tag]; if (data->size() <= 0) { G4ExceptionDescription description; description << G4endl << "==> Invalid data set `" << tag << "' <==" << G4endl; G4Exception("IGoupilSettings", "A GOUPIL configuration error occurred", FatalException, description); } IGoupilTopographyLayer * layer = &gSettings.topography.layers.back(); layer->ResetData(); for (IGoupilTopographyData::const_iterator i = data->begin(); i != data->end(); i++) { layer->AddData(i->first, i->second); } } /* Create a default topography layer */ static void CreateDefaultLayer(const G4String& name) { gSettings.topography.layers.push_back( IGoupilTopographyLayer(name, "Rock", 2.65 * CLHEP::g / CLHEP::cm3)); CopyData("default"); } /* Add a topography layer */ static void ProcessTopographyLayerNew( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAString * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/topography/layer/new", &ProcessTopographyLayerNew); cmd->SetParameterName("layerName", false); cmd->SetGuidance("Create a new topography layer"); } else if (op == Operation::Get) { *value = "(invalid)"; } else if (op == Operation::Set) { CreateDefaultLayer(*value); } } /* Check that there is at least one layer. Create a default one otherwise */ static void CheckLayers() { if (gSettings.topography.layers.size() == 0) CreateDefaultLayer("rock"); } /* Set the material of the last topography layer */ static void ProcessTopographyLayerMaterial( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAString * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/topography/layer/material", &ProcessTopographyLayerMaterial); cmd->SetParameterName("layerMaterial", false); cmd->SetGuidance( "Set the material of the last topography layer"); } else if (op == Operation::Get) { if (gSettings.topography.layers.size()) { *value = gSettings.topography.layers.back().GetMaterial(); } else { *value = "(invalid)"; } } else if (op == Operation::Set) { CheckLayers(); gSettings.topography.layers.back().SetMaterial(*value); } } /* Set the density of the last topography layer */ static void ProcessTopographyLayerDensity( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithADoubleAndUnit * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/topography/layer/density", &ProcessTopographyLayerDensity); cmd->SetParameterName("layerDensity", false); cmd->SetGuidance( "Set the density of the last topography layer"); new G4UnitDefinition("g/cm3" , "g/cm3", "Density", CLHEP::g / CLHEP::cm3); new G4UnitDefinition("kg/m3", "kg/m3", "Density", CLHEP::kg / CLHEP::m3); cmd->SetUnitCategory("Density"); } else if (op == Operation::Get) { if (gSettings.topography.layers.size()) { G4double density = gSettings.topography.layers.back().GetDensity(); *value = cmd->ConvertToString(density, "kg/m3"); } else { *value = "(invalid)"; } } else if (op == Operation::Set) { CheckLayers(); gSettings.topography.layers.back().SetDensity( cmd->GetNewDoubleValue(value->c_str())); } } /* Set the data set of the last topography layer */ static void ProcessTopographyLayerData( Operation::Value op, G4UImessenger * msg, G4String * value) { static G4UIcmdWithAString * cmd = NULL; if (op == Operation::Initialise) { cmd = addCommand( msg, "/goupil/topography/layer/data", &ProcessTopographyLayerData); cmd->SetParameterName("layerData", false); cmd->SetGuidance( "Set the data set of the last topography layer"); } else if (op == Operation::Get) { *value = "(invalid)"; } else if (op == Operation::Set) { CheckLayers(); CopyData(*value); } } /* Register the settings to process */ IGoupilSettings::IGoupilSettings() { addDirectory("/goupil/", "Commands for configuring GOUPIL"); ProcessChargeRandomisation(Operation::Initialise, this, NULL); addDirectory("/goupil/verbose/", "Commands for controlling GOUPIL verbose"); ProcessVerboseLevel(Operation::Initialise, this, NULL); ProcessVerboseFile(Operation::Initialise, this, NULL); addDirectory("/goupil/earthLocation/", "GPS coordinates of the World origin"); ProcessEarthLocationLatitude(Operation::Initialise, this, NULL); ProcessEarthLocationLongitude(Operation::Initialise, this, NULL); ProcessEarthLocationAltitude(Operation::Initialise, this, NULL); addDirectory("/goupil/worldOrientation/", "Orientation of the world volume (Euler angles Z1.Y2.Z3)"); ProcessWorldOrientationAlpha(Operation::Initialise, this, NULL); ProcessWorldOrientationBeta(Operation::Initialise, this, NULL); ProcessWorldOrientationGamma(Operation::Initialise, this, NULL); addDirectory("/goupil/geomagnet/", "Commands for managing the geomagnetic field"); ProcessGeomagnetDateYear(Operation::Initialise, this, NULL); ProcessGeomagnetDateMonth(Operation::Initialise, this, NULL); ProcessGeomagnetDateDay(Operation::Initialise, this, NULL); ProcessGeomagnetModel(Operation::Initialise, this, NULL); addDirectory("/goupil/primary/", "Commands for managing the primary flux"); ProcessPrimaryHeight(Operation::Initialise, this, NULL); ProcessPrimaryModel(Operation::Initialise, this, NULL); addDirectory("/goupil/topography/", "Commands for managing the topography"); ProcessTopographyBottom(Operation::Initialise, this, NULL); ProcessTopographyReference(Operation::Initialise, this, NULL); addDirectory("/goupil/topography/data/", "Commands for managing topography data"); ProcessTopographyDataNew(Operation::Initialise, this, NULL); addDirectory("/goupil/topography/data/datum/", "Commands for managing a topography datum"); ProcessTopographyDataDatumNew(Operation::Initialise, this, NULL); ProcessTopographyDataDatumOffset(Operation::Initialise, this, NULL); addDirectory("/goupil/topography/layer/", "Commands for managing a topography layer"); ProcessTopographyLayerNew(Operation::Initialise, this, NULL); ProcessTopographyLayerMaterial(Operation::Initialise, this, NULL); ProcessTopographyLayerDensity(Operation::Initialise, this, NULL); ProcessTopographyLayerData(Operation::Initialise, this, NULL); } const IGoupilTopography & IGoupilSettings::GetTopography() { return gSettings.topography.layers; } void IGoupilSettings::SetTopography(IGoupilTopography topography) { gSettings.topography.layers = topography; } /* Clean the memory */ IGoupilSettings::~IGoupilSettings() { /* Clean all commands */ for (std::list::iterator i = gCommands.begin(); i != gCommands.end(); i++) delete *i; /* Clean all directories */ for (std::list::iterator i = gDirectories.begin(); i != gDirectories.end(); i++) delete *i; } /* Fetch the settings */ G4String IGoupilSettings::GetCurrentValue(G4UIcommand * command) { ProcessorWrapper * wrapper = dynamic_cast(command); G4String value; wrapper->Process(Operation::Get, NULL, &value); return value; } /* Process the settings */ void IGoupilSettings::SetNewValue(G4UIcommand * command, G4String newValue) { ProcessorWrapper * wrapper = dynamic_cast(command); wrapper->Process(Operation::Set, this, &newValue); } /* Encapsulation of the single instance of the settings */ IGoupilSettings * IGoupilSettings::GetInstance() { static IGoupilSettings instance; return &instance; }