Skip to content

Latest commit

 

History

History
406 lines (330 loc) · 14.4 KB

dev_runthecode.adoc

File metadata and controls

406 lines (330 loc) · 14.4 KB

Running the Code: The Basics

In order to run GENIE as a developer it is important to understand how to run specific interaction channels on specific targets. It is also important to understand how to run the code inside of a debugger. Adding logging commands and recompiling is a very painful way to make progress and in a loosely-coupled framework like GENIE, where so much of the configuration is stored in XML files and enforced only at run-time, it is difficult to rely on the compiler to find some classes of bugs.

Getting Set-up

It is useful to add a `set up'' function to your `.bash_profile (or the appropriate file if you use a different shell):

function gwork () {
  export GENIEWORKDIR=(Your working area)/GENIE/
  echo "Setting working directory to {d}GENIEWORKDIR"
  cd {d}GENIEWORKDIR
  source environment_genie.sh
}

Generating an Interaction Spline

These splines are used by the flux driver to calculate whether an interaction takes place. It additionally specifies which interactions are possible: processes that don’t exist in the spline file or have zero cross section at the neutrino’s energy will not be selected. We can use that to our advantage when developing a new model by building a spline that only includes our interaction channel. These splines only provide the total cross section though - to get the kinematics of the event we will need to evaluate the differential cross section during event generation.

Let’s generate cross-section splines for muon-flavor neutrinos on Carbon for CCQE events only:

nice gmkspl -p 14,-14 -t 1000060120 \
  -o ccqe_carbon_splines.xml --event-generator-list CCQE

If we run this for one event generator only, we will find a short XML file with contents like (slightly reformatted for presentation):

<?xml version="1.0" encoding="ISO-8859-1"?>

<!-- generated by genie::XSecSplineList::SaveSplineList() -->

<genie_xsec_spline_list version="2.00" uselog="1">

<spline
    name="genie::LwlynSmithQELCCPXSec/Default/nu:-14;
    tgt:1000060120;
    N:2212;
    proc:Weak[CC],QES;"
    nknots="44">
  <knot> <E>    0.01000 </E> <xsec>          0 </xsec> </knot>
  <knot> <E>   0.030466 </E> <xsec>          0 </xsec> </knot>
  <knot> <E>   0.050932 </E> <xsec>          0 </xsec> </knot>
  <knot> <E>   0.071399 </E> <xsec>          0 </xsec> </knot>
  <knot> <E>   0.091865 </E> <xsec>          0 </xsec> </knot>
  <knot> <E>    0.11233 </E> <xsec>          0 </xsec> </knot>
  <knot> <E>     0.1427 </E> <xsec> 8.487371629e-13 </xsec> </knot>
  <knot> <E>    0.18129 </E> <xsec> 4.103713443e-12 </xsec> </knot>
  <knot> <E>     0.2303 </E> <xsec> 8.367696679e-12 </xsec> </knot>
  <knot> <E>    0.29257 </E> <xsec> 1.290439962e-11 </xsec> </knot>
  <knot> <E>    0.37168 </E> <xsec> 1.807792243e-11 </xsec> </knot>
  ...

Copy this file to your \$XSECSPLINEDIR. Note that for single-model work, the value of the cross section (in milibarns) need not be exactly correct and sometimes it is convenient to ``hack'' a spline file (for example, when working on a differential cross section formula for a new model in order to be able to generate a spline file).

See config/EventGeneratorListAssembler.xml for a list of valid event generator lists. If we check there, we find entries like:

<param_set name="CCQE">
   <param type="int" name="NGenerators"> 1                            </param>
   <param type="alg" name="Generator-0"> genie::EventGenerator/QEL-CC </param>
</param_set>

We can see that if we specify a list containing only CCQE, that the number of generators is set to one and the algorithm `category'' is identified. We can see what that means by investigating `\$GENIE/config/UserPhysicsOptions.xml:

 <!--
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Specify which cross section model is to be used by each GENIE
  event generation thread. The parameter name is build as:
  "XSecModel@[name of thread]"
  -->
<param type="alg" name="XSecModel@genie::EventGenerator/QEL-CC">
  genie::LwlynSmithQELCCPXSec/Default
</param>

Here we find a useful comment and the actual algorithm used. It is a GENIE convention to name files after classes, so we can quickly find the code with (in the GENIE source directory):

