1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#!/usr/bin/env python
import sys
import optparse
import time
import detectors
import optics
import gpu
import g4gen
from io import root
import numpy as np
import math
import ROOT
def info(type, value, tb):
if hasattr(sys, 'ps1') or not sys.stderr.isatty():
# we are in interactive mode or we don't have a tty-like
# device, so we call the default hook
sys.__excepthook__(type, value, tb)
else:
import traceback, pdb
# we are NOT in interactive mode, print the exception...
traceback.print_exception(type, value, tb)
print
# ...then start the debugger in post-mortem mode.
pdb.pm()
sys.excepthook = info
if __name__ == '__main__':
parser = optparse.OptionParser('%prog')
parser.add_option('-b', type='int', dest='nbits', default=10)
parser.add_option('-j', type='int', dest='device', default=None)
parser.add_option('-n', type='int', dest='nblocks', default=64)
parser.add_option('--detector', type='string', dest='detector', default='microlbne')
parser.add_option('--nevents', type='int', dest='nevents', default=100)
parser.add_option('--particle', type='string', dest='particle', default='e-')
parser.add_option('--energy', type='float', dest='energy', default=100.0)
parser.add_option('--pos', type='string', dest='pos', default='(0,0,0)')
parser.add_option('--dir', type='string', dest='dir', default='(1,0,0)')
options, args = parser.parse_args()
if len(args) != 1:
print 'Must specify output filename!'
sys.exit(1)
else:
output_filename = args[0]
if options.nevents <= 0:
print '--nevents must be greater than 0!'
sys.exit(1)
position = np.array(eval(options.pos), dtype=float)
direction = np.array(eval(options.dir), dtype=float)
detector = detectors.find(options.detector)
print >>sys.stderr, 'Creating detector...'
detector.build(bits=options.nbits)
print >>sys.stderr, 'Initializing generator...'
detector_material = optics.water
generator = g4gen.G4Generator(detector_material)
print >>sys.stderr, 'WARNING: ASSUMING DETECTOR IS WATER!!'
print >>sys.stderr, 'Initializing GPU...'
gpu_worker = gpu.GPU(options.device)
print >>sys.stderr, 'Loading detector onto GPU...'
gpu_worker.load_geometry(detector)
print >>sys.stderr, 'Initializing random numbers generators...'
gpu_worker.setup_propagate()
gpu_worker.setup_daq(max(detector.pmtids))
print >>sys.stderr, 'Loading tables in GEANT4...'
# Do easy event to force tables to load, throw away photons
generator.generate_photons(particle_name='e-',
total_energy=1.5,
position=(0,0,0),
direction=(1,0,0))
# Create output file
f = ROOT.TFile(output_filename, 'RECREATE')
ev, T = root.make_tree('T')
print >>sys.stderr, 'Starting simulation...'
start_sim = time.time()
#### Do the generation and writing in this offset order to ensure
#### that propagation on the GPU overlaps with CPU work to create
#### and save photons.
#### WARNING: THIS MAKES THE CODE LOOK A LITTLE CRAZY. I AM SORRY
# Do first event
photons = generator.generate_photons(particle_name=options.particle,
total_energy=options.energy,
position=position,
direction=direction)
nphotons = len(photons['pos'])
gpu_worker.load_photons(**photons)
gpu_worker.propagate()
gpu_worker.run_daq()
for i in xrange(1, options.nevents-1):
# photons for next event while previous event propagates on GPU
photons = generator.generate_photons(particle_name=options.particle,
total_energy=options.energy,
position=position,
direction=direction)
nphotons += len(photons['pos'])
# this will stop and wait for event to finish
hit_times = gpu_worker.get_hits()
# turn around next event
gpu_worker.load_photons(**photons)
gpu_worker.propagate()
gpu_worker.run_daq()
# write out this event
root.fill_event(T, ev, i-1, position, len(hit_times), hit_times)
if i % 10 == 0:
print >>sys.stderr, "\rEvent:", i,
# Get results for last event and write it out
hit_times = gpu_worker.get_hits()
root.fill_event(T, ev, options.nevents - 1, position, len(hit_times), hit_times)
end_sim = time.time()
print >>sys.stderr, "\rEvent:", options.nevents - 1
T.Write()
f.Close()
print >>sys.stderr, 'Done. %1.1f events/sec, %1.0f photons/sec.' % (options.nevents/(end_sim - start_sim), nphotons/(end_sim - start_sim))
gpu_worker.shutdown()
|