Unlike it's predecessor, g4numi, the current version of does not have a simple ASCII test file that describes the geometry. Instead, additional Geant User Interface "cards" have been added to control the geometry of the beamline. The reasons for adopting the standard Geant4 command interface instead a custom file are:

Complexity of the problem:

While the configuration of a highly modelled, and thereby simplified, Horn can indeed be described by a few basic numbers, a better simulation requires the use of equations to describe the thickness of the inner conductors and (optional) additional volumes needed to take into account the layer of cooling water around this inner conductor. Thus, such a "simple" ASCII will have to support a Domain Specific Language that contains conditional instructions, some of them interrelated. For instance, one would like to summarize a set of options that contains a self-consistent design of a target capable of sustaining 1.2 MW operations.

Note also that since Geant4 acts as finite state system, as the complete simulation occurs in well defined phase (global initialization, run initialization, run termination, and so forth). Thus, some instructions are only valid when Geant4 is in a specific state, something which is difficult to implement with a single "simple" ASCII file.


Geant4 User Interface Commands system does exist, and is well documented. Let us use it to our advantage.


As new commands are simply added to existing ones, the basic use of the g4lbne commands follows those documented in . While this link addresses application tool kit issue, let us start from the end-user perspective. At some point, either in a batch or interactive environment, the user will issue the following Unix command from his Unix shell (most likely, bash):

  .../g4lbne ./macros/myCommand.mac 

where "..." refers to the Unix path name where the executable resides. The file myCommand.mac is the macro files that contains the values of the G4UI cards. This pages described it's use, how to modify and extend one such file. In it, only a few commands are actually mandatory, as all the variables, defined in g4lbne source code, that corresponds to G4UI command do have default values. However, for real studies, most of the commands will consist of directives, specific to the study you have in mind. The mandatory commands in such macro file are:

# A simple macro file 
/LBNE/run/NEvents 1000
/LBNE/output/OutputNtpFileName test2_100k_B

This is the shortest macros file one should consider using. The is so-called "Nominal" macro g4lbne will run on. It will produce an neutrino Ntuple that corresponds to our baseline, possibly not quite as updated as one would like. More on this later. Lines starting with "#" are ignored by the G4UI and therefore can be a good place to insert comments.

The first line sounds truly superfluous, of course we'd like to build LBNE, one day. But it signals a change of state in Geant4: from the pre-init state to the state where the geometry is defined. Prior to this line, the users can make modifications to the geometry, to which we'll go back a bit later. In practice, no matter what, we probably want to control the duration of our run, so setting the number of events is de-facto mandatory. Since, by default, g4lbne will generate a Neutrino Ntuple, we might as well specify the file name as well, so we know what to look for when the g4lbne run is completed. (Note that Python scripts can modify these lines, which are quite convenient to run in a Grid environment).

The next line also indicates a change of state: we actually pressed to "go" button", and Geant4 will throw proton on target, and collect neutrino. Once that is done, the run is over and we exit. Since Geant4 allows for multiple runs, we'll have to tell when to quit, for clean termination, including closing output files.

O.K., we got a few neutrino out, but what's the corresponding beamline? Details, please! For instance, I was told that "powers-at be" decided to change the radius of the pipe again, a blessed modification to the baseline will be made very shortly, but is it in g4blne? The simplest way to find this out is to run g4lbne interactively, and use the standard G4UI to learn about the capabilities of g4lbne:

%host g4blne 

The first line places you in the directory where the g4lbne geometry parameters are listed. Note the Unix-like syntax. Pursuing a bit further, just type "ls", and you'll get a abbreviated listing of the available command:

PreInit> ls
Command directory path : /LBNE/det/

Guidance :
detector control

Sub-directories : 
Commands :
decayPipeLength * Length of the decay Pipe
decayPipeLongPosition * Longitudinal Position of the entrance window of the decay pipe with respect to target
decayPipeRadius * Radius of the decay Pipe
decayPipeUsptreamWindowThickness * Thickness of the upstream window of the decay pipe.

O.K. We now know that both the length and the radius of the decay pipe can be changed. More specifically, to change the radius, one inserts the following command in the macro file:
 /LBNE/det/decayPipeRadius 500

This might set the radius to 500... But, 500 meter, or cm? In addition, we still do not know what the default value is. Fortunately, a more verbose listing can be obtained by using the "/control/" G4UI command:

/control/manual /LBNE/det