find . -name "*LwlynSmithQELCCPXSec*" | grep -v svn | grep -v ROOT
./LlewellynSmith/LwlynSmithQELCCPXSec.cxx
./LlewellynSmith/LwlynSmithQELCCPXSec.h

Generating Events on Simple Targets

For physics work, we obviously want to use the rich detector geometry and flux facilities offered by GENIE, but for initial coding development work, it is fine to run using a single nucleus.

Create a shell script to run your job, do_a_ccqe_run.sh:

#!/bin/sh
gevgen -n 5 -p 14 -t 1000060120 -e 1,2 --run 100 \
  -f 'x*exp(-x)' \
  --seed 2989819 --cross-sections {d}XSECSPLINEDIR/ccqe_carbon_splines.xml \
  --event-generator-list CCQE

(Be careful of trailing spaces after the line-continuation characters if copying-and-pasting this code.) It is also useful to be able to specify mono-energetic beams. You can do this by dropping the -f flag and giving just one number to the -e flag.

Running Inside gdb

gdb is a large and full-featured program and it is impossible to go over all the features here. Instead, we will present a short list of common commands. These will be demonstrated in the walkthrough.

Important
For Mac users, Apple’s recent decision to stop supporting the GNU toolchain makes using gdb painful on a Mac. There are comments online suggesting ways to get gdb working again, but I have had limited success. The alternative is to use lldb as a debugger instead. Google searches will turn up tutorials and gdb to lldb cheatsheets. What lldb lacks (at the moment) is a `graphical'' mode that shows large sections of the source code concurrent with the stepper. We are investigating an extension that may solve this problem. In the interim, please try to run this tutorial on Linux or an older version of OSX that supports `gdb. We are workging on an lldb version of the instructions and walkthrough.

Note that gdb will automatically extend unambiguous abbreviations of words, so b, br, bre, brea, and break are all equivalent. However, f is ambiguous because there are commands file, finish, flushregs, and so on.

gdb Commands
  1. n - continue to the next line.

  2. s - step into the next function call.

  3. fin - step out of a function call.

  4. c - continue to the next break point.

  5. u - finish the current loop. (Note: this can be a bit slow. You may wish to use a break after the loop instead.)

  6. b - set a breakpoint at the current line.

  7. info b - look at the existing set of break points.

  8. disable N - disable breakpoint N. disable will disable all breakpoints.

  9. enable N - disable breakpoint N. enable will enable all breakpoints.

  10. p var - print a variable’s value. This has surprising power. print i to look at a loop counter, but also print *p to de-reference a pointer, and even print p→method(). You can use tab-completion with p.

  11. Control-l - Clean the screen (very useful after large blocks of text go to stdout).

  12. Control-x o - Switch focus in TUI mode (e.g., up and down arrow keys will scroll code or move through gdb history).

  13. Control-x Control a - Switch TUI mode on and off.

Put the set args…​ command on one line. Environment variable resolution (e.g., \$XSECSPLINEDIR) is temperamental in gdb, so it will be useful to save a few fully-formatted commands in local text files.

gdb -tui gevgen

set args -n 5 -p 14 -t 1000060120 \
  -e 0,10 --run 100 -f 'x*exp(-x)' --seed 2989819 \
  --cross-sections <Your Dev>/data/ccqe_carbon_splines.xml \
  --event-generator-list CCQE

Note: you will often want to turn the default logging verbosity down. Copy the file Messenger_laconic.xml over the default Messenger.xml (save the default if you’d like). You may even prefer to create a Messenger_fatal.xml file with all output levels set to FATAL only. (The logging output is not needed while inside gdb since you may inspect variables directly.)

gdb: Printing Variables

We can print (or just p) variable names and even de-reference pointers:

(gdb) p i
(gdb) p	fXSecModel
(gdb) p *fXSecModel

Printing a std::string is sometimes tricky. If you’re having trouble, try (for string ``inpfile''):

(gdb) p *(char**)inpfile._M_dataplus._M_p
$3 = 0xa682038 "/minerva/app/users/perdue/GENIE/data/coh_carbon_splines.xml"

gdb: Breakpoint Commands

We can break on a line in the file we’re stepping through:

(gdb) break 158
Breakpoint 13 at 0x2b8e0f0c4781: file COHKinematicsGenerator.cxx, line 158.

Then, we can add a set of commands for gdb to execute every time we hit that breakpoint:

