This section assumes you have a cross section spline and have tested the steps outlined in [Running-GENIE-Basics].
The following breaks can be very useful for understanding the flow control, and are valid in the frozen release v2-8-0. Put these commands in a file named .gdbinit in the directory where you will run GENIE. If you cloned the supporting document repository from [How-To], you may copy gdbinit_ccqels into your .gdbinit file to get these breakpoints and functions.
Warning
|
You may also place .gdbinit in your \$HOME directory, but this sets values for all instances of gdb globally. |
# we can't set breakpoints for .so's we haven't loaded yet without this set breakpoint pending on # can often get away with typing: pv or pvis, etc. define pvisit p visitor->Id().Key()._M_dataplus._M_p end # print C++ standard strings define pcppstr p *(char**)($arg0)._M_dataplus._M_p end # # Breakpoints ---------- # # 1 break main # 2 break gEvGen.cxx:274 # 3 # watch the loop through event record visitors! # top of the loop. `p visitor->Id().Key()` (pvis above) # check the processor and see if you want to step in break EventGenerator.cxx:107 if ffwd==false commands 3 pvisit end # 4 actual call to ProcessEventRecord(event_rec) break EventGenerator.cxx:118 if ffwd==false # 5 once an event is accepted break QELKinematicsGenerator.cxx:193 commands 5 silent printf "xsec = %g ; E = %f ; Q^2 = %f\n", xsec, E, gQ2 end # 6 break QELKinematicsGenerator.cxx:116 # 7 break KineGeneratorWithCache.cxx:78 # 8 break KineGeneratorWithCache.cxx:83 # 9 break QELKinematicsGenerator.cxx:499 # 10 break LwlynSmithQELCCPXSec.cxx:82 # 11 break LwlynSmithQELCCPXSec.cxx:114 commands 11 printf "xsec = %g; ml = %f; Q2 = %f", xsec, ml, -1.0*q2 end # 12 - After algorithm loop break EventGenerator.cxx:195
Of course, these breakpoints are fragile if you are changing the source code because they rely on line numbers. You may also use function names to make a more generic ``starting'' .gdbinit file (they may not always work though, while line numbers are reliable).
It is important to understand some of GENIE’s design patterns [wikidesignpatterns], [wikigof] when stepping through framework code. GENIE makes heavy use of the Singleton Pattern, Visitor Pattern, and Chain of Responsibility Pattern [gof]. The Singleton Pattern restricts object creation for a given class to one and only one instance. The Visitor Pattern separates an algorithm from an object structure by moving the hierarchy of methods into one object. The Chain of Responsibility Pattern delegates commands to a chain of processing objects.
These patterns are how you see pointers on the stack accessing global data, and why sometimes loops over vectors of generic classes calling the same method over and over are able to process such a wide variety of behaviors with very compact code.
Don’t worry overly much about the patterns in the main framework. Stepping through
them with gdb
will make their operation clear in any case.
Feel free to explore more along the way and step into whatever you like. It is always okay to set a break point just after the function you step into so you leap out with a continue at any time.
First,
gdb -tui gevgen
Then, at the gdb
prompt,
set args -n 5 -p 14 -t 1000060120 -e 3 --run 100 \ --seed 2989819 \ --cross-sections /minerva/app/users/perdue/GENIE/data/ccqe_carbon_splines.xml \ --event-generator-list CCQE
It is convenient to simply copy and paste these lines. Note that we use ``\'' to break the line (the whole command needs to be on one line). You should use the correct path to your spline file. Then,
run
Or just r
. Try to solve all of the exercises below. Note that you may not have
the complete set of tools the first time through, or you may come to a conclusion
and then change your mind later after you learn more about GENIE and how to investigate
with gdb
. Now, for the walkthrough:
n |
1. We were automatically set to break on |
s |
2. Step into |
b 237 |
3. Set a breakpoint at the end of this function. We’ll test it shortly. |
inf b |
4. Note the number of the breakpoint you just set. |
Exercise |
5. What is the |
n |
6. Step down to |
s |
7. Step into |
Exercise |
8. Try to figure out what is going on in this function. Step into anything you
need to. Experiment with |
c |
9. ``Continue'' once you are satisfied in XSecTable. You should end up on line 237 of gEvGen.cxx back where we just set our breakpoint. |
del # |
10. Delete the breakpoint we set (we won’t need it any longer). |
inf b |
11. Verify the breakpoint is gone. |
n |
12. Step back into main. You only need to press |
n |
13. Step down to |
s |
14. Step into |
n |
15. Step down over these functions down to the break at line 274.
Try stepping a couple of times with |
Note |
16. From this point, it is understood you need to use |
s |
17. Step into |
b 276 |
18. We don’t want to accidently go past line 276. |
s |
19. Walk down through |
b 178 |
20. We have now stepped into |
b 214 |
21. Set a breakpoint on line 214. |
Exercise |
22. Walk through the code in this method and find out the names of the cross
section algorithms as they are loaded. You will need to use the |
Exercise |
23. When you get to line 178, print the size of the |
Exercise |
24. When you get to line 214, try the following commands (first, recall that
|
Note |
25. We just learned some nice tricks for inspecting objects on the heap! |
n |
26. Continue stepping through the program until you reach line 322 of GEVGDriver.cxx. |
s |
27. Step into |
n |
28. Walk down to our breakpoint on line 107. |
Exercise |
29. Hitting the breakpoint should trigger a print statement. What is the information it is telling us? |
c |
30. Continue to the breakpoint on line 118. Step into the function if you would like to see what is happening, otherwise, continue. |
Exercise |
31. Later, return to and study these algorithms we’re skipping now. What do they do? |
c |
32. Continute again to the breakpoint on line 107. What is the name of the algorithm being processed now. |
c |
33. Keep pressing |
s |
34. Step into the Kinematics generator. |
n |
35. Walk down to the breakpoint on line 116. |
Exercise |
36. What are the Q-squared limits for this event? |
s |
37. Step in at the breakpoint on line 116. |
Exercise |
38. We end up in |
c |
39. Continue to the breakpoint on line 78. |
Exercise |
40. Step into |
inf b |
41. What is the number of the breakpoint we just crossed? |
dis # |
42. Disable the breakpoint we just crossed by number. |
c |
43. Continue to the breakpoint on line 83. |
s |
44. Step into |
Exercise |
45. What is going on in this function? How are we computing the maximum cross section? |
s |
46. Step into the breakpoint on line 499. We are now in the |
s |
47. Step into the breakpoint on line 82. |
Exercise |
48. We are now in |
Note |
49. If you use |
n |
50. When you get back into |
disable |
51. When we get back into |
u |
52. Walk through the rest of the for loop, but when you reach line 496, use
|
enable |
53. Now turn all breakpoints back on. |
n |
54. Keep walking and note what happens next in |
n |
55. Once we get back to |
Exercise |
56. By what mechanism do we finally accept a cross section value? Note that while
walking through, we will end up stopping at our breakpoints inside |
c |
57. Once you are satisfied with mechanics of how we accept a cross section, continue to the breakpoint on line 193. |
n |
58. Walk through the rest of the function and note what is going on. What happens
between lines 230 and 234? |
c |
59. We are now in |
c |
60. Continue until we are alerted the next algorithm is |
s |
61. Inside |
Exercise |
62. Check out what is going on in |
n |
63. After the algorithm loop, continue to the breakpoint on line 195 and walk out
the method, or use |
n |
64. Back in |
Congratulations! |
65. We finished a walthrough of one event. |
disable |
66. Disable all breakpoints. |
c |
67. Continue to the end. There are no breakpoints, so this will end the program. |
r |
68. You may press |
Where did the long list of algorithms we stepped through come from? For CCQE, the classes that process the event can be found and specified in config/EventGenerator.xml:
<param_set name="QEL-CC"> <param type="string" name="VldContext"> </param> <param type="int" name="NModules"> 12 </param> <param type="alg" name="Module-0"> genie::InitialStateAppender/Default </param> <param type="alg" name="Module-1"> genie::VertexGenerator/Default </param> <param type="alg" name="Module-2"> genie::FermiMover/Default </param> <param type="alg" name="Module-3"> genie::QELKinematicsGenerator/CC-Default </param> <param type="alg" name="Module-4"> genie::QELPrimaryLeptonGenerator/Default </param> <param type="alg" name="Module-5"> genie::QELHadronicSystemGenerator/Default </param> <param type="alg" name="Module-6"> genie::PauliBlocker/Default </param> <param type="alg" name="Module-7"> genie::UnstableParticleDecayer/BeforeHadronTransport </param> <param type="alg" name="Module-8"> genie::NucDeExcitationSim/Default </param> <param type="alg" name="Module-9"> genie::HadronTransporter/Default </param> <param type="alg" name="Module-10"> genie::NucBindEnergyAggregator/Default </param> <param type="alg" name="Module-11"> genie::UnstableParticleDecayer/AfterHadronTransport </param> <param type="alg" name="ILstGen"> genie::QELInteractionListGenerator/CC-Default </param> </param_set>
One very important feature of this approach is that these classes can be swapped or re-ordered. Of course, re-ordering these specific classes might break the event, but nothing in GENIE forces us to handle the target first or the final-state lepton second, etc. We can sequence the appropriate set of computations as required by the physics and we can even make some changes dynamically (without recompiling).