will give you a complete and verbose on what can be changed. Scroll back, and you'll find:

Command /LBNE/det/decayPipeRadius
Guidance :
Radius of the decay Pipe

Parameter : decayPipeRadius
 Parameter type  : d
 Omittable       : True
 Default value   : 2000

Parameter : Unit
 Parameter type  : s
 Omittable       : True
 Default value   : m
 Candidates      : cm m

It tells you that the default values is 2000, and this ought to be mm, the default unit in Geant4. The next part is tells you that the coder decided to attach his own units to this variable. So, declaring

Command /LBNE/det/decayPipeRadius 2 m 

will give you the default value. Simply inserting:

Command /LBNE/det/decayPipeRadius 500 

will give a radius of 500 m. A bit too disturbing on the Fermilab site. Geant4 System of units is rather complete and exhaustive, tedious to find things out, though, and thereby, a bit error prone, but, that's life. ..

A complete and formatted listing can be obtained using the "/control/createHTML" command. This listing is available as an html "_LBNE_det_.html", file at the end of this page. By the time you read this page, it might be incomplete, as it is just a snapshot of what's available as of May 21 2014.

This parameters do set the geometry of the g4lbne beamline, as designed. The actual position of important devices, such as target and horns might be slightly misaligned with respect to the nominal beamline. Thus, an additional set of G4UI commands have been added, to simulate the process of the survey of an instance of the "as-build" LBNE beamline. This will be obviously relevant when the LBNE beam line is actually assembled. Meanwhile, simulation exercises do tell us something about the anticipated systematic uncertainties. These commands - and the corresponding g4lbne code, have been written making some assumptiosn on how these components will actually be surveyed, and based on previous experienced. For instance, the alignment pins on either Horn1 or the target can are not just the expression of the not-so-fertile imagination of the developer: these are parts of the NUMI beamline gadgets.

For consistency, to each surveyed volumes in g4lbne are associated for G4UI commands, available in the "/LBNE/Surveyor" command directory. Each such commands allows the user to enter the xyz coordinates of the alignment pin, or ball, at the left (or right), downstream (upstream) side of the volume. For instance,

/LBNE/Surveyor/ PosUpstreamLeftPinTargetHeTube  3.1 0.0 0.
/LBNE/Surveyor/ PosUpstreamRightPinTargetHeTube  3.1 0.0 0.

states that the upstream position of the left side of the Target Helium container vessel, which contains the target, has been found at _x_=3.1 mm off to it's nominal position. Same for the right side. This means that the target has been moved by + 3.1 mm along the X-axis. Note that the downstream position, if left undeclared, has default position of (0., 0., 0.). This implies that the target is actually tilted by ~3,1 mrad, since the target length is approximately 1m. long. Should the second data card be omitted, the position on the right side is left at _x_=0. Which leads us to an inconsistency in the survey. The current code does not flag this as an error, and simply takes the arithmetic average of the left and right position.

There are currently five such surveyed volume in the beam line:

  1. The target canister (kind of irrelevant for flux studies..)
  2. The Target Helium Container vessel that hold the target in place.
  3. Horn1 : The mother volume that contain both the Inner and Outer conductor of Horn1
  4. Horn2 : idem
  5. DecayPipe : The decay pipe.

More can be added as we go along. Note that, for now, the Z-coordinate is not used to characterize misalignment. It is assume the survey can be done with enough accuracy along the beam line. However, by design, one can pull the target in or out of the Horn1, as well as changing the longitudinal position Horn 2, via the LBNE/det command cards. (Horn1 defines Z = 0., so that one is, by fiat, not movable).

Installing a simple Horn 1 that can be optimized upon.

The NuMI horns were originally designed for a relatively higher neutrino energy than for LBNE. The possibility to have the entire target inserted in the Horn1, along with a straight upstream section up to the neck, is appealing, as it will enhance the flux for low energy pions ( about 5 GeV). Thus, we have a need for a flexible way to define an arbitrary shaped inner conductor, such that we can quantify the gain in flux for such a new Horn 1.

In august/Sept 2014, the geometry of the target and Horn 1 have bee re-implemented, such that a new target can easily be inserted in Horn1, as well as a plug downstream of the Neck. The mother (in Geant 4 sense) volume that physically encompasses Horn1 is now a "G4Polycone", not a simple tube, such that other volumes can be inserted into it, provide the inner radius is smaller than the innter radius of the inner conductor, of course. This upgrade allows us to implement a new type of Horn1, based on a simple table that describe the shape of the inner conductor. As usual, of course, this is entirely optional, the default Horn 1 is style of the NuMi style.