(gdb) commands 13
Type commands for when breakpoint 13 is hit, one per line.
End with a line saying just "end".
>silent
>printf"xsec =%g ; Q2 = %f ; y= %f ; t = %f \n", xsec, gQ2, gy, gt
>end
(gdb) c
Continuing.
xsec =5.17161e-16 ; Q2 = 0.602666 ; y= 0.730704;   t = 0.191961
Continuing.
xsec =7.96193e-15 ; Q2 = 0.415240 ; y= 0.625730; t = 0.148100
Continuing.

gdb: Conditional Breakpoints

It is also often useful to only break if a certain condition is met:

(gdb) break 119 if tpi < 0
(gdb) info b
...
10      breakpoint     keep y   ...
        stop only if tpi<0

We can turn conditions off with condition number where number is the breakpoint number and then reset them if we choose:

(gdb) condition 11
Breakpoint 11 now unconditional.
(gdb) condition 11 xsec      > 5e-10
(gdb) info b
Num     Type           Disp EnbAddress               What
...
11      breakpoint     keep y   0x00002ad85a8c3fa4 in ...
        stop only if xsec > 5e-10
        breakpoint already hit 254 times
        printf "xsec = %g\n", xsec

Running valgrind

Our goal is naturally that there be no resource leaks, but that is impossible given the resource leaks that invariably appear in third-party code. ROOT [Brun:1997pa], for example, contains some leaks by design. The most we can expect is that new work on model development will not introduce any new resource leaks.

We will want to run valgrind in a deep diagnostic mode. Edit a file in your GENIE run directory called .valgrindrc and include these lines:

--num-callers=50
--leak-check=full
--verbose
--show-reachable=yes
--suppressions=valgrind-genie.supp

The first step towards sensible output with ROOT is to create a suppressions file. ROOT is distributed with a default file in \$ROOTSYS/etc, but the default version may not work with older releases of valgrind. In that case, first create a suppressions file with this script:

#!/bin/sh
valgrind --log-file-exactly=tmp.txt --gen-suppressions=all \
 gevgen -n 5 -p 14 -t 1000060120 -e 0,10 --run 100 \
 -f x*exp\(-x\) --seed 2989819 \
 --cross-sections \$XSECSPLINEDIR/gxspl-vA-v2.8.0.xml

Next, we will want to scrub the log file to get only the suppressions. Use the Perl script trim_suppressions_log.pl:

#!/usr/bin/env perl

# Run on the captured output of a valgrind job with suppression
# generation turned on to remove everything but the suppression
# messages.

if ($ARGV < 2 ) {
  print " USAGE:\n";
  print "   $0 [-i valgrind log file] [-o output suppressions file]\n";
  exit 1;
}

foreach $argnum (0 .. $ARGV) {
  print $argnum."\n";
  if (lc($ARGV[$argnum]) eq "-i") {
    $logfile = $ARGV[$argnum+1];
  }
  elsif (lc($ARGV[$argnum]) eq "-o") {
    $suppfile = $ARGV[$argnum+1];
  }
}
print $logfile."\n";
print $suppfile."\n";

open INPUT, $logfile or die "Can't open raw valgrind log file!";
open OUTPUT, ">$suppfile" or die "Can't open suppressions file!";

while (<INPUT>) {
  chomp;
  if ( !(/==\d+==/ or /--\d+--/) ) { print OUTPUT $_."\n"; }
}

With the trimmed suppressions file in hand, we can run valgrind and check for resource leaks using only our development model:

#!/bin/sh

NUMEVT=1
if [ $# -gt 0 ]; then
  NUMEVT=$1
fi

EXE=gevgen
A1=$(echo -e "-n $NUMEVT -p 14 -t 1000060120 -e 1,2")
A2=$(echo -e "--run 100 -f x*exp(-x) --seed 2989819")
A3=$(echo -e "--cross-sections $XSECSPLINEDIR/ccqe_carbon_splines.xml")
A4=$(echo -e "--event-generator-list CCQE")
DAT=`date -u +%s`
VALLOG="${DAT}_CCQE_grindlog.txt"

valgrind --log-file-exactly=${VALLOG} ${EXE} ${A1} ${A2} ${A3} ${A4}

cp $VALLOG leaksum.txt
perl -i -e 'while(<>) { chomp; if (/definitely/) {print $_,"\n";} }' lsmy.txt
cat lsmy.txt
echo

(The different argument pieces may all be combined into one line, they are only broken up here for presentation purposes. Only the line producing the function requires the -e flag on the echo.)

It is a good idea to periodically run the memory test and look for changes. Once a resource leak enters the code, it can be challenging to track down.