Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Luter 345 Experiments
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Adjusting Variables at Run-Time
Page
Discussion
English
Read
Edit
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
Edit source
View history
General
What links here
Related changes
Special pages
Page information
Get shortened URL
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
The edit appears to have already been undone.
Anti-spam check. Do
not
fill this in!
==Summary== When running simulations, it is common to want to change some aspects of the simulation. This can be cumbersome, because changing any of the source files requires the program to be recompiled. A convenient solution to this problem is to create a Variables class and input file that contain any variables that may need to be manipulated. Then the main method must be adjusted to read in these variables at run time. This way, the input file can be manipulated between runs without having to recompile. ==The Main== The existence of a main method is essential to the inter-workings of the controlling class. This is true for most major object oriented programming languages like Java and C++. Geant follows suit by requiring the user to create their own main method. Below I will highlight the key items that are required in a minimal main method. '''1. Importance of G4RunManager''' *Constructs major manager classes of GEANT4 - ''Completed in the Constructor'' G4RunManager* runManager = new G4RunManager; *Manages initialization procedures including methods in user initialization classes - ''Invoke Initialize()'' // Initialize G4 kernel runManager->Initialize(); *Manages event loops - ''Invoke beamOn()'' *Terminates major manager classes of GEANT4 - ''Completed in the Destructor'' delete runManager; '''2. Mandatory User Classes''' *Detector Construction - Materials & Geometry runManager->SetUserInitialization(new S1DetectorConstruction()); *Physics List - Particles & Physics Processes // Physics list G4VModularPhysicsList* physicsList = new QBBC; physicsList->SetVerboseLevel(0); runManager->SetUserInitialization(physicsList); *Primary Generator Action - Make Primary Event //User action initialization runManager->SetUserInitialization(new S1ActionInitialization()); ==Input Files== '''Example:''' Initialization File #X-length of both scintillators (in cm) scintX 30.5 #Y-length of both scintillators (in cm) scintY 17.0 #Z-length of both scintillators (in cm) scintZ 1.0 #height(POSITION) of bottom scintillator (in cm) bottomScintPos -30.0 #height(POSITION) of top scintillator (in cm) topScintPos 30 #thickness of the Lead layer (in cm) blockThickness 15.0 #the material the block will be made of (must be a valid G4Material name) blockMaterial G4_Pb #name of the output file(ONLY THE BASE NAME, THICKNIESS WILL BE ADDED AS A SUFFIX IN THE PROGRAM) #outFileBase S1_thickness_ outFileBase S1_uncert_ #the run number (for finding an uncertainty in positron count) runNum 10 As seen above, the initialization file is essentially a list of all variables in the program that may be necessary to change between runs. The benefit to using this type of file is that it can be changed without having to recompile the program. Obviously it is crucial to know what type these variable should be, what units the number should be in if applicable, and what order these variables should be in. The hash-tagged lines are comments, and should be used gratuitously if some other person may end up using the program so the requirements of the input file are clear. Input files get read at run-time by the variables class via the main file. In other words, the main calls a read file function of the variables class that then reads and saves the appropriate variables. Typically this is the first, or one of the first, actions to occurs in the main. A quick example of the line in the main is provided below, and a more robust explanation of the variables class is provided in another section farther below. int main(int argc,char** argv) { //The first object to load should be the variables, since they are read externally //Create a variables object to read and store the variables Variables = new S1Variables(); //Insert the input file here, ours is called S1.ini G4String dataname = "S1.ini"; //call the function to read the data from the file Variables->loadFromFile(dataname); ==Variables Class== The variables class is the class that allows use of an input file and other classes to use those variables. In this class, all desired variables (ones that will be used throughout the simulation, often in different classes) should be defined with appropriate getters and setters, as well as a read function. This read function is the crux of the whole input file process, and thus will be focused upon heavily here. Below are a few example sections of a variables class, and explanations of the code are provided after. //this example requires the use of a string stream, a c++ class #include <sstream> //the following are definitions of some functions to read in the variables from the file #define READBOOL(myx) \ if (buf == #myx) \ { \ ss >> wert; \ myx = ReadBoolean(wert); \ } #define READDOUBLE(x) \ if (buf == #x) \ { \ ss >> doublewert; \ x = doublewert; \ } #define READINT(x) \ if (buf == #x) \ { \ ss >> intwert; \ x = intwert; \ } #define READSTRING(x) \ if (buf == #x) \ { \ ss >> x; \ } #define READVECTOR(v) \ if (buf == #v) \ { \ G4double x,y,z; \ if (ss >> x >> y >> z) \ v = G4ThreeVector(x, y, z); \ } //this is the default constructor S1Variables::S1Variables() { //Any defaults should be set in this space in case loadFromFile() fails } G4bool S1Variables::loadFromFile(G4String FileName) { //reads from some input file(S1.ini), which should list all variables in appropriate order ifstream infile; G4String line; infile.open(FileName); if (infile) { G4String outFileBase; G4String outFileTag; while (!infile.eof()) { if (getline(infile,line)) { G4String buf; G4String wert; G4double doublewert; G4int intwert; stringstream ss(line); ss >> buf; READDOUBLE(scintX); READDOUBLE(scintY); READDOUBLE(scintZ); READDOUBLE(bottomScintPos); READDOUBLE(topScintPos); READINT(blockThickness); READSTRING(blockMaterial); READSTRING(outFileBase); READSTRING(outFileTag); READINT(runNum); } } As stated earlier, all the variable names are already defined in the associated header file but are not initialized until the readfile function is executed. If this function fails, as occasionally happens when performing file io, it is always a good idea to initialize with some defaults in the constructor so the program can will not fail altogether. The defined functions at the top are crucial to the function as well as the string stream class, and explanations of these features will not be discussed here, as better and more in depth discussions can be found on any number of c++ reference pages. From the piece of the example presented, it is clear how this function works: An io stream is opened and that stream passes lines to the string stream, which is then parsed by the string stream and the corresponding data is read and saved by the predefined functions at the top. For this to work properly it is of great importance that the input file being read adhere to strict structure rules, and the example input file found in another section above can be used as reference. Once the above code is executed the variables have been read and can now be used throughout the simulation. In some cases the variables may require further manipulation. One common example of this is an output file name. In the code presented above, there are two variables read in called "outFileBase" and "outFileTag" that were used, along with some other variables found above, to create a file name that would later hold the nTuple produced by the simulation. Below is how this process was coded, albeit in a round-about way. Again for other methods of concatenation use your favorite c++ reference site. stringstream holdRunNum(""); stringstream holdThick(""); holdRunNum << runNum; holdThick << blockThickness; outFile = (outFileBase + holdThick.str() + outFileTag + holdRunNum.str() + ".root"); Here "outFile" is the actual variable held by the variables class, but there is no convenient way to craft the complete file name prior to reading the variables in. If running in batch mode this is a simple trick to automate the file naming process according to a convention, which makes further use of those files simple (i.e. looping through files in a ROOT macro). I will admit this string stream method is a poor method to use for concatenation so it may be better to find a new method when crafting your own simulation; However, it does work so if in a bind, feel free to utilize.
Summary:
Please note that all contributions to Luter 345 Experiments may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Luter 345 Experiments:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)