Should the user decide to verify that, indeed, the flux improves at low energy when a 1/2 parabolic Horn1 is used, where the upstream part of the inner conductor is (almost) a simple cylinder, he now can define such a device with the following G4UI data cards:

/LBNE/det/UseHorn1Polycone True
/LBNE/det/NumInnerPtsHorn1Polycone 15
/LBNE/det/Horn1PolyPt0RinThickZ   40.000   2.500       0.00 mm
/LBNE/det/Horn1PolyPt1RinThickZ   19.000   2.500      12.50 mm
/LBNE/det/Horn1PolyPt2RinThickZ   19.000   2.500     850.00 mm
/LBNE/det/Horn1PolyPt3RinThickZ   98.167   2.495    1556.67 mm
/LBNE/det/Horn1PolyPt4RinThickZ  162.292   2.480    1733.33 mm
/LBNE/det/Horn1PolyPt5RinThickZ  212.958   2.455    1910.00 mm
/LBNE/det/Horn1PolyPt6RinThickZ  251.750   2.420    2086.67 mm
/LBNE/det/Horn1PolyPt7RinThickZ  280.250   2.375    2263.33 mm
/LBNE/det/Horn1PolyPt8RinThickZ  300.042   2.320    2440.00 mm
/LBNE/det/Horn1PolyPt9RinThickZ  312.708   2.255    2616.67 mm
/LBNE/det/Horn1PolyPt10RinThickZ  319.833   2.180    2793.33 mm
/LBNE/det/Horn1PolyPt11RinThickZ  323.000   2.095    2970.00 mm
/LBNE/det/Horn1PolyPt12RinThickZ  323.792   2.000    3146.67 mm
/LBNE/det/Horn1PolyPt13RinThickZ  323.792   1.895    3323.33 mm
/LBNE/det/Horn1PolyPt14RinThickZ  324.583   1.780    3500.00 mm
/LBNE/det/Horn1PolyOuterRadius 360.0 mm

Of course, the above is just an example. The first two card, as well as the last one, are mandatory, if the first card is entered. This first card will de-facto remove the NuMi style Horn1, and provide a much simplified Horn, where we have no welds, no spider support, Inner/Outer transition conductor. Just an inner conductor defined by a table, and the outer conductor of fixed thickness (2.5 cm). The material is aluminium. However, a uniform thickness water layer on the inner conductor does exist as well (default thickness, 1 mm, as for the NuMI horn. ).

The second card specifies the number of points that define the shape of the inner conductor. It is a "cylindrical polygon", i..e, of azimuthal symmetry, with abrupt change of its radius at discrete Z locations. Up to 20 such points can be defined. Three separate quantities define such a point: (i) the inner radius of the inner conductor at this Z location. (ii) The thickness of the aluminium conductor (iii) The Z coordinate for the change in radius of the inner conductor. The first point must be a Z = 0., which is also the origin (Z=0.) for the Geant4 world coordinate system.

The last data card specifies the outer conductor radius, inner side. Its thickness is currently fixed at 2.5 cm. (If important, yet an other G4UI can be create if need be).

In the above example, the length of Horn is 3.5m, it's thickness at the neck is only 2.5 mm ( against 4.5 mm for the NuMI), and only 1.780 at a radius of 32.5 cm. It is approximately parabolic downstream of Z = 85 cm, the length of upstream, cylindrical upstream section. This is shown graphically in the following picture:

Installing Multiple Polycone Horns

During F.Y. 2015, it was shown that a higher neutrino yield and thereby improved sensitivity to the CP violating phase in the Neutrino oscillation phenomena was obtained by (i) optimizing the shape of Horn1, using the above method to define it (ii) by rescaling Horn2, and moving it downstream. (See talks by Laura Fields, CD1-refresh reviews). As a result, both the width and the length of the chase were increased in the baseline design. It makes sense to try to optimize the shape of the Horn2 conductor as well. In addition a 3-Horn system has been proposed in the past. Little improvement has been obtained (Byron Lundberg, talks presented in LBNE Beam design meeting, more recently M. Bishai talk the first LBNF beam optimization meeting). However, our G4 based tool and the amount of CPU available for such calculations have improved markedly over the last few decades, so it does make sense to have an other go at it.

