1 gaskelld 1.1 subroutine limits_update(main,vertex,orig,recon,doing_deuterium,
2 > doing_pion,doing_kaon,doing_delta,doing_rho,contrib,slop)
3
4 include 'structures.inc'
5 include 'radc.inc'
6 record /event_main/ main
7 record /event/ vertex, orig, recon
8 record /contrib/ contrib
9 record /slop/ slop
10 integer i
11 logical doing_deuterium, doing_pion, doing_kaon, doing_delta, doing_rho
12
13 ! Update the "contribution limits" records
14
15 ! ... GENERATION values
16 call update_range(vertex.e.delta, contrib.gen.e.delta)
17 call update_range(vertex.e.yptar, contrib.gen.e.yptar)
18 call update_range(vertex.e.xptar, contrib.gen.e.xptar)
19 call update_range(vertex.p.delta, contrib.gen.p.delta)
20 call update_range(vertex.p.yptar, contrib.gen.p.yptar)
21 call update_range(vertex.p.xptar, contrib.gen.p.xptar)
22 gaskelld 1.1 call update_range(main.Trec, contrib.gen.Trec)
23
24 ! ........ another tricky shift
25 if (doing_deuterium .or. doing_pion .or. doing_kaon .or. doing_delta .or. doing_rho) then
26 call update_range(vertex.e.E-main.Ein_shift,contrib.gen.sumEgen)
27 else
28 call update_range(vertex.e.E+vertex.p.E-main.Ein_shift,contrib.gen.sumEgen)
29 endif
30
31 ! ... TRUE values
32 ! ........ tricky shift here, remember this'll get compared with edge.e.E,
33 ! ........ compensate for main.target.Coulomb to
34 ! ........ copy the shift made to the edge in generate
35 call update_range(orig.e.E-main.Ee_shift, contrib.tru.e.E)
36 call update_range(orig.e.xptar, contrib.tru.e.xptar)
37 call update_range(orig.e.yptar, contrib.tru.e.yptar)
38 call update_range(orig.e.xptar, contrib.tru.e.xptar)
39 call update_range(orig.p.E, contrib.tru.p.E)
40 call update_range(orig.p.yptar, contrib.tru.p.yptar)
41 call update_range(orig.p.xptar, contrib.tru.p.xptar)
42
43 gaskelld 1.1 ! ........ another tricky shift
44 call update_range(orig.Em-main.Ein_shift+main.Ee_shift,contrib.tru.Em)
45 call update_range(orig.Pm, contrib.tru.Pm)
46 call update_range(orig.Trec, contrib.tru.Trec)
47
48 ! ... SPECTROMETER values
49 call update_range(main.SP.e.delta, contrib.SP.e.delta)
50 call update_range(main.SP.e.yptar, contrib.SP.e.yptar)
51 call update_range(main.SP.e.xptar, contrib.SP.e.xptar)
52 call update_range(main.SP.p.delta, contrib.SP.p.delta)
53 call update_range(main.SP.p.yptar, contrib.SP.p.yptar)
54 call update_range(main.SP.p.xptar, contrib.SP.p.xptar)
55
56 ! ... VERTEX values
57 call update_range(vertex.Trec, contrib.vertex.Trec)
58 call update_range(vertex.Em, contrib.vertex.Em)
59 call update_range(vertex.Pm, contrib.vertex.Pm)
60
61 ! ... RADIATION stuff
62 ! ??? should be looking at Egamma2+3 cause we do use limits on that, indirectly
63
64 gaskelld 1.1 do i = 1, 3
65 call update_range(Egamma_used(i), contrib.rad.Egamma(i))
66 enddo
67 call update_range(Egamma_used(1)+Egamma_used(2)+Egamma_used(3),
68 > contrib.rad.Egamma_total)
69
70 ! Update the "slop limits" records
71 ! ... MC slops
72 call update_range(main.RECON.e.delta-main.SP.e.delta,slop.MC.e.delta)
73 call update_range(main.RECON.e.yptar-main.SP.e.yptar,slop.MC.e.yptar)
74 call update_range(main.RECON.e.xptar-main.SP.e.xptar,slop.MC.e.xptar)
75 call update_range(main.RECON.p.delta-main.SP.p.delta,slop.MC.p.delta)
76 call update_range(main.RECON.p.yptar-main.SP.p.yptar,slop.MC.p.yptar)
77 call update_range(main.RECON.p.xptar-main.SP.p.xptar,slop.MC.p.xptar)
78
79 ! ... total slops
80 ! ........ that tricky shift again, slops accounted for by the shift not
81 ! ........ included in slop.total.Em.
82 call update_range(recon.Em-(orig.Em-main.Ein_shift+main.Ee_shift),
83 > slop.total.Em)
84 call update_range(abs(recon.Pm)-abs(orig.Pm), slop.total.Pm)
85 gaskelld 1.1
86 return
87 end
88
89 !-------------------------------------------------------------------
90
91 subroutine update_range(val,range)
92
93 include 'structures.inc'
94 record /range/ range
95 real*8 val
96
97 range.lo = min(range.lo, val)
98 range.hi = max(range.hi, val)
99
100 return
101 end
102
103 !----------------------------------------------------------------------
104 ! THE routine to GENERATE the (max of 7) random quantities we need to get
105 ! a full description of our event.
106 gaskelld 1.1
107 subroutine generate(main,vertex,orig,success)
108
109 implicit none
110 include 'simulate.inc'
111
112 integer i, ii
113 real*8 Emin, Emax
114 real*8 ranprob,ranth1,ranth,ranph,t3,t4,t5,t6
115 real*8 pferlo,pferhi
116 real*8 m_spec !spectator (A-1) mass based on missing energy
117 real*8 gauss1
118 logical success
119 real*8 grnd !random # generator.
120 record /event_main/ main
121 record /event/ vertex, orig
122
123 real*8 nsig_max
124 parameter(nsig_max=3.0d0) !max #/sigma for gaussian ran #s.
125
126
127 gaskelld 1.1 ! Randomize the position of the interaction inside the available region.
128 ! gen.xwid and gen.ywid are the intrinsic beam widths (one sigma value).
129 ! Use a gaussian beam distribution with +/- 3.0 sigma (add raster afterwards).
130 if (debug(2)) write(6,*)'gen: entering'
131 main.target.x = gauss1(nsig_max)*gen.xwid+targ.xoffset
132 main.target.y = gauss1(nsig_max)*gen.ywid+targ.yoffset
133
134 ! fr_pattern=1 - rectangle - targ.fr1/fr2 are the x/y raster half-widths.
135 ! fr_pattern=2 - circle - targ.fr1/fr2 are the inner and outer radii.
136
137 if (targ.fr_pattern .eq. 1) then !square raster
138 t3=grnd()*pi
139 t4=grnd()*pi
140 t5=cos(t3)*targ.fr1
141 t6=cos(t4)*targ.fr2
142 elseif (targ.fr_pattern .eq. 2) then !circular raster
143 t3=grnd()*2.*pi
144 t4=sqrt(grnd())*(targ.fr2-targ.fr1)+targ.fr1
145 t5=cos(t3)*t4
146 t6=sin(t3)*t4
147 else !no raster
148 gaskelld 1.1 t5=0.0
149 t6=0.0
150 endif
151
152 main.target.x = main.target.x+t5
153 main.target.y = main.target.y+t6
154 main.target.z = (0.5-grnd())*targ.length+targ.zoffset
155 main.target.rastery = t6 !'raster' contribution to vert. pos.
156
157 ! Take fluctuations of the beam energy into account, and remember to correct
158 ! for ionization loss in the target and Coulomb acceleration of incoming
159 ! electron. Remove targ.zoffset from the z position of the scattering
160 ! in order to get the position relative to the center of the target.
161
162 call trip_thru_target (1, main.target.z-targ.zoffset, Ebeam, 0.0d0,
163 > main.target.Eloss(1), main.target.teff(1),Me,1)
164 if (.not.using_Eloss) main.target.Eloss(1) = 0.0
165 if (using_Coulomb) then
166 main.target.Coulomb=targ.Coulomb_constant*(3.-(grnd())**(2./3.))
167 else
168 main.target.Coulomb=0.0
169 gaskelld 1.1 endif
170 vertex.Ein = Ebeam + (grnd()-0.5)*dEbeam +
171 > main.target.Coulomb - main.target.Eloss(1)
172
173 ! ... deterimine known variation in Ein from Ebeam_vertex_ave and in
174 ! ... Ee due to Coulomb energy to compare limits to generated event by event.
175 ! ... (USED TO SHIFT 'LIMIT' VALUES IN UPDATE_RANGE CALLS. ARE THEY NEEDED???)
176
177 main.Ein_shift = vertex.Ein - Ebeam_vertex_ave
178 main.Ee_shift = main.target.Coulomb - targ.Coulomb.ave
179
180 ! Initialize success code and fractional weight due to radiation and
181 ! generation tricks
182
183 5 success = .false.
184 main.gen_weight = 1.0
185
186 ! Generated quantities: (phase_space NOT YET IMPLEMENTED).
187 !
188 ! phase_space: Generate electron E,yptar,xptar and hadron yptar,xptar??
189 ! doing_hyd_elast: Generate electron angles. Solve for everything else.
190 gaskelld 1.1 ! doing_deuterium: Generate electron energy and angles, proton angles.
191 ! Solve for proton momentum, p_fermi.
192 ! doing_eep, A>2: generate electron and hadron energy, angles. Solve for Em,Pm.
193 ! doing_pion: generate electron energy and angles, hadron angles, p_fermi, Em.
194 ! Solve for hadron momentum.
195 ! doing_kaon: as doing_pion.
196 ! doing_delta: as doing_pion.
197 ! doing_rho: as doing_pion.
198 ! doing_semi: Generate electron E,yptar,xptar and hadron E, yptar,xptar
199 !
200 ! The above is summarized in the following table:
201 !
202 ! ELECTRON HADRON
203 ! ------------------ ------------------
204 ! E yptar xptar E yptar xptar p_fermi Em
205 !
206 !H(e,e'p) X X
207 !D(e,e'p) X X X X X
208 !A(e,e'p) X X X X X X
209 !----------------------------------------------------------------------
210 !H(e,e'pi) X X X X X
211 gaskelld 1.1 !A(e,e'pi) X X X X X X X
212 !H(e,e'K) X X X X X
213 !A(e,e'K) X X X X X X X
214 !H(e,e'p)pi X X X X X
215 !A(e,e'p)pi X X X X X X X
216 !----------------------------------------------------------------------
217 !phase_space X X X ? X X
218 !
219 ! So our procedure is the following:
220 ! 1) Always generate electron yptar and xptar
221 ! 2) generate hadron yptar and xptar for all cases except H(e,e'p).
222 ! 3) Generate hadron E for A(e,e'p)
223 ! 4) generate electron E for all but hydrogen elastic.
224 ! 5) generate p_fermi, Em for A(e,e'pi) and A(e,e'K).
225 !
226 ! After we generate xptar/yptar/energy, we calculate physics angles (theta/phi),
227 ! momenta, unit vectors, etc... here and/or in complete_ev.
228 !
229 ! Note that there are also jacobians associated with some and/or all of
230 ! the above.
231 ! 1: We generate uniformly in xptar/yptar, not theta/phi. We define the
232 gaskelld 1.1 ! phase space volume (genvol contribution) as the product of the xptar/yptar
233 ! range, and have a jacobian for each event taking into account the mapping
234 ! between the solid angle on the unit sphere, and the dxptar/dyptar volume
235 ! (the jacobian is 1/cos**3(dtheta), where dtheta is the angle between the
236 ! event and the central spectrometer vector
237 ! 2: For the D(e,e'p), we take Em as fixed in order to calculate the proton
238 ! energy. There is a jacobian ( |dEp'/dEm| ). It comes from integrating
239 ! over the energy conservation delta function: delta(E_D - E_p - E_n - Em).
240
241 ! Generate Electron Angles (all cases):
242 vertex.e.yptar=gen.e.yptar.min+grnd()*(gen.e.yptar.max-gen.e.yptar.min)
243 vertex.e.xptar=gen.e.xptar.min+grnd()*(gen.e.xptar.max-gen.e.xptar.min)
244
245 ! Generate Hadron Angles (all but H(e,e'p)):
246 if (doing_deuterium.or.doing_heavy.or.doing_pion.or.doing_kaon
247 1 .or.doing_delta.or.doing_semi.or.doing_rho) then
248 vertex.p.yptar=gen.p.yptar.min+grnd()*
249 1 (gen.p.yptar.max-gen.p.yptar.min)
250 vertex.p.xptar=gen.p.xptar.min+grnd()*
251 1 (gen.p.xptar.max-gen.p.xptar.min)
252 endif
253 gaskelld 1.1
254 ! Generate Hadron Momentum (A(e,e'p) or semi-inclusive production).
255 if (doing_heavy .or. doing_semi) then
256 Emin = max(gen.p.E.min, gen.sumEgen.min - gen.e.E.max)
257 Emax = min(gen.p.E.max, gen.sumEgen.max - gen.e.E.min)
258 if (Emin.gt.Emax) goto 100
259 main.gen_weight=main.gen_weight*(Emax-Emin)/(gen.p.E.max-gen.p.E.min)
260 vertex.p.E = Emin + grnd()*(Emax-Emin)
261 vertex.p.P = sqrt(vertex.p.E**2 - Mh2)
262 vertex.p.delta = 100.*(vertex.p.P-spec.p.P)/spec.p.P
263 endif
264
265 ! Generate Electron Energy (all but hydrogen elastic)
266 if (doing_deuterium.or.doing_heavy.or.doing_pion.or.doing_kaon
267 1 .or.doing_delta.or.doing_rho.or.doing_semi) then
268 Emin=gen.e.E.min
269 Emax=gen.e.E.max
270 if (doing_deuterium .or. doing_pion .or. doing_kaon .or. doing_delta .or. doing_rho) then
271 Emin = max(Emin,gen.sumEgen.min)
272 Emax = min(Emax,gen.sumEgen.max)
273 else if (doing_heavy) then ! A(e,e'p)
274 gaskelld 1.1 Emin = max(Emin, gen.sumEgen.min - vertex.p.E)
275 Emax = min(Emax, gen.sumEgen.max - vertex.p.E)
276 endif
277 if (Emin.gt.Emax) goto 100
278 main.gen_weight=main.gen_weight*(Emax-Emin)/(gen.e.E.max-gen.e.E.min)
279 vertex.e.E = Emin + grnd()*(Emax-Emin)
280 vertex.e.P = vertex.e.E
281 vertex.e.delta = 100.*(vertex.e.P-spec.e.P)/spec.e.P
282 endif !not (doing_hyd_elast)
283
284
285 ! Calculate the electron and proton PHYSICS angles from the spectrometer angles.
286 ! Note that the proton angles are not yet know for hydrogen elastic.
287
288 call physics_angles(spec.e.theta,spec.e.phi,
289 & vertex.e.xptar,vertex.e.yptar,vertex.e.theta,vertex.e.phi)
290 call physics_angles(spec.p.theta,spec.p.phi,
291 & vertex.p.xptar,vertex.p.yptar,vertex.p.theta,vertex.p.phi)
292
293 ! Generate Fermi Momentum and Em for A(e,e'pi) and A(e,e'K).
294 pfer=0.0
295 gaskelld 1.1 pferx=0.0
296 pfery=0.0
297 pferz=0.0
298 vertex.Em=0.0
299 efer=targ.Mtar_struck !used for pion/kaon xsec calcs.
300 if(doing_deutpi.or.doing_hepi.or.doing_deutkaon.or.doing_hekaon.or.
301 1 doing_deutdelta.or.doing_hedelta.or.doing_deutrho.or.doing_herho
302 2 .or.doing_deutsemi)then
303 ranprob=grnd()
304 ii=1
305 do while (ranprob.gt.mprob(ii) .and. ii.lt.nump)
306 ii=ii+1
307 enddo
308 if (ii.eq.1) then
309 pferlo=0
310 else
311 pferlo=(pval(ii-1)+pval(ii))/2
312 endif
313 if (ii.eq.nump) then
314 pferhi=pval(nump)
315 else
316 gaskelld 1.1 pferhi=(pval(ii)+pval(ii+1))/2
317 endif
318 pfer=pferlo+(pferhi-pferlo)*grnd()
319 ranth1=grnd()*2.-1.0
320 ranth=acos(ranth1)
321 ranph=grnd()*2.*pi
322 pferx=sin(ranth)*cos(ranph)
323 pfery=sin(ranth)*sin(ranph)
324 pferz=cos(ranth)
325
326 if (doing_deutpi.or.doing_deutkaon.or.doing_deutdelta
327 1 .or.doing_deutrho .or.doing_deutsemi) then !Em = binding energy
328 vertex.Em = Mp + Mn - targ.M
329 m_spec = targ.M - targ.Mtar_struck + vertex.Em != Mn(Mp) for pi+(-)
330 efer = targ.M - sqrt(m_spec**2+pfer**2)
331 endif
332 if (doing_hepi .or. doing_hekaon .or. doing_hedelta .or. doing_herho) then
333 call generate_em(pfer,vertex.Em) !Generate Em
334 m_spec = targ.M - targ.Mtar_struck + vertex.Em != M^*_{A-1}
335 efer = targ.M - sqrt(m_spec**2+pfer**2)
336 endif
337 gaskelld 1.1 endif
338
339 ! Compute all non-generated quantities
340
341 if (debug(5)) write(6,*)'gen: calling comp_ev with false, main, vertex'
342 if (debug(3)) write(6,*)'gen: calling comp_ev with false, main, vertex'
343 if (debug(3)) write(6,*)'gen: Ein, E =',vertex.Ein,vertex.e.E
344 call complete_ev(main,vertex,success)
345
346 main.sigcc = 1.0
347
348 if (debug(2)) write(6,*)'gen: initial success =',success
349 if (.not.success) goto 100
350
351 ! ........ temporary storage of Trec for generated event
352
353 main.Trec = vertex.Trec
354
355 ! Radiate the event, if requested. If we get an event weight of zero (i.e.
356 ! if we CAN'T radiate our event into the acceptance) then success is
357 ! false. generate_rad also set orig kinematics, and cuts on Em/Pm.
358 gaskelld 1.1 ! If not using_rad, must do these here.
359
360 if (using_rad) then
361 call generate_rad(main,vertex,orig,success)
362 if (debug(2)) write(6,*)'gen: after gen_rad, success =',success
363 else
364 success = .true.
365 if (doing_heavy) success =
366 > (vertex.Em .ge. VERTEXedge.Em.min .and.
367 > vertex.Em .le. VERTEXedge.Em.max .and.
368 > vertex.Pm .ge. VERTEXedge.Pm.min .and.
369 > vertex.Pm .le. VERTEXedge.Pm.max)
370 if (success) then
371 do i = 1, neventfields
372 orig.all(i) = vertex.all(i)
373 enddo
374 endif
375 endif
376
377
378 C DJG need to decay the rho here before we begin transporting through the
379 gaskelld 1.1 C DJG spectrometer
380 if(doing_rho) then
381 call rho_decay(orig.p.xptar,orig.p.yptar,orig.p.delta,spec.p.P,Mh2,
382 1 main.epsilon,orig.Q2)
383 endif
384
385 100 if (debug(2)) write(6,*)'gen: final success =',success
386 if (debug(2)) write(6,*)'gen: ending'
387 return
388 end
389
390 !---------------------------------------------------------------------
391
392 subroutine complete_ev(main,vertex,success)
393
394 implicit none
395 include 'simulate.inc'
396
397 real*8 a, b, c, r, t, QA, QB, QC, radical
398 real*8 p_new_x,p_new_y,new_x_x,new_x_y,new_x_z
399 real*8 new_y_x,new_y_y,new_y_z,dummy
400 gaskelld 1.1 real*8 px,py,pz,qx,qy,qz
401 real*8 oop_x,oop_y
402 real*8 krel,krelx,krely,krelz
403 real*8 MM
404
405 real*8 Ehad2,E_rec
406 real*8 W2
407 real*8 grnd !random # generator.
408
409 logical success
410 record /event_main/ main
411 record /event/ vertex
412
413 !-----------------------------------------------------------------------
414 ! Calculate everything left in the /event/ structure, given all necessary
415 ! GENERATION values (some set of xptar,yptar,delta for both arms and p_fermi,
416 ! and p_fermi, depending on the scattering process: see table in generate.f
417 !
418 ! The SINGLE element of /event/ NOT computed here is sigcc.
419 !
420 ! Another small anomaly is that main.jacobian IS computed here.
421 gaskelld 1.1 ! This is because all the necessary terms have to be
422 ! computed here anyway to calculate /event/ qties.
423 !
424 !-----------------------------------------------------------------------
425
426 ! Initialize
427
428 success = .false.
429 main.jacobian = 1.0
430
431 ! ... unit vector components of outgoing e,p
432 ! ... z is DOWNSTREAM, x is DOWN and y is LEFT looking downstream.
433
434 if (debug(4)) write(6,*)'comp_ev: at 1'
435 vertex.ue.x = sin(vertex.e.theta)*cos(vertex.e.phi)
436 vertex.ue.y = sin(vertex.e.theta)*sin(vertex.e.phi)
437 vertex.ue.z = cos(vertex.e.theta)
438 if (.not.doing_hyd_elast) then
439 vertex.up.x = sin(vertex.p.theta)*cos(vertex.p.phi)
440 vertex.up.y = sin(vertex.p.theta)*sin(vertex.p.phi)
441 vertex.up.z = cos(vertex.p.theta)
442 gaskelld 1.1 endif
443 if (debug(4)) write(6,*)'comp_ev: at 2'
444
445 ! First finish off the e side
446 ! Calculate scattered electron energy for hydrogen/deuterium (e,e'p)
447
448 if (doing_hyd_elast) then
449 vertex.e.E = vertex.Ein*Mh/(Mh+vertex.Ein*(1.-vertex.ue.z))
450
451 if (vertex.e.E.gt.vertex.Ein) return
452 vertex.e.P = vertex.e.E
453 vertex.e.delta = (vertex.e.P - spec.e.P)*100./spec.e.P
454 if (debug(4)) write(6,*)'comp_ev: at 3'
455 endif
456
457 ! The q vector
458
459 if (debug(5)) write(6,*)'comp_ev: Ein,E,uez=',vertex.Ein,vertex.e.E,vertex.ue.z
460
461 vertex.nu = vertex.Ein - vertex.e.E
462 vertex.Q2 = 2*vertex.Ein*vertex.e.E*(1.-vertex.ue.z)
463 gaskelld 1.1 vertex.q = sqrt(vertex.Q2 + vertex.nu**2)
464 vertex.xbj = vertex.Q2/2./Mp/vertex.nu
465
466
467 vertex.uq.x = - vertex.e.P*vertex.ue.x / vertex.q
468 vertex.uq.y = - vertex.e.P*vertex.ue.y / vertex.q
469 vertex.uq.z =(vertex.Ein - vertex.e.P*vertex.ue.z)/ vertex.q
470 if (abs(vertex.uq.x**2+vertex.uq.y**2+vertex.uq.z**2-1).gt.0.01)
471 > stop 'Error in q vector normalization'
472 if (debug(4)) write(6,*)'comp_ev: at 5'
473
474
475 ! Now complete the p side, along with vertex.Em, vertex.Pm, vertex.Mrec.
476 ! NOTE: Coherent pion/kaon production (bound final state) is treated as
477 ! hydrogen, but with targ.Mtar_struck=targ.M, targ.Mtar_rec=bound final state.
478
479 if (doing_hyd_elast) then !p = q
480 vertex.Em = 0.0
481 vertex.Pm = 0.0
482 vertex.Mrec = 0.0
483 vertex.up.x = vertex.uq.x
484 gaskelld 1.1 vertex.up.y = vertex.uq.y
485 vertex.up.z = vertex.uq.z
486 vertex.p.P = vertex.q
487 vertex.p.theta = acos(vertex.up.z)
488 if (abs(vertex.up.x/sin(vertex.p.theta)).gt.1)
489 > write(6,*) 'cos(phi)=',vertex.up.x/sin(vertex.p.theta)
490 vertex.p.phi = atan2(vertex.up.y,vertex.up.x)
491 if (vertex.p.phi.lt.0.) vertex.p.phi=vertex.p.phi+2.*pi
492 call spectrometer_angles(spec.p.theta,spec.p.phi,
493 & vertex.p.xptar,vertex.p.yptar,vertex.p.theta,vertex.p.phi)
494 vertex.p.E = sqrt(vertex.p.P**2+Mh2)
495 vertex.p.delta = (vertex.p.P - spec.p.P)*100./spec.p.P
496 if (debug(4)) write(6,*)'comp_ev: at 6'
497
498 elseif (doing_deuterium) then !need Ep, and a jacobian.
499
500 vertex.Em = targ.Mtar_struck + targ.Mrec - targ.M !=2.2249 MeV
501 vertex.Mrec = targ.M - targ.Mtar_struck + vertex.Em !=targ.Mrec
502
503 a = -1.*vertex.q*(vertex.uq.x*vertex.up.x+vertex.uq.y*vertex.up.y+vertex.uq.z*vertex.up.z)
504 b = vertex.q**2
505 gaskelld 1.1 c = vertex.nu + targ.M
506 t = c**2 - b + Mh2 - vertex.Mrec**2
507 QA = 4.*(a**2 - c**2)
508 QB = 4.*c*t
509 QC = -4.*a**2*Mh2 - t**2
510 radical = QB**2 - 4.*QA*QC
511 if (radical.lt.0) return
512 vertex.p.E = (-QB - sqrt(radical))/2./QA
513
514 ! Check for two solutions
515 ! if ( (-QB + sqrt(radical))/2./QA .gt. Mh ) then
516 ! write(6,*) 'There are two valid solutions for the hadron momentum'
517 ! write(6,*) 'We always pick one, so this may be a problem, and needs to be checked'
518 ! write(6,*) 'solns=',(-QB - sqrt(radical))/2./QA,(-QB + sqrt(radical))/2./QA
519 ! endif
520
521 ! Check for two solutions, but only print warning if both are within
522 ! event generation limits.
523 Ehad2 = (-QB + sqrt(radical))/2./QA
524 if (Ehad2.gt.edge.p.E.min .and. Ehad2.lt.edge.p.E.max .and. ntried.le.5000) then
525 write(6,*) 'The low-momentum solution to E_hadron is within the spectrometer generation'
526 gaskelld 1.1 write(6,*) 'limits. If it is in the acceptance, Its the end of the world as we know it!!!'
527 write(6,*) 'E_hadron solns=',vertex.p.E,Ehad2
528 endif
529
530
531 if (vertex.p.E.le.Mh) return
532 vertex.p.P = sqrt(vertex.p.E**2 - Mh2)
533 vertex.p.delta = (vertex.p.P - spec.p.P)*100./spec.p.P
534
535 ! ........ the Jacobian here is |dEp'/dEm|
536 main.jacobian = (t*(c-vertex.p.E) + 2*c*vertex.p.E*(vertex.p.E-c)) /
537 1 (2*(a**2-c**2)*vertex.p.E + c*t)
538 main.jacobian = abs(main.jacobian)
539
540
541 elseif (doing_pion .or. doing_kaon .or. doing_delta .or. doing_rho) then
542
543 if (doing_rho) then
544 Mh = Mrho
545 ! DJG give the rho mass some width (non-relativistic Breit-Wigner)
546 Mh = Mh + 0.5*150.2*tan((2.*grnd()-1.)*atan(2.*500./150.2))
547 gaskelld 1.1 Mh2 = Mh*Mh
548 ntup.rhomass=Mh
549 c write(6,*) 'rho mass is', Mh
550 endif
551
552
553
554 vertex.Pm = pfer !vertex.Em generated at beginning.
555 vertex.Mrec = targ.M - targ.Mtar_struck + vertex.Em
556 a = -1.*vertex.q*(vertex.uq.x*vertex.up.x+vertex.uq.y*vertex.up.y+vertex.uq.z*vertex.up.z)
557 b = vertex.q**2
558 c = vertex.nu + targ.M
559
560 ! For nuclei, correct for fermi motion and missing energy. Also, check
561 ! second solution to quadratic equation - there are often two valid
562 ! solutions, and we always pick the larger one (which is the forward going
563 ! one in the center of mass) and HOPE that the smaller one is never in the
564 ! acceptance. If the low momentum solution IS within the acceptance, we
565 ! have big problems.
566 if (doing_deutpi.or.doing_hepi.or.doing_deutkaon.or.doing_hekaon.or.
567 1 doing_deutdelta.or.doing_hedelta.or.doing_deutrho.or.doing_herho) then
568 gaskelld 1.1 a = a - abs(pfer)*(pferx*vertex.up.x+pfery*vertex.up.y+pferz*vertex.up.z)
569 b = b + pfer**2 + 2*vertex.q*abs(pfer)*
570 1 (pferx*vertex.uq.x+pfery*vertex.uq.y+pferz*vertex.uq.z)
571 *** c = c - sqrt(vertex.Mrec**2+pfer**2)
572 c = vertex.nu + efer !same as above, but this way if we redefine
573 !'efer', it's the same everywhere.
574 endif
575 t = c**2 - b + Mh2 - targ.Mrec_struck**2
576 QA = 4.*(a**2 - c**2)
577 QB = 4.*c*t
578 QC = -4.*a**2*Mh2 - t**2
579
580 ! write(6,*) ' '
581 ! write(6,*) ' '
582 ! write(6,*) 'E0=',vertex.Ein
583 ! write(6,*) 'P_elec,P_prot=',vertex.e.P/1000.,vertex.p.P/1000.
584 ! write(6,*) 'thetae,phie=',vertex.e.theta*180./pi,vertex.e.phi*180./pi
585 ! write(6,*) 'thetap,phip=',vertex.p.theta*180./pi,vertex.p.phi*180./pi
586 ! write(6,*) 'q,nu,costhetapq=',vertex.q,vertex.nu,(vertex.uq.x*vertex.up.x+vertex.uq.y*vertex.up.y+vertex.uq.z*vertex.up.z)
587 ! write(6,*) 'a,b,c=',a/1000.,b/1000000.,c/1000.
588 ! write(6,*) 't=',t/1000000.
589 gaskelld 1.1 ! write(6,*) 'A,B,C=',QA/1.d6,QB/1.d9,QC/1.d12
590 ! write(6,*) 'rad=',QB**2 - 4.*QA*QC
591 ! write(6,*) 'e1,e2=',(-QB-sqrt(radical))/2000./QA,(-QB+sqrt(radical))/2000./QA
592 ! write(6,*) 'E_pi1,2=',vertex.nu+targ.M-(-QB-sqrt(radical))/2./QA,
593 ! > vertex.nu+targ.M-(-QB+sqrt(radical))/2./QA
594
595
596 radical = QB**2 - 4.*QA*QC
597 if (radical.lt.0) return
598 vertex.p.E = (-QB - sqrt(radical))/2./QA
599 Ehad2 = (-QB + sqrt(radical))/2./QA
600
601 if (doing_delta.or.doing_rho) then !choose one of the two solutions.
602 ! write(6,*) ' e1, e2=',vertex.p.E,Ehad2
603 if (grnd().gt.0.5) vertex.p.E = Ehad2
604 else !verify that 'backwards' soln. is no good.
605 if (Ehad2.gt.edge.p.E.min .and. Ehad2.lt.edge.p.E.max .and. ntried.le.5000) then
606 write(6,*) 'The low-momentum solution to E_hadron is within the spectrometer generation'
607 write(6,*) 'limits. If it is in the acceptance, Its the end of the world as we know it!!!'
608 write(6,*) 'E_hadron solns=',vertex.p.E,Ehad2
609 endif
610 gaskelld 1.1 endif
611
612 E_rec=c-vertex.p.E !energy of recoil system
613 if (E_rec.le.targ.Mrec_struck) return !non-physical solution
614
615 if (vertex.p.E.le.Mh) return
616 vertex.p.P = sqrt(vertex.p.E**2 - Mh2)
617 vertex.p.delta = (vertex.p.P - spec.p.P)*100./spec.p.P
618 ! write(6,*) 'p,e=',vertex.p.P,vertex.p.E
619
620 elseif (doing_phsp) then
621
622 vertex.p.P = spec.p.P !????? single arm phsp??
623 vertex.p.E= sqrt(Mh2+vertex.p.P**2)
624 vertex.p.delta = (vertex.p.P - spec.p.P)*100./spec.p.P
625 if (debug(4)) write(6,*)'comp_ev: at 7.5',Mh2,vertex.p.E
626
627 endif
628
629 if (debug(4)) write(6,*)'comp_ev: at 7'
630
631 gaskelld 1.1 ! Compute some pion and kaon stuff. Some of these should be OK for proton too.
632
633 if (doing_pion .or. doing_kaon .or. doing_delta .or. doing_rho .or. doing_semi) then
634 W2 = targ.M**2 + 2.*targ.M*vertex.nu - vertex.Q2
635 main.W = sqrt(abs(W2)) * W2/abs(W2)
636 main.epsilon=1./(1. + 2.*(1+vertex.nu**2/vertex.Q2)*tan(vertex.e.theta/2.)**2)
637 main.theta_pq=acos(vertex.up.x*vertex.uq.x+vertex.up.y*vertex.uq.y+vertex.up.z*vertex.uq.z)
638 main.t = vertex.Q2 - Mh2 + 2*vertex.nu*vertex.p.E -
639 > 2*vertex.p.P*vertex.q*cos(main.theta_pq)
640 main.tmin = vertex.Q2 - Mh2 + 2*vertex.p.E*vertex.nu -
641 > 2*vertex.p.P*vertex.q
642 main.q2 = vertex.Q2
643
644 ! CALCULATE ANGLE PHI BETWEEN SCATTERING PLANE AND REACTION PLANE.
645 ! Therefore, define a new system with the z axis parallel to q, and
646 ! the x axis inside the q-z-plane: z' = q, y' = q X z, x' = y' X q
647 ! this gives phi the way it is usually defined, i.e. phi=0 for in-plane
648 ! particles closer to the downstream beamline than q.
649 ! phi=90 is above the horizontal plane when q points to the right, and
650 ! below the horizontal plane when q points to the left.
651 ! Also take into account the different definitions of x, y and z in
652 gaskelld 1.1 ! replay and SIMC:
653 ! As seen looking downstream: replay SIMC (old_simc)
654 ! x right down (left)
655 ! y down left (up)
656 ! z all have z pointing downstream
657 !
658 ! SO: x_replay=-y_simc, y_replay=x_simc, z_replay= z_simc
659
660 qx = -vertex.uq.y !convert to 'replay' coord. system
661 qy = vertex.uq.x
662 qz = vertex.uq.z
663 px = -vertex.up.y
664 py = vertex.up.x
665 pz = vertex.up.z
666
667 dummy=sqrt((qx**2+qy**2)*(qx**2+qy**2+qz**2))
668 new_x_x = -qx*qz/dummy
669 new_x_y = -qy*qz/dummy
670 new_x_z = (qx**2 + qy**2)/dummy
671
672 dummy = sqrt(qx**2 + qy**2)
673 gaskelld 1.1 new_y_x = qy/dummy
674 new_y_y = -qx/dummy
675 new_y_z = 0.0
676
677 p_new_x = px*new_x_x + py*new_x_y + pz*new_x_z
678 p_new_y = px*new_y_x + py*new_y_y + pz*new_y_z
679
680 main.phi_pq = atan2(p_new_y,p_new_x) !atan2(y,x)=atan(y/x)
681 if (main.phi_pq.lt.0.d0) main.phi_pq=main.phi_pq+2.*pi
682 ! if (p_new_y.lt.0.) then
683 ! main.phi_pq = 2*pi - main.phi_pq
684 ! endif
685
686 ! if ((p_new_x**2+p_new_y**2).eq.0.) then
687 ! main.phi_pq = 0.0
688 ! else
689 ! main.phi_pq = acos(p_new_x/sqrt(p_new_x**2+p_new_y**2))
690 ! endif
691 ! if (p_new_y.lt.0.) then
692 ! main.phi_pq = 2*pi - main.phi_pq
693 ! endif
694 gaskelld 1.1
695 if (debug(2)) then
696 write(6,*)'comp_ev: nu =',vertex.nu
697 write(6,*)'comp_ev: Q2 =',vertex.Q2
698 write(6,*)'comp_ev: theta_e =',vertex.e.theta
699 write(6,*)'comp_ev: epsilon =',main.epsilon
700 write(6,*)'comp_ev: theta_pq =',main.theta_pq
701 write(6,*)'comp_ev: phi_pq =',main.phi_pq
702 write(6,*)'comp_ev: E_hadron =',vertex.p.E
703 endif
704 endif !end of pion/kaon specific stuff.
705
706 if (debug(4)) write(6,*)'comp_ev: at 8'
707
708 ! Compute the Pm vector in in SIMC LAB system, with x down, and y to the left.
709 ! Computer Parallel, Perpendicular, and Out of Plane componenants.
710 ! Parallel is component along q_hat. Out/plane is component along
711 ! (e_hat) x (q_hat) (oop_x,oop_y are components of out/plane unit vector)
712 ! Perp. component is what's left: along (q_hat) x (oop_hat).
713 ! So looking along q, out of plane is down, perp. is left.
714
715 gaskelld 1.1 vertex.Pmx = vertex.p.P*vertex.up.x - vertex.q*vertex.uq.x
716 vertex.Pmy = vertex.p.P*vertex.up.y - vertex.q*vertex.uq.y
717 vertex.Pmz = vertex.p.P*vertex.up.z - vertex.q*vertex.uq.z
718 vertex.Pmiss = sqrt(vertex.Pmx**2+vertex.Pmy**2+vertex.Pmz**2)
719 vertex.Emiss = vertex.nu + targ.M - vertex.p.E
720
721 !STILL NEED SIGN FOR PmPer!!!!!!
722
723 oop_x = -vertex.uq.y ! oop_x = q_y *(z_hat x y_hat) = q_y *-(x_hat)
724 oop_y = vertex.uq.x ! oop_y = q_x *(z_hat x x_hat) = q_x * (y_hat)
725 vertex.PmPar = (vertex.Pmx*vertex.uq.x + vertex.Pmy*vertex.uq.y + vertex.Pmz*vertex.uq.z)
726 vertex.PmOop = (vertex.Pmx*oop_x + vertex.Pmy*oop_y) / sqrt(oop_x**2+oop_y**2)
727 vertex.PmPer = sqrt( max(0.d0, vertex.Pm**2 - vertex.PmPar**2 - vertex.PmOop**2 ) )
728
729 if (debug(4)) write(6,*)'comp_ev: at 9',vertex.Pmx,vertex.Pmy,vertex.Pmz
730
731 ! Calculate Em, Pm, Mrec, Trec for all cases not already done.
732 ! For doing_heavy, get Mrec from nu+M=Ep+Erec, and Erec**2=Mrec**2+Pm**2
733 ! For (e,e'pi/K), could go back and determine momentum of recoil struck
734 ! particle, and get Mrec and Trec seperately for struck nucleon(hyperon)
735 ! and A-1 system. For now, just take Trec for the A-1 system, and ignore
736 gaskelld 1.1 ! the recoiling struck nucleon (hyperon), so Trec=0 for hydrogen target.
737
738 if (doing_hyd_elast) then
739 vertex.Trec = 0.0
740 else if (doing_deuterium) then
741 vertex.Pm = vertex.Pmiss
742 vertex.Trec = sqrt(vertex.Mrec**2 + vertex.Pm**2) - vertex.Mrec
743 else if (doing_heavy) then
744 vertex.Pm = vertex.Pmiss
745 vertex.Mrec = sqrt(vertex.Emiss**2-vertex.Pmiss**2)
746 vertex.Em = targ.Mtar_struck + vertex.Mrec - targ.M
747 vertex.Trec = sqrt(vertex.Mrec**2 + vertex.Pm**2) - vertex.Mrec
748 else if (doing_hydpi .or. doing_hydkaon .or. doing_hyddelta .or. doing_hydrho) then
749 vertex.Trec = 0.0
750 else if (doing_deutpi.or.doing_hepi.or.doing_deutkaon.or.doing_hekaon
751 1 .or.doing_deutdelta.or.doing_hedelta.or.doing_deutrho.or.doing_herho) then
752 vertex.Trec = sqrt(vertex.Mrec**2 + vertex.Pm**2) - vertex.Mrec
753 else if (doing_semi) then
754 vertex.Pm = vertex.Pmiss
755 vertex.Em = vertex.Emiss
756 endif
757 gaskelld 1.1
758 if (debug(5)) write(6,*) 'vertex.Pm,vertex.Trec,vertex.Em',vertex.Pm,vertex.Trec,vertex.Em
759 if (debug(4)) write(6,*)'comp_ev: at 10'
760
761
762 ! calculate krel for deuteron/heavy pion(kaon). Deuteron is straightforward.
763 ! A>2 case is some approximation for 3He (DJG).
764
765 if (doing_deutpi .or. doing_deutkaon .or. doing_deutdelta .or. doing_deutrho) then
766 if ((vertex.Emiss**2-vertex.Pmiss**2).lt.0) write(6,*) 'BAD MM!!!!! Emiss,Pmiss=',vertex.Emiss, vertex.Pmiss
767 MM = sqrt(max(0.d0,vertex.Emiss**2-vertex.Pmiss**2))
768 krel = sqrt( max(0.d0,MM**2-4.*targ.Mrec_struck**2) )
769 else if (doing_hepi .or. doing_hekaon .or. doing_hedelta .or. doing_herho) then
770 if ((vertex.Emiss**2-vertex.Pmiss**2).lt.0) write(6,*) 'BAD MM!!!!! Emiss,Pmiss=',vertex.Emiss, vertex.Pmiss
771 MM = sqrt(max(0.d0,vertex.Emiss**2-vertex.Pmiss**2))
772 krelx = vertex.Pmx + 1.5*pferx*pfer
773 krely = vertex.Pmy + 1.5*pfery*pfer
774 krelz = vertex.Pmz + 1.5*pferz*pfer
775 krel = sqrt(krelx**2+krely**2+krelz**2)
776 if(vertex.Em.lt.6.0) krel = -krel !bound state test???
777 endif
778 gaskelld 1.1 ntup.krel = krel
779
780 if(doing_semi) then
781 CDJG if ((vertex.Emiss**2-vertex.Pmiss**2).lt.0) then
782 CDJG I should be testing that the missing mass is above two pion
783 CDJG threshold! Otherwise, it's just exclusive
784 if ((vertex.Emiss**2-vertex.Pmiss**2).lt.(Mp+Mpi0)**2) then
785 success=.false.
786 return
787 endif
788 endif
789
790 if(doing_semi) then
791 vertex.zhad = vertex.p.E/vertex.nu
792 vertex.pt2 = vertex.p.P**2*(1.0-cos(main.theta_pq)**2)
793 if(vertex.zhad.gt.1.0) then
794 success=.false.
795 return
796 endif
797 endif
798
799 gaskelld 1.1
800 ! Determine PHYSICS scattering angles theta/phi for the two spectrometer
801 ! vectors, and the Jacobian which we must include in our xsec computation
802 ! to take into account the fact that we're not generating in the physics
803 ! solid angle d(omega) but in 'spectrometer angles' yptar,xptar.
804 ! NOTE: the conversion from spectrometer to physics angles was done when
805 ! the angles were first generated (except for the proton angle for hydrogen
806 ! elastic, where it was done earlier in complete_ev).
807 !
808 ! call physics_angles(spec.e.theta,spec.e.phi,
809 ! & vertex.e.xptar,vertex.e.yptar,vertex.e.theta,vertex.e.phi)
810 ! call physics_angles(spec.p.theta,spec.p.phi,
811 ! & vertex.p.xptar,vertex.p.yptar,vertex.p.theta,vertex.p.phi)
812
813 r = sqrt(1.+vertex.e.yptar**2+vertex.e.xptar**2) !r=cos(theta-theta0)
814 main.jacobian = main.jacobian / r**3 !1/cos**3(theta-theta0)
815
816 if (doing_heavy .or. doing_pion .or. doing_kaon .or.
817 1 doing_rho .or. doing_delta .or. doing_semi) then
818 r = sqrt(1.+vertex.p.yptar**2+vertex.p.xptar**2)
819 main.jacobian = main.jacobian / r**3 !1/cos**3(theta-theta0)
820 gaskelld 1.1 endif
821
822 if (debug(4)) write(6,*)'comp_ev: at 11'
823
824 ! The effective target thickness that the scattered particles see, and the
825 ! resulting energy losses
826
827 call trip_thru_target (2, main.target.z-targ.zoffset, vertex.e.E,
828 > vertex.e.theta, main.target.Eloss(2), main.target.teff(2),Me,1)
829 call trip_thru_target (3, main.target.z-targ.zoffset, vertex.p.E,
830 > vertex.p.theta, main.target.Eloss(3), main.target.teff(3),Mh,1)
831 if (.not.using_Eloss) then
832 main.target.Eloss(2) = 0.0
833 main.target.Eloss(3) = 0.0
834 endif
835 if (debug(4)) write(6,*)'comp_ev: at 12'
836
837 ! Initialize parameters necessary for radiative corrections
838
839 call radc_init_ev(main,vertex)
840
841 gaskelld 1.1 ! Success code
842
843 success = .true.
844 if(debug(2)) write(6,*)'comp_ev: at end...'
845 return
846 end
847
848 !---------------------------------------------------------------------
849
850 subroutine complete_recon_ev(recon,success)
851
852 implicit none
853 include 'simulate.inc'
854
855 real*8 p_new_x,p_new_y,new_x_x,new_x_y,new_x_z
856 real*8 new_y_x,new_y_y,new_y_z,dummy
857 real*8 px,py,pz,qx,qy,qz
858 real*8 W2
859 real*8 oop_x,oop_y
860 real*8 mm,mmA,mm2,mmA2,t
861
862 gaskelld 1.1 logical success
863 record /event/ recon
864
865 !-----------------------------------------------------------------------
866 ! Calculate everything left in the /event/ structure, given
867 ! recon.Ein, and the following for both recon.e AND recon.p:
868 ! delta,xptar,yptar, z,P,E,theta,phi (with E,P corrected for eloss, if desired).
869 !
870 ! The SINGLE element of /event/ NOT computed here is sigcc (for (e,e'p)).
871 !
872 !-----------------------------------------------------------------------
873
874 ! Initialize
875
876 success = .false.
877
878 recon.Ein = Ebeam_vertex_ave !lowered by most probable eloss (init.f)
879
880 ! ... unit vector components of outgoing e,p
881 ! ... z is DOWNSTREAM, x is DOWN and y is LEFT looking downstream.
882
883 gaskelld 1.1 if (debug(4)) write(6,*)'comp_rec_ev: at 1'
884 recon.ue.x = sin(recon.e.theta)*cos(recon.e.phi)
885 recon.ue.y = sin(recon.e.theta)*sin(recon.e.phi)
886 recon.ue.z = cos(recon.e.theta)
887 recon.up.x = sin(recon.p.theta)*cos(recon.p.phi)
888 recon.up.y = sin(recon.p.theta)*sin(recon.p.phi)
889 recon.up.z = cos(recon.p.theta)
890 if (debug(4)) write(6,*)'comp_rec_ev: at 2'
891
892 ! The q vector
893
894 if (debug(5)) write(6,*)'comp_rec_ev: Ein,E,uez=',recon.Ein,recon.e.E,recon.ue.z
895 recon.nu = recon.Ein - recon.e.E
896 recon.Q2 = 2*recon.Ein*recon.e.E*(1-recon.ue.z)
897 recon.q = sqrt(recon.Q2 + recon.nu**2)
898 recon.uq.x = - recon.e.P*recon.ue.x / recon.q
899 recon.uq.y = - recon.e.P*recon.ue.y / recon.q
900 recon.uq.z =(recon.Ein - recon.e.P*recon.ue.z)/ recon.q
901 W2 = targ.M**2 + 2.*targ.M*recon.nu - recon.Q2
902 recon.W = sqrt(abs(W2)) * W2/abs(W2)
903 recon.xbj = recon.Q2/2./Mp/recon.nu
904 gaskelld 1.1 if (debug(4)) write(6,*)'comp_rec_ev: at 5'
905
906 ! Now complete the p side
907
908 if(doing_phsp)then
909 recon.p.P=spec.p.P
910 recon.p.E=sqrt(Mh2+recon.p.P**2)
911 if (debug(4)) write(6,*)'comp_rec_ev: at 7.5',Mh2,recon.p.E
912 endif
913
914 ! Compute some pion/kaon stuff.
915
916 recon.epsilon=1./(1. + 2.*(1+recon.nu**2/recon.Q2)*tan(recon.e.theta/2.)**2)
917 recon.theta_pq=acos(min(1.0,recon.up.x*recon.uq.x+recon.up.y*recon.uq.y+recon.up.z*recon.uq.z))
918
919 ! CALCULATE ANGLE PHI BETWEEN SCATTERING PLANE AND REACTION PLANE.
920 ! Therefore, define a new system with the z axis parallel to q, and
921 ! the x axis inside the q-z-plane: z' = q, y' = q X z, x' = y' X q
922 ! this gives phi the way it is usually defined, i.e. phi=0 for in-plane
923 ! particles closer to the downstream beamline than q.
924 ! phi=90 is above the horizontal plane when q points to the right, and
925 gaskelld 1.1 ! below the horizontal plane when q points to the left.
926 ! Also take into account the different definitions of x, y and z in
927 ! replay and SIMC:
928 ! As seen looking downstream: replay SIMC (old_simc)
929 ! x right down (left)
930 ! y down left (up)
931 ! z all have z pointing downstream
932 !
933 ! SO: x_replay=-y_simc, y_replay=x_simc, z_replay= z_simc
934
935 qx = -recon.uq.y !convert to 'replay' coord. system
936 qy = recon.uq.x
937 qz = recon.uq.z
938 px = -recon.up.y
939 py = recon.up.x
940 pz = recon.up.z
941
942 dummy=sqrt((qx**2+qy**2)*(qx**2+qy**2+qz**2))
943 new_x_x = -qx*qz/dummy
944 new_x_y = -qy*qz/dummy
945 new_x_z = (qx**2 + qy**2)/dummy
946 gaskelld 1.1
947 dummy = sqrt(qx**2 + qy**2)
948 new_y_x = qy/dummy
949 new_y_y = -qx/dummy
950 new_y_z = 0.0
951
952 p_new_x = px*new_x_x + py*new_x_y + pz*new_x_z
953 p_new_y = px*new_y_x + py*new_y_y + pz*new_y_z
954
955 if ((p_new_x**2+p_new_y**2).eq.0.) then
956 recon.phi_pq = 0.0
957 else
958 recon.phi_pq = acos(p_new_x/sqrt(p_new_x**2+p_new_y**2))
959 endif
960 if (p_new_y.lt.0.) then
961 recon.phi_pq = 2*pi - recon.phi_pq
962 endif
963
964 if (debug(2)) then
965 write(6,*)'comp_rec_ev: nu =',recon.nu
966 write(6,*)'comp_rec_ev: Q2 =',recon.Q2
967 gaskelld 1.1 write(6,*)'comp_rec_ev: theta_e =',recon.e.theta
968 write(6,*)'comp_rec_ev: epsilon =',recon.epsilon
969 write(6,*)'comp_rec_ev: theta_pq =',recon.theta_pq
970 write(6,*)'comp_rec_ev: phi_pq =',recon.phi_pq
971 endif
972
973 if (debug(4)) write(6,*)'comp_rec_ev: at 8'
974
975 ! Compute the Pm vector in in SIMC LAB system, with x down, and y to the left.
976 ! Computer Parallel, Perpendicular, and Out of Plane componenants.
977 ! Parallel is component along q_hat. Out/plane is component along
978 ! (e_hat) x (q_hat) (oop_x,oop_y are components of out/plane unit vector)
979 ! Perp. component is what's left: along (q_hat) x (oop_hat).
980 ! So looking along q, out of plane is down, perp. is left.
981
982 recon.Pmx = recon.p.P*recon.up.x - recon.q*recon.uq.x
983 recon.Pmy = recon.p.P*recon.up.y - recon.q*recon.uq.y
984 recon.Pmz = recon.p.P*recon.up.z - recon.q*recon.uq.z
985 recon.Pm = sqrt(recon.Pmx**2+recon.Pmy**2+recon.Pmz**2)
986
987 !STILL NEED SIGN FOR PmPer!!!!!!
988 gaskelld 1.1
989 oop_x = -recon.uq.y ! oop_x = q_y *(z_hat x y_hat) = q_y *-(x_hat)
990 oop_y = recon.uq.x ! oop_y = q_x *(z_hat x x_hat) = q_x * (y_hat)
991 recon.PmPar = (recon.Pmx*recon.uq.x + recon.Pmy*recon.uq.y + recon.Pmz*recon.uq.z)
992 recon.PmOop = (recon.Pmx*oop_x + recon.Pmy*oop_y) / sqrt(oop_x**2+oop_y**2)
993 recon.PmPer = sqrt( max(0.d0, recon.Pm**2 - recon.PmPar**2 - recon.PmOop**2 ) )
994
995 if (doing_pion .or. doing_kaon .or. doing_delta .or. doing_rho .or. doing_semi) then
996 recon.Em = recon.nu + targ.Mtar_struck - recon.p.E
997 mm2 = recon.Em**2 - recon.Pm**2
998 mm = sqrt(abs(mm2)) * abs(mm2)/mm2
999 mmA2= (recon.nu + targ.M - recon.p.E)**2 - recon.Pm**2
1000 mmA = sqrt(abs(mmA2)) * abs(mmA2)/mmA2
1001 t = recon.Q2 - Mh2
1002 > + 2*(recon.nu*recon.p.E - recon.p.P*recon.q*cos(recon.theta_pq))
1003 ntup.mm = mm
1004 ntup.mmA = mmA
1005 ntup.t = t
1006 endif
1007
1008 if(doing_semi.or.doing_rho) then
1009 gaskelld 1.1 recon.zhad = recon.p.E/recon.nu
1010 recon.pt2 = recon.p.P**2*(1.0-cos(recon.theta_pq)**2)
1011 endif
1012
1013 ! Calculate Trec, Em. Trec for (A-1) system (eep), or for struck nucleon (pi/K)
1014 ! Note that there are other ways to calculate 'Em' for the pion/kaon case.
1015 ! This Em for pi/kaon gives roughly E_m + E_rec + T_{A-1} (I think)
1016 if (doing_hyd_elast) then
1017 recon.Trec = 0.0
1018 recon.Em = recon.nu + targ.M - recon.p.E - recon.Trec
1019 else if (doing_deuterium .or. doing_heavy) then
1020 recon.Trec = sqrt(recon.Pm**2+targ.Mrec**2) - targ.Mrec
1021 recon.Em = recon.nu + targ.Mtar_struck - recon.p.E - recon.Trec
1022 else if (doing_pion .or. doing_kaon .or. doing_delta .or. doing_rho) then
1023 recon.Em = recon.nu + targ.Mtar_struck - recon.p.E
1024 endif
1025
1026 if (debug(5)) write(6,*) 'recon.Pm,recon.Trec,recon.Em',recon.Pm,recon.Trec,recon.Em
1027 if (debug(4)) write(6,*)'comp_rec_ev: at 10'
1028
1029 success=.true.
1030 gaskelld 1.1 return
1031 end
1032
1033 !------------------------------------------------------------------------
1034
1035 subroutine complete_main(force_sigcc,main,vertex,vertex0,recon,success)
1036
1037 implicit none
1038 include 'simulate.inc'
1039
1040 integer i, iPm1
1041 real*8 a, b, r, frac, peepi, peeK, peedelta, peerho, peepiX
1042 real*8 survivalprob
1043 real*8 weight, width, sigep, deForest, tgtweight
1044 logical force_sigcc, success
1045 record /event_main/ main
1046 record /event/ vertex, vertex0, recon
1047
1048 !-----------------------------------------------------------------------
1049 ! Calculate everything left in the /main/ structure that hasn't been
1050 ! required up til now. This routine is called ONLY after we
1051 gaskelld 1.1 ! know an event IS going to contribute, don't want to be doing these
1052 ! calculations if they're not needed!
1053 !
1054 ! A small anomaly is that sigcc from the /event/ structure is computed
1055 ! here since it's not needed til now, and was not calculated by
1056 ! COMPLETE_ev.
1057 !-----------------------------------------------------------------------
1058
1059
1060 ! Initialize success code
1061
1062 if (debug(2)) write(6,*)'comp_main: entering...'
1063 success = .false.
1064
1065 ! The spectral function weighting
1066
1067 if (doing_hyd_elast.or.doing_pion.or.doing_kaon.or.doing_delta.or.doing_phsp.or.doing_rho.or.doing_semi) then !no SF.
1068 main.SF_weight=1.0
1069 else if (doing_deuterium .or. doing_heavy) then
1070 main.SF_weight = 0.0
1071 do i=1,nrhoPm
1072 gaskelld 1.1 weight = 0.0
1073
1074 ! ... use linear interpolation to determine rho(pm)
1075
1076 r = (vertex.Pm-Pm_theory(i).min)/Pm_theory(i).bin
1077 if (r.ge.0 .and. r.le.Pm_theory(i).n) then
1078 iPm1 = nint(r)
1079 if (iPm1.eq.0) iPm1 = 1
1080 if (iPm1.eq.Pm_theory(i).n) iPm1 = Pm_theory(i).n-1
1081 frac = r+0.5-float(iPm1)
1082 b = theory(i,iPm1)
1083 a = theory(i,iPm1+1)-b
1084 weight = a*frac + b
1085 endif
1086
1087 if (doing_heavy) then
1088
1089 width=Emsig_theory(i)/2.0
1090 if (vertex.Em.lt.E_Fermi) weight = 0.0
1091 weight=weight/pi/Em_int_theory(i) * width/
1092 > ((vertex.Em-Em_theory(i))**2+width**2)
1093 gaskelld 1.1 endif
1094 main.SF_weight = main.SF_weight+weight*nprot_theory(i)
1095 enddo ! <i=1,nrhoPm>
1096 endif
1097
1098 ! ... if we have come up with weight<=, quit now (avoid weight<0 in ntuple)
1099 ! ... unless FORCE_SIGCC is on (to get central sigcc).
1100
1101 if (debug(5))write(6,*)'comp_main: calculating cross section'
1102 if (main.SF_weight.le.0 .and. .not.force_sigcc) return
1103
1104 ! ... Cross section, for BOTH vertex and recon (where possible)
1105 ! ... Note that all of these are cross section per nucleon. For A(e,e'p)
1106 ! ... this becomes cross section per nucleus because of the weighting of
1107 ! ... the spectral function. For pion/kaon production, we explicitly
1108 ! ... apply a weight for the number of nucleons involved (protons for pi+ or Y0,
1109 ! ... neutrons for pi- or Y-) (Y=hyperon)
1110
1111 tgtweight = 1.0
1112
1113 if (doing_phsp) then
1114 gaskelld 1.1 main.sigcc = 1.0
1115 main.sigcc_recon = 1.0
1116
1117 elseif (doing_hyd_elast) then
1118 main.sigcc = sigep(vertex)
1119 main.sigcc_recon = sigep(recon)
1120
1121 elseif (doing_deuterium.or.doing_heavy) then
1122 main.sigcc = deForest(vertex)
1123 main.sigcc_recon = deForest(recon)
1124
1125 elseif (doing_pion) then
1126 main.sigcc = peepi(vertex,main)
1127 main.sigcc_recon = 1.0
1128 if (which_pion.eq.1 .or. which_pion.eq.11) then !OK for coherent???
1129 tgtweight = targ.N
1130 else
1131 tgtweight = targ.Z
1132 endif
1133
1134 elseif (doing_kaon) then
1135 gaskelld 1.1 main.sigcc = peeK(vertex,main,survivalprob)
1136 main.sigcc_recon = 1.0
1137 if (which_kaon.eq.2 .or. which_kaon.eq.12) then !OK for coherent???
1138 tgtweight = targ.N
1139 else
1140 tgtweight = targ.Z
1141 endif
1142
1143 elseif (doing_delta) then
1144 main.sigcc = peedelta(vertex,main) !Need new xsec model.
1145 main.sigcc_recon = 1.0
1146
1147 elseif (doing_rho) then
1148 main.sigcc = peerho(vertex,main)
1149 main.sigcc_recon = 1.0
1150
1151 elseif (doing_semi) then
1152 main.sigcc = peepiX(vertex,vertex0,main,survivalprob,.FALSE.)
1153 main.sigcc_recon = 1.0
1154 main.sigcent = peepiX(vertex,vertex0,main,survivalprob,.TRUE.)
1155
1156 gaskelld 1.1 else
1157 main.sigcc = 1.0
1158 main.sigcc_recon = 1.0
1159 endif
1160
1161 if (debug(3)) then
1162 write(6,*)'======================================'
1163 write(6,*)'complete_main:'
1164 write(6,*)'theta_e =',vertex.e.theta
1165 write(6,*)'q mag =',vertex.q
1166 write(6,*)'nu =',vertex.nu
1167 write(6,*)'Q2 =',vertex.Q2/1000000.
1168 write(6,*)'Ein =',vertex.Ein
1169 write(6,*)'hadron mom =',vertex.p.P
1170 write(6,*)'e mom =',vertex.e.P
1171 write(6,*)'mass =',Mh
1172 write(6,*)'epsilon =',main.epsilon
1173 write(6,*)'phi_pq =',main.phi_pq
1174 write(6,*)'theta_pq =',main.theta_pq
1175 write(6,*)'======================================'
1176 endif
1177 gaskelld 1.1
1178 ! The total contributing weight from this event -- this weight is
1179 ! proportional to # experimental counts represented by the event.
1180 ! Apply survival probability to kaons if we're not modeling decay.
1181
1182 main.weight = main.SF_weight*main.jacobian*main.gen_weight*main.sigcc
1183 main.weight = main.weight * tgtweight !correct for #/nucleons involved
1184 if ((doing_kaon.or.doing_semika) .and. .not.doing_decay)
1185 > main.weight = main.weight*survivalprob
1186 if (debug(5))write(6,*) 'gen_weight = ',main.gen_weight,
1187 > main.jacobian,main.sigcc
1188
1189 success = .true.
1190
1191 if (debug(2)) write(6,*)'comp_main: ending, success =',success
1192 return
1193 end
1194
1195
1196 subroutine physics_angles(theta0,phi0,dx,dy,theta,phi)
1197
1198 gaskelld 1.1 !Generate physics angles in lab frame. Theta is angle from beamline.
1199 !phi is projection on x-y plane (so phi=0 is down, sos=pi/2, hms=3*pi/2.
1200 !
1201 !theta=acos( (cos(theta0)-dy*sin(theta0)*sin(phi0))/ sqrt(1+dx**2+dy**2) )
1202 !phi=atan( (dy*cos(theta0)+sin(theta0)*sin(phi0)) / (sin(theta0)*cos(phi0)+dx) )
1203 !
1204 ! Note that these formulae assume phi0=pi/2 or 3*pi/2 (thus the sin(phi0)
1205 ! gives a -/+ sign for the HMS/SOS). Thus, we set the cos(phi0) term to zero.
1206
1207 real*8 dx,dy !dx/dy (xptar/yptar) for event.
1208 real*8 theta0,phi0 !central physics angles of spectrometer.
1209 real*8 theta,phi !physics angles for event.
1210 real*8 r,sinth,costh,sinph,cosph !intermediate variables.
1211 real*8 tmp
1212
1213 include 'constants.inc'
1214
1215 costh = cos(theta0)
1216 sinth = sin(theta0)
1217 sinph = sin(phi0)
1218 cosph = cos(phi0)
1219 gaskelld 1.1 r = sqrt( 1. + dx**2 + dy**2 )
1220
1221 if (abs(cosph).gt.0.0001) then !phi not at +/- pi/2
1222 write(6,*) 'theta,phi will be incorrect if phi0 <> pi/2 or 3*pi/2'
1223 write(6,*) 'phi0=',phi0,'=',phi0*180/pi,'degrees'
1224 endif
1225
1226 tmp=(costh - dy*sinth*sinph) / r
1227 if (abs(tmp).gt.1) write(6,*) 'tmp=',tmp
1228 theta = acos( (costh - dy*sinth*sinph) / r )
1229 if (dx.ne.0.0) then
1230 phi = atan( (dy*costh + sinth*sinph) / dx ) !gives -90 to 90 deg.
1231 if (phi.le.0) phi=phi+pi !make 0 to 180 deg.
1232 if (sinph.lt.0.) phi=phi+pi !add pi to phi for HMS
1233 else
1234 phi = phi0
1235 endif
1236
1237 return
1238 end
1239
1240 gaskelld 1.1
1241
1242 subroutine spectrometer_angles(theta0,phi0,dx,dy,theta,phi)
1243
1244 !Generate spectrometer angles from physics angles in lab frame.
1245 !Theta is angle from beamline.
1246 !phi is projection on x-y plane (so phi=0 is down, sos=pi/2, hms=3*pi/2.
1247
1248 real*8 dx,dy !dx/dy (xptar/yptar) for event.
1249 real*8 theta0,phi0 !central physics angles of spectrometer.
1250 real*8 theta,phi !physics angles for event.
1251 real*8 x,y,z !intermediate variables.
1252 real*8 x0,y0,z0 !intermediate variables.
1253 real*8 cos_dtheta,y_event
1254
1255 include 'constants.inc'
1256
1257 x = sin(theta)*cos(phi)
1258 y = sin(theta)*sin(phi)
1259 z = cos(theta)
1260 x0 = sin(theta0)*cos(phi0)
1261 gaskelld 1.1 y0 = sin(theta0)*sin(phi0)
1262 z0 = cos(theta0)
1263
1264 cos_dtheta = x*x0 + y*y0 + z*z0
1265 dx = x / cos_dtheta
1266 dy = sqrt(1/cos_dtheta**2-1.-dx**2)
1267
1268 y_event = y/cos_dtheta !projected to plane perp. to spectrometer.
1269 if (y_event .lt. y0) dy = -dy
1270
1271 return
1272 end
|