Therefore, we have implemented a new set of data cards, and the corresponding G4 geometry code, aiming a defining up to 5 simple Polycone Horns. They replace the NuMI Horn1 and Horn2. It is assumed that the length of the chase is 17.3 m. long (the decay pipe snout is removed), and a usable width of 78 inch. (It is advisable to keep ~ 6 inches on both sides for installation clearance, but this constraint is not implemented in the code yet). This section documents this upgrade. Note that the G4LBNE is fully backward compatible with regards to the implementation of the Horns, that is, one can still use the NuMI hors (default), or a single optimized Horn1, rescaling Horn2, etc..

The first data card is obvious: we need first to define the number of Polycone Horns:

/LBNE/det/NumberOfHornsPolycone n

where n ranges from 1 to 5, inclusive. The first horn always starts (i.e., it's field region) at Z=0., G4 world coordinate system. The Z location next horns, located downstream of Horn1 are defined with the following data card:

/LBNE/det/HorniPolyZStartPos 6600 mm

where i is the horn number, ranging from 2 to 5, inclusive. For any given horn i, The number of sections is defined as in the section above:

/LBNE/det/NumInnerPtsHorniPolycone 10

And, for sake of consistency, the inner radius, inner conductor thickness and length of each section is defined as before:

/LBNE/det/HorniPolyPt0RinThickZ 417.  2.000  0.00 mm
/LBNE/det/HorniPolyPt1RinThickZ 21.1277198234  2.000  1.00 mm
/LBNE/det/HorniPolyPt2RinThickZ 21.1277198234  2.000  1625.92686049 mm

The outer radius of the Horn is defined by

/LBNE/det/HorniPolyOuterRadius 425 mm

Notice that its size is ~ 7 mm bigger that the biggest radius of any given longitudinal section of the Polcone that defines the shape of the horn. This is because the width of the outer conductor is fixed (~ 1/4 inch), the quantity defined by this data cards is the outer radius of the device. (In retrospect, this data card is sort of reundant, but it was kept for backward compatibility.)

Installing Parabolic Polycone Horns

At the Sept 2015 collaboration meeting, (or shortly thereafter) John LoSecco proposed to install PolyParabolic horns: Instead of having the Inner Conductor made of multiple cones, we could have multi parabolic horns, with curvature signs that are set according to the goal of having focal lengths that depends linearly on the radius of the charged particle moving through the horn.

This is just a logical flag, assign to given Polycone horn. The above interfaces are valid. Just add:

/LBNE/det/SetPolyconeHornParabolic ix

where ix is the horn number (ranging from 1 to 5)

Advanced Instruction for the sceptics.

And the code developers! In fact, this section addresses two distinct issues:
  • How do I convinced myself that by changing the radius of the decay pipe via the above G4UI data card, I actually am running g4lbne with an appropriately modified geometry?
  • How do I installed a new g4lbne-G4UI command card, for changing, say the thickness of the outer conductor of Horn2?

So, let us trace the C++ code related to an existing g4lbne-G4UI command card, say "/LBNE/det/decayPipeRadius". Adding a new card will become obvious in the process. Three - possibly more, depending on side effects of changing a parameter in the code - classes are involved:

  1. LBNEPlacementMessenger : This is the class where the geometry that are relevant to sizing or placing the volumes are defined. Messenger is a key word borrowed from the Geant4 tool-kit: It take a message from the user and establishes the required communication path to the actual algorithm that defines and places the volume in question. A simple Unix grep command in the source directory leads you to the following code, in file

fDecayPipeRadius = new G4UIcmdWithADoubleAndUnit("/LBNE/det/decayPipeRadius",this);
fDecayPipeRadius->SetGuidance("Radius of the decay Pipe");
double value = volP->GetDecayPipeRadius();
fDecayPipeRadius->SetDefaultValue (value);
fDecayPipeRadius->SetDefaultUnit ("m");
fDecayPipeRadius->SetUnitCandidates ("cm m");

in the constructor of the LBNEPlacementMessenger class. The first few line simply defines the G4UI command. The last line states that this command must be issued prior to the initialization of the geometry. You'll note that the default value for this parameter is picked from an other place, via the volp pointer. The leads us to the 2nd class in the problem, LBNEVolumePlacements But, before going there, let us finish the investigation of the class LBNEPlacementMessenger. Once the command is defined, we have one more task to do: establish the call-back from the messenger to the class that will actually be using the new value. This is done in the mandatory SetNewValue of the messenger class:

if (command == fDecayPipeRadius) {
G4UIcmdWithADoubleAndUnit* cmdWD = dynamic_cast<G4UIcmdWithADoubleAndUnit*> (command);

This time around we use a "setter" instead of an "accessor" of the  LBNEVolumePlacements class. So, now, let go to this next class:
  1. LBNEVolumePlacements : Here, we will use the data member fDecayPipeRadius . (Same C++ variable name as in the previous class, as the difference of function is expressed in the class name, so, no point differentiating them again.) You'll easily find the corresponding inline setter and accessor in the LBNEVolumePlacements.hh :

inline double GetDecayPipeRadius() const { return fDecayPipeRadius; }

... and ...
inline void SetDecayPipeRadius(double l) {fDecayPipeRadius=l;}

Note: should we have studied changing the length of the pipe instead of its radius, we'll notice that the setter are not always trivial:

inline void SetDecayPipeLength(double l) {
const double lCorr = l + fDecayPipeLengthCorrection;
fDecayPipeLength=lCorr; fTotalLength = 2.0*(fDecayPipeLength + 160.*m + fLengthOfRockDownstr);

Indeed, by changing the length of the decay pipe has implication for the total length of the beamline, obiviously. Hence, the requirement that such G4UI commands be issued at the pre-init stage. Note also a bit of naughty thing: the hardcoded "160." meters, which must be coming from somewhere and therefore should have been declared as data member.. Nobody is perfect..

Moving on, let now find how fDecayPipeRadius is used in the LBNEVolumePlacements class. Again, searching to the code for this fDecayPipeRadius variable, one finds in the constructor:

fDecayPipeRadius = 4.0*m/2.;

Indeed, the adopted default for the beam pipe radius is 2 meters. Good. Note that this variable is also used to defined other sizes.  For instance:

if (name == G4String("Tunnel")) {
info.fParams[0] = std::max((18.5*m), 2.0*(fDecayPipeRadius));
// Note: the total volume is 60 m. wide => plenty enough rocks. The last term is for the Hadron Absorber cavern
info.fParams[1] = std::max((50*m), 2.0*(fDecayPipeRadius)); // Too tall... Set by the Hadron absorber requirement
info.fParams[2] = fTotalLength - fLengthOfRockDownstr -2.0*cm;
std::cerr << " Total half length of the tunnel " << info.fParams[2]/2. << std::endl;

This is the code the mother volume "Tunnel" is defined. Again, changing one size has implication in the other parts of the design.. Finally, we come to the point where the actual beam pipe volume, which will be filled with Helium, is defined:

if (name == G4String("DecayPipeVolume")) {
info.fParams[0] = 0.; // such that the decay pipe wall & volume
// can be surveyable.
info.fParams[1] = fDecayPipeRadius - 0.010*mm;
info.fParams[2] = fDecayPipeLength ;
G4Tubs* tubs = new G4Tubs(volumeName, info.fParams[0], info.fParams[1],
info.fParams[2]/2., 0., 360.0*deg);
info.fCurrent = new G4LogicalVolume(tubs, G4Material::GetMaterial("DecayPipeGas"), volumeName);

Note the comment here: so far, we only defined the volume as a rigid body, it still needs to be surveyed! The LBNEVolumePlacement class acts here as container for placement data, which will be used later, in the third class in the problem: The LBNEDetectorConstruction class:

@ //
// Place the decay pipe
G4PVPlacement *vDecayPipe = fPlacementHandler->PlaceFinal(G4String("DecayPipeHall"), tunnel);
fPlacementHandler->PlaceFinal(G4String("DecayPipeConcrete"), vDecayPipe);
fPlacementHandler->PlaceFinal(G4String("DecayPipeOuterWall"), vDecayPipe);
fPlacementHandler->PlaceFinal(G4String("DecayPipeWall"), vDecayPipe);
fPlacementHandler->PlaceFinal(G4String("DecayPipeVolume"), vDecayPipe);


Where we create these volumes, and place them, one by one. For some specific volumes, the method LBNEVolumePlacements::PlaceFinal invokes the LBNESurveyor class, to find out where such surveyed volumes are:

if (name == G4String("DecayPipeHall")) surveyedPtName = std::string("DecayPipe");

Note that we surveyed the decay pipe hall, it does not make sense to survey the decay pipe volume itself. The actual positioning of the volume involves both a translation and a rotation, defined later in that method.

Note the last class in the game is the LBNESurveyor class, where