1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """Several different checks for processes (and hence models):
16 permutation tests, gauge invariance tests, lorentz invariance
17 tests. Also class for evaluation of Python matrix elements,
18 MatrixElementEvaluator."""
19
20 from __future__ import division
21
22 import array
23 import copy
24 import fractions
25 import itertools
26 import logging
27 import math
28 import os
29 import re
30
31 import aloha.aloha_writers as aloha_writers
32 import aloha.create_aloha as create_aloha
33
34 import madgraph.iolibs.export_python as export_python
35 import madgraph.iolibs.helas_call_writers as helas_call_writers
36 import models.import_ufo as import_ufo
37 import madgraph.iolibs.save_load_object as save_load_object
38
39 import madgraph.core.base_objects as base_objects
40 import madgraph.core.color_algebra as color
41 import madgraph.core.color_amp as color_amp
42 import madgraph.core.helas_objects as helas_objects
43 import madgraph.core.diagram_generation as diagram_generation
44
45 import madgraph.various.rambo as rambo
46 import madgraph.various.misc as misc
47
48
49 from madgraph import MG5DIR, InvalidCmd
50
51 import models.model_reader as model_reader
52 import aloha.template_files.wavefunctions as wavefunctions
53 from aloha.template_files.wavefunctions import \
54 ixxxxx, oxxxxx, vxxxxx, sxxxxx, txxxxx
55
56
57
58
59
60 logger = logging.getLogger('madgraph.various.process_checks')
61
62
63
64
66 """Class taking care of matrix element evaluation, storing
67 relevant quantities for speedup."""
68
69 - def __init__(self, model, param_card = None,
70 auth_skipping = False, reuse = True):
71 """Initialize object with stored_quantities, helas_writer,
72 model, etc.
73 auth_skipping = True means that any identical matrix element will be
74 evaluated only once
75 reuse = True means that the matrix element corresponding to a
76 given process can be reused (turn off if you are using
77 different models for the same process)"""
78
79
80 self.helas_writer = helas_call_writers.PythonUFOHelasCallWriter(model)
81
82
83 self.full_model = model_reader.ModelReader(model)
84 self.full_model.set_parameters_and_couplings(param_card)
85
86 self.auth_skipping = auth_skipping
87 self.reuse = reuse
88 self.store_aloha = []
89 self.stored_quantities = {}
90
91
92
93
94 - def evaluate_matrix_element(self, matrix_element, p=None, full_model=None,
95 gauge_check=False, auth_skipping=None, output='m2'):
96 """Calculate the matrix element and evaluate it for a phase space point
97 output is either m2, amp, jamp
98 """
99 if full_model:
100 self.full_model = full_model
101
102 process = matrix_element.get('processes')[0]
103 model = process.get('model')
104
105 if "matrix_elements" not in self.stored_quantities:
106 self.stored_quantities['matrix_elements'] = []
107 matrix_methods = {}
108
109 if self.reuse and "Matrix_%s" % process.shell_string() in globals() and p:
110
111 matrix = eval("Matrix_%s()" % process.shell_string())
112 me_value = matrix.smatrix(p, self.full_model)
113 if output == "m2":
114 return matrix.smatrix(p, self.full_model), matrix.amp2
115 else:
116 m2 = matrix.smatrix(p, self.full_model)
117 return {'m2': m2, output:getattr(matrix, output)}
118
119 if (auth_skipping or self.auth_skipping) and matrix_element in \
120 self.stored_quantities['matrix_elements']:
121
122 logger.info("Skipping %s, " % process.nice_string() + \
123 "identical matrix element already tested" \
124 )
125 return None
126
127 self.stored_quantities['matrix_elements'].append(matrix_element)
128
129
130
131
132 if "list_colorize" not in self.stored_quantities:
133 self.stored_quantities["list_colorize"] = []
134 if "list_color_basis" not in self.stored_quantities:
135 self.stored_quantities["list_color_basis"] = []
136 if "list_color_matrices" not in self.stored_quantities:
137 self.stored_quantities["list_color_matrices"] = []
138
139 col_basis = color_amp.ColorBasis()
140 new_amp = matrix_element.get_base_amplitude()
141 matrix_element.set('base_amplitude', new_amp)
142 colorize_obj = col_basis.create_color_dict_list(new_amp)
143
144 try:
145
146
147
148 col_index = self.stored_quantities["list_colorize"].index(colorize_obj)
149 except ValueError:
150
151
152 self.stored_quantities['list_colorize'].append(colorize_obj)
153 col_basis.build()
154 self.stored_quantities['list_color_basis'].append(col_basis)
155 col_matrix = color_amp.ColorMatrix(col_basis)
156 self.stored_quantities['list_color_matrices'].append(col_matrix)
157 col_index = -1
158
159
160 matrix_element.set('color_basis',
161 self.stored_quantities['list_color_basis'][col_index])
162 matrix_element.set('color_matrix',
163 self.stored_quantities['list_color_matrices'][col_index])
164
165
166 if "used_lorentz" not in self.stored_quantities:
167 self.stored_quantities["used_lorentz"] = []
168
169 me_used_lorentz = set(matrix_element.get_used_lorentz())
170 me_used_lorentz = [lorentz for lorentz in me_used_lorentz \
171 if lorentz not in self.store_aloha]
172
173 aloha_model = create_aloha.AbstractALOHAModel(model.get('name'))
174 aloha_model.compute_subset(me_used_lorentz)
175
176
177 aloha_routines = []
178 for routine in aloha_model.values():
179 aloha_routines.append(routine.write(output_dir = None,
180 mode='mg5',
181 language = 'Python'))
182 for routine in aloha_model.external_routines:
183 aloha_routines.append(
184 open(aloha_model.locate_external(routine, 'Python')).read())
185
186
187
188 for routine in aloha_routines:
189 exec(routine, globals())
190
191
192 self.store_aloha.extend(me_used_lorentz)
193
194
195 exporter = export_python.ProcessExporterPython(matrix_element,
196 self.helas_writer)
197 try:
198 matrix_methods = exporter.get_python_matrix_methods(\
199 gauge_check=gauge_check)
200 except helas_call_writers.HelasWriterError, error:
201 logger.info(error)
202 return None
203
204 if self.reuse:
205
206 exec(matrix_methods[process.shell_string()], globals())
207 else:
208
209 exec(matrix_methods[process.shell_string()])
210
211
212 if not p:
213 p, w_rambo = self.get_momenta(process)
214
215
216 exec("data = Matrix_%s()" % process.shell_string())
217 if output == "m2":
218 return data.smatrix(p, self.full_model), data.amp2
219 else:
220 m2 = data.smatrix(p, self.full_model)
221 return {'m2': m2, output:getattr(data, output)}
222
223
224
225
227 """Get a point in phase space for the external states in the given
228 process, with the CM energy given. The incoming particles are
229 assumed to be oriented along the z axis, with particle 1 along the
230 positive z axis."""
231
232 if not (isinstance(process, base_objects.Process) and \
233 isinstance(energy, float)):
234 raise rambo.RAMBOError, "Not correct type for arguments to get_momenta"
235
236 sorted_legs = sorted(process.get('legs'), lambda l1, l2:\
237 l1.get('number') - l2.get('number'))
238
239 nincoming = len([leg for leg in sorted_legs if leg.get('state') == False])
240 nfinal = len(sorted_legs) - nincoming
241
242
243 mass_strings = [self.full_model.get_particle(l.get('id')).get('mass') \
244 for l in sorted_legs]
245 mass = [abs(self.full_model.get('parameter_dict')[m]) for m in mass_strings]
246
247
248 energy = max(energy, sum(mass[:nincoming]) + 200.,
249 sum(mass[nincoming:]) + 200.)
250
251 e2 = energy**2
252 m1 = mass[0]
253
254 p = []
255
256 masses = rambo.FortranList(nfinal)
257 for i in range(nfinal):
258 masses[i+1] = mass[nincoming + i]
259
260 if nincoming == 1:
261
262
263 p.append([m1, 0., 0., 0.])
264
265 p_rambo, w_rambo = rambo.RAMBO(nfinal, m1, masses)
266
267
268 for i in range(1, nfinal+1):
269 momi = [p_rambo[(4,i)], p_rambo[(1,i)],
270 p_rambo[(2,i)], p_rambo[(3,i)]]
271 p.append(momi)
272
273 return p, w_rambo
274
275 if nincoming != 2:
276 raise rambo.RAMBOError('Need 1 or 2 incoming particles')
277
278 if nfinal == 1:
279 energy = masses[0]
280
281 m2 = mass[1]
282
283 mom = math.sqrt((e2**2 - 2*e2*m1**2 + m1**4 - 2*e2*m2**2 - \
284 2*m1**2*m2**2 + m2**4) / (4*e2))
285 e1 = math.sqrt(mom**2+m1**2)
286 e2 = math.sqrt(mom**2+m2**2)
287
288 p.append([e1, 0., 0., mom])
289 p.append([e2, 0., 0., -mom])
290
291 if nfinal == 1:
292 p.append([energy, 0., 0., 0.])
293 return p, 1.
294
295 p_rambo, w_rambo = rambo.RAMBO(nfinal, energy, masses)
296
297
298 for i in range(1, nfinal+1):
299 momi = [p_rambo[(4,i)], p_rambo[(1,i)],
300 p_rambo[(2,i)], p_rambo[(3,i)]]
301 p.append(momi)
302
303 return p, w_rambo
304
305
306
307
310 """A wrapper function for running an iteration of a function over
311 a multiprocess, without having to first create a process list
312 (which makes a big difference for very large multiprocesses.
313 stored_quantities is a dictionary for any quantities that we want
314 to reuse between runs."""
315
316 model = multiprocess.get('model')
317 isids = [leg.get('ids') for leg in multiprocess.get('legs') \
318 if not leg.get('state')]
319 fsids = [leg.get('ids') for leg in multiprocess.get('legs') \
320 if leg.get('state')]
321
322 id_anti_id_dict = {}
323 for id in set(tuple(sum(isids+fsids, []))):
324 id_anti_id_dict[id] = model.get_particle(id).get_anti_pdg_code()
325 id_anti_id_dict[model.get_particle(id).get_anti_pdg_code()] = id
326
327 sorted_ids = []
328 results = []
329 for is_prod in apply(itertools.product, isids):
330 for fs_prod in apply(itertools.product, fsids):
331
332
333 if check_already_checked(is_prod, fs_prod, sorted_ids,
334 multiprocess, model, id_anti_id_dict):
335 continue
336
337
338 process = base_objects.Process({\
339 'legs': base_objects.LegList(\
340 [base_objects.Leg({'id': id, 'state':False}) for \
341 id in is_prod] + \
342 [base_objects.Leg({'id': id, 'state':True}) for \
343 id in fs_prod]),
344 'model':multiprocess.get('model'),
345 'id': multiprocess.get('id'),
346 'orders': multiprocess.get('orders'),
347 'required_s_channels': \
348 multiprocess.get('required_s_channels'),
349 'forbidden_s_channels': \
350 multiprocess.get('forbidden_s_channels'),
351 'forbidden_particles': \
352 multiprocess.get('forbidden_particles'),
353 'is_decay_chain': \
354 multiprocess.get('is_decay_chain'),
355 'overall_orders': \
356 multiprocess.get('overall_orders')})
357
358 result = function(process, stored_quantities, *args)
359
360 if result:
361 results.append(result)
362
363 return results
364
365
366
367
370 """Check if process already checked, if so return True, otherwise add
371 process and antiprocess to sorted_ids."""
372
373
374 if id_anti_id_dict:
375 is_ids = [id_anti_id_dict[id] for id in \
376 is_ids]
377 else:
378 is_ids = [model.get_particle(id).get_anti_pdg_code() for id in \
379 is_ids]
380
381 ids = array.array('i', sorted(is_ids + list(fs_ids)) + \
382 [process.get('id')])
383
384 if ids in sorted_ids:
385
386 return True
387
388
389 sorted_ids.append(ids)
390
391
392 return False
393
394
395
396
398 """Check processes by generating them with all possible orderings
399 of particles (which means different diagram building and Helas
400 calls), and comparing the resulting matrix element values."""
401
402 if isinstance(processes, base_objects.ProcessDefinition):
403
404
405 multiprocess = processes
406 model = multiprocess.get('model')
407
408
409 evaluator = MatrixElementEvaluator(model,
410 auth_skipping = True, reuse = False)
411 results = run_multiprocs_no_crossings(check_process,
412 multiprocess,
413 evaluator,
414 quick)
415
416 if "used_lorentz" not in evaluator.stored_quantities:
417 evaluator.stored_quantities["used_lorentz"] = []
418 return results, evaluator.stored_quantities["used_lorentz"]
419
420 elif isinstance(processes, base_objects.Process):
421 processes = base_objects.ProcessList([processes])
422 elif isinstance(processes, base_objects.ProcessList):
423 pass
424 else:
425 raise InvalidCmd("processes is of non-supported format")
426
427 if not processes:
428 raise InvalidCmd("No processes given")
429
430 model = processes[0].get('model')
431
432
433 evaluator = MatrixElementEvaluator(model, param_card,
434 auth_skipping = True, reuse = False)
435
436
437
438 sorted_ids = []
439 comparison_results = []
440
441
442 for process in processes:
443
444
445 if check_already_checked([l.get('id') for l in process.get('legs') if \
446 not l.get('state')],
447 [l.get('id') for l in process.get('legs') if \
448 l.get('state')],
449 sorted_ids, process, model):
450 continue
451
452 res = check_process(process, evaluator, quick)
453 if res:
454 comparison_results.append(res)
455
456 if "used_lorentz" not in evaluator.stored_quantities:
457 evaluator.stored_quantities["used_lorentz"] = []
458 return comparison_results, evaluator.stored_quantities["used_lorentz"]
459
460
462 """Check the helas calls for a process by generating the process
463 using all different permutations of the process legs (or, if
464 quick, use a subset of permutations), and check that the matrix
465 element is invariant under this."""
466
467 model = process.get('model')
468
469
470 for i, leg in enumerate(process.get('legs')):
471 leg.set('number', i+1)
472
473 logger.info("Checking %s" % \
474 process.nice_string().replace('Process', 'process'))
475
476 process_matrix_elements = []
477
478
479
480 if quick:
481 leg_positions = [[] for leg in process.get('legs')]
482 quick = range(1,len(process.get('legs')) + 1)
483
484 values = []
485
486
487 for legs in itertools.permutations(process.get('legs')):
488
489 order = [l.get('number') for l in legs]
490
491 if quick:
492 found_leg = True
493 for num in quick:
494
495
496 leg_position = legs.index([l for l in legs if \
497 l.get('number') == num][0])
498
499 if not leg_position in leg_positions[num-1]:
500 found_leg = False
501 leg_positions[num-1].append(leg_position)
502
503 if found_leg:
504 continue
505
506 legs = base_objects.LegList(legs)
507
508 if order != range(1,len(legs) + 1):
509 logger.info("Testing permutation: %s" % \
510 order)
511
512
513 newproc = copy.copy(process)
514 newproc.set('legs', legs)
515
516
517 try:
518 amplitude = diagram_generation.Amplitude(newproc)
519 except InvalidCmd:
520 result=False
521 else:
522 result = amplitude.get('diagrams')
523
524 if not result:
525
526 logging.info("No diagrams for %s" % \
527 process.nice_string().replace('Process', 'process'))
528 break
529
530 if order == range(1,len(legs) + 1):
531
532 p, w_rambo = evaluator.get_momenta(process)
533
534
535 matrix_element = helas_objects.HelasMatrixElement(amplitude,
536 gen_color=False)
537
538 if matrix_element in process_matrix_elements:
539
540
541 continue
542
543 process_matrix_elements.append(matrix_element)
544
545 res = evaluator.evaluate_matrix_element(matrix_element, p = p)
546 if res == None:
547 break
548
549 values.append(res[0])
550
551
552
553 if abs(max(values)) + abs(min(values)) > 0 and \
554 2 * abs(max(values) - min(values)) / \
555 (abs(max(values)) + abs(min(values))) > 0.01:
556 break
557
558
559 if not values:
560 return None
561
562
563
564 diff = 0
565 if abs(max(values)) + abs(min(values)) > 0:
566 diff = 2* abs(max(values) - min(values)) / \
567 (abs(max(values)) + abs(min(values)))
568
569 passed = diff < 1.e-8
570
571 return {"process": process,
572 "momenta": p,
573 "values": values,
574 "difference": diff,
575 "passed": passed}
576
577
579 """Present the results of a comparison in a nice list format
580 mode short: return the number of fail process
581 """
582
583 proc_col_size = 17
584
585 for proc in comparison_results:
586 if len(proc['process'].base_string()) + 1 > proc_col_size:
587 proc_col_size = len(proc['process'].base_string()) + 1
588
589 col_size = 17
590
591 pass_proc = 0
592 fail_proc = 0
593 no_check_proc = 0
594
595 failed_proc_list = []
596 no_check_proc_list = []
597
598 res_str = fixed_string_length("Process", proc_col_size) + \
599 fixed_string_length("Min element", col_size) + \
600 fixed_string_length("Max element", col_size) + \
601 fixed_string_length("Relative diff.", col_size) + \
602 "Result"
603
604 for result in comparison_results:
605 proc = result['process'].base_string()
606 values = result['values']
607
608 if len(values) <= 1:
609 res_str += '\n' + fixed_string_length(proc, proc_col_size) + \
610 " * No permutations, process not checked *"
611 no_check_proc += 1
612 no_check_proc_list.append(result['process'].nice_string())
613 continue
614
615 passed = result['passed']
616
617 res_str += '\n' + fixed_string_length(proc, proc_col_size) + \
618 fixed_string_length("%1.10e" % min(values), col_size) + \
619 fixed_string_length("%1.10e" % max(values), col_size) + \
620 fixed_string_length("%1.10e" % result['difference'],
621 col_size)
622 if passed:
623 pass_proc += 1
624 res_str += "Passed"
625 else:
626 fail_proc += 1
627 failed_proc_list.append(result['process'].nice_string())
628 res_str += "Failed"
629
630 res_str += "\nSummary: %i/%i passed, %i/%i failed" % \
631 (pass_proc, pass_proc + fail_proc,
632 fail_proc, pass_proc + fail_proc)
633
634 if fail_proc != 0:
635 res_str += "\nFailed processes: %s" % ', '.join(failed_proc_list)
636 if no_check_proc != 0:
637 res_str += "\nNot checked processes: %s" % ', '.join(no_check_proc_list)
638
639 return res_str
640
642 """Helper function to fix the length of a string by cutting it
643 or adding extra space."""
644
645 if len(mystr) > length:
646 return mystr[0:length]
647 else:
648 return mystr + " " * (length - len(mystr))
649
650
651
652
653
655 """Check gauge invariance of the processes by using the BRS check.
656 For one of the massless external bosons (e.g. gluon or photon),
657 replace the polarization vector (epsilon_mu) with its momentum (p_mu)
658 """
659
660 if isinstance(processes, base_objects.ProcessDefinition):
661
662
663 multiprocess = processes
664
665 model = multiprocess.get('model')
666
667
668 evaluator = MatrixElementEvaluator(model, param_card,
669 auth_skipping = True, reuse = False)
670
671
672 for particle in evaluator.full_model.get('particles'):
673 if particle.get('width') != 'ZERO':
674 evaluator.full_model.get('parameter_dict')[particle.get('width')] = 0.
675
676 return run_multiprocs_no_crossings(check_gauge_process,
677 multiprocess,
678 evaluator)
679
680 elif isinstance(processes, base_objects.Process):
681 processes = base_objects.ProcessList([processes])
682 elif isinstance(processes, base_objects.ProcessList):
683 pass
684 else:
685 raise InvalidCmd("processes is of non-supported format")
686
687 assert processes, "No processes given"
688
689 model = processes[0].get('model')
690
691
692 evaluator = MatrixElementEvaluator(model, param_card,
693 auth_skipping = True, reuse = False)
694
695 comparison_results = []
696
697
698 for process in processes:
699
700
701
702
703
704
705
706
707
708 result = check_gauge_process(process, evaluator)
709 if result:
710 comparison_results.append(result)
711
712 return comparison_results
713
714
716 """Check gauge invariance for the process, unless it is already done."""
717
718 model = process.get('model')
719
720
721 found_gauge = False
722 for i, leg in enumerate(process.get('legs')):
723 part = model.get_particle(leg.get('id'))
724 if part.get('spin') == 3 and part.get('mass').lower() == 'zero':
725 found_gauge = True
726 break
727
728 if not found_gauge:
729
730 return None
731
732 for i, leg in enumerate(process.get('legs')):
733 leg.set('number', i+1)
734
735 logger.info("Checking gauge %s" % \
736 process.nice_string().replace('Process', 'process'))
737
738 legs = process.get('legs')
739
740
741 try:
742 amplitude = diagram_generation.Amplitude(process)
743 except InvalidCmd:
744 logging.info("No diagrams for %s" % \
745 process.nice_string().replace('Process', 'process'))
746 return None
747
748 if not amplitude.get('diagrams'):
749
750 logging.info("No diagrams for %s" % \
751 process.nice_string().replace('Process', 'process'))
752 return None
753
754
755 matrix_element = helas_objects.HelasMatrixElement(amplitude,
756 gen_color = False)
757
758 brsvalue = evaluator.evaluate_matrix_element(matrix_element, gauge_check = True,
759 output='jamp')
760
761
762 matrix_element = helas_objects.HelasMatrixElement(amplitude,
763 gen_color = False)
764 mvalue = evaluator.evaluate_matrix_element(matrix_element, gauge_check = False,
765 output='jamp')
766
767 if mvalue and mvalue['m2']:
768 return {'process':process.base_string(),'value':mvalue,'brs':brsvalue}
769
771 """Present the results of a comparison in a nice list format"""
772
773 proc_col_size = 17
774 for one_comp in comparison_results:
775 proc = one_comp['process']
776 mvalue = one_comp['value']
777 brsvalue = one_comp['brs']
778 if len(proc) + 1 > proc_col_size:
779 proc_col_size = len(proc) + 1
780
781 col_size = 17
782
783 pass_proc = 0
784 fail_proc = 0
785
786 failed_proc_list = []
787 no_check_proc_list = []
788
789 res_str = fixed_string_length("Process", proc_col_size) + \
790 fixed_string_length("matrix", col_size) + \
791 fixed_string_length("BRS", col_size) + \
792 fixed_string_length("ratio", col_size) + \
793 "Result"
794
795 for one_comp in comparison_results:
796 proc = one_comp['process']
797 mvalue = one_comp['value']
798 brsvalue = one_comp['brs']
799 ratio = (brsvalue['m2']/mvalue['m2'])
800 res_str += '\n' + fixed_string_length(proc, proc_col_size) + \
801 fixed_string_length("%1.10e" % mvalue['m2'], col_size)+ \
802 fixed_string_length("%1.10e" % brsvalue['m2'], col_size)+ \
803 fixed_string_length("%1.10e" % ratio, col_size)
804
805 if ratio > 1e-12:
806 fail_proc += 1
807 proc_succeed = False
808 failed_proc_list.append(proc)
809 res_str += "Failed"
810 else:
811 pass_proc += 1
812 proc_succeed = True
813 res_str += "Passed"
814
815
816
817 for k in range(len(mvalue['jamp'][0])):
818 m_sum = 0
819 brs_sum = 0
820
821 for j in range(len(mvalue['jamp'])):
822
823 m_sum += abs(mvalue['jamp'][j][k])**2
824 brs_sum += abs(brsvalue['jamp'][j][k])**2
825
826
827 if not m_sum:
828 continue
829 ratio = brs_sum / m_sum
830
831 tmp_str = '\n' + fixed_string_length(' JAMP %s'%k , proc_col_size) + \
832 fixed_string_length("%1.10e" % m_sum, col_size) + \
833 fixed_string_length("%1.10e" % brs_sum, col_size) + \
834 fixed_string_length("%1.10e" % ratio, col_size)
835
836 if ratio > 1e-15:
837 if not len(failed_proc_list) or failed_proc_list[-1] != proc:
838 fail_proc += 1
839 pass_proc -= 1
840 failed_proc_list.append(proc)
841 res_str += tmp_str + "Failed"
842 elif not proc_succeed:
843 res_str += tmp_str + "Passed"
844
845
846 res_str += "\nSummary: %i/%i passed, %i/%i failed" % \
847 (pass_proc, pass_proc + fail_proc,
848 fail_proc, pass_proc + fail_proc)
849
850 if fail_proc != 0:
851 res_str += "\nFailed processes: %s" % ', '.join(failed_proc_list)
852
853 if output=='text':
854 return res_str
855 else:
856 return fail_proc
857
858
859
861 """ Check if the square matrix element (sum over helicity) is lorentz
862 invariant by boosting the momenta with different value."""
863
864 if isinstance(processes, base_objects.ProcessDefinition):
865
866
867 multiprocess = processes
868
869 model = multiprocess.get('model')
870
871
872 evaluator = MatrixElementEvaluator(model,
873 auth_skipping = False, reuse = True)
874
875
876 for particle in evaluator.full_model.get('particles'):
877 if particle.get('width') != 'ZERO':
878 evaluator.full_model.get('parameter_dict')[\
879 particle.get('width')] = 0.
880 return run_multiprocs_no_crossings(check_lorentz_process,
881 multiprocess,
882 evaluator)
883 elif isinstance(processes, base_objects.Process):
884 processes = base_objects.ProcessList([processes])
885 elif isinstance(processes, base_objects.ProcessList):
886 pass
887 else:
888 raise InvalidCmd("processes is of non-supported format")
889
890 assert processes, "No processes given"
891
892 model = processes[0].get('model')
893
894
895 evaluator = MatrixElementEvaluator(model, param_card,
896 auth_skipping = False, reuse = True)
897
898 comparison_results = []
899
900
901 for process in processes:
902
903
904
905
906
907
908
909
910
911 result = check_lorentz_process(process, evaluator)
912 if result:
913 comparison_results.append(result)
914
915 return comparison_results
916
917
919 """Check gauge invariance for the process, unless it is already done."""
920
921 amp_results = []
922 model = process.get('model')
923
924 for i, leg in enumerate(process.get('legs')):
925 leg.set('number', i+1)
926
927 logger.info("Checking lorentz %s" % \
928 process.nice_string().replace('Process', 'process'))
929
930 legs = process.get('legs')
931
932
933 try:
934 amplitude = diagram_generation.Amplitude(process)
935 except InvalidCmd:
936 logging.info("No diagrams for %s" % \
937 process.nice_string().replace('Process', 'process'))
938 return None
939
940 if not amplitude.get('diagrams'):
941
942 logging.info("No diagrams for %s" % \
943 process.nice_string().replace('Process', 'process'))
944 return None
945
946
947 p, w_rambo = evaluator.get_momenta(process)
948
949
950 matrix_element = helas_objects.HelasMatrixElement(amplitude,
951 gen_color = True)
952
953 data = evaluator.evaluate_matrix_element(matrix_element, p=p, output='jamp',
954 auth_skipping = True)
955
956 if data and data['m2']:
957 results = [data]
958 else:
959 return {'process':process.base_string(), 'results':'pass'}
960
961 for boost in range(1,4):
962 boost_p = boost_momenta(p, boost)
963 results.append(evaluator.evaluate_matrix_element(matrix_element,
964 p=boost_p,
965 output='jamp'))
966
967
968 return {'process': process.base_string(), 'results': results}
969
970
972 """boost the set momenta in the 'boost direction' by the 'beta'
973 factor"""
974 boost_p = []
975 gamma = 1/ math.sqrt(1 - beta**2)
976 for imp in p:
977 bosst_p = imp[boost_direction]
978 E, px, py, pz = imp
979 boost_imp = []
980
981 boost_imp.append(gamma * E - gamma * beta * bosst_p)
982
983 if boost_direction == 1:
984 boost_imp.append(-gamma * beta * E + gamma * px)
985 else:
986 boost_imp.append(px)
987
988 if boost_direction == 2:
989 boost_imp.append(-gamma * beta * E + gamma * py)
990 else:
991 boost_imp.append(py)
992
993 if boost_direction == 3:
994 boost_imp.append(-gamma * beta * E + gamma * pz)
995 else:
996 boost_imp.append(pz)
997
998 boost_p.append(boost_imp)
999
1000 return boost_p
1001
1003 """Present the results of a comparison in a nice list format
1004 if output='fail' return the number of failed process -- for test--
1005 """
1006
1007 proc_col_size = 17
1008 for proc, values in comparison_results:
1009 if len(proc) + 1 > proc_col_size:
1010 proc_col_size = len(proc) + 1
1011
1012 col_size = 17
1013
1014 pass_proc = 0
1015 fail_proc = 0
1016 no_check_proc = 0
1017
1018 failed_proc_list = []
1019 no_check_proc_list = []
1020
1021 res_str = fixed_string_length("Process", proc_col_size) + \
1022 fixed_string_length("Min element", col_size) + \
1023 fixed_string_length("Max element", col_size) + \
1024 fixed_string_length("Relative diff.", col_size) + \
1025 "Result"
1026
1027 for one_comp in comparison_results:
1028 proc = one_comp['process']
1029 data = one_comp['results']
1030
1031 if data == 'pass':
1032 no_check_proc += 1
1033 no_check_proc_list.append(proc)
1034 continue
1035
1036 values = [data[i]['m2'] for i in range(len(data))]
1037
1038 min_val = min(values)
1039 max_val = max(values)
1040 diff = (max_val - min_val) / max_val
1041
1042 res_str += '\n' + fixed_string_length(proc, proc_col_size) + \
1043 fixed_string_length("%1.10e" % min_val, col_size) + \
1044 fixed_string_length("%1.10e" % max_val, col_size) + \
1045 fixed_string_length("%1.10e" % diff, col_size)
1046
1047 if diff < 1e-8:
1048 pass_proc += 1
1049 proc_succeed = True
1050 res_str += "Passed"
1051 else:
1052 fail_proc += 1
1053 proc_succeed = False
1054 failed_proc_list.append(proc)
1055 res_str += "Failed"
1056
1057
1058
1059 for k in range(len(data[0]['jamp'][0])):
1060 sum = [0] * len(data)
1061
1062 for j in range(len(data[0]['jamp'])):
1063
1064 values = [abs(data[i]['jamp'][j][k])**2 for i in range(len(data))]
1065 sum = [sum[i] + values[i] for i in range(len(values))]
1066
1067
1068 min_val = min(sum)
1069 max_val = max(sum)
1070 if not max_val:
1071 continue
1072 diff = (max_val - min_val) / max_val
1073
1074 tmp_str = '\n' + fixed_string_length(' JAMP %s'%k , proc_col_size) + \
1075 fixed_string_length("%1.10e" % min_val, col_size) + \
1076 fixed_string_length("%1.10e" % max_val, col_size) + \
1077 fixed_string_length("%1.10e" % diff, col_size)
1078
1079 if diff > 1e-10:
1080 if not len(failed_proc_list) or failed_proc_list[-1] != proc:
1081 fail_proc += 1
1082 pass_proc -= 1
1083 failed_proc_list.append(proc)
1084 res_str += tmp_str + "Failed"
1085 elif not proc_succeed:
1086 res_str += tmp_str + "Passed"
1087
1088
1089
1090 res_str += "\nSummary: %i/%i passed, %i/%i failed" % \
1091 (pass_proc, pass_proc + fail_proc,
1092 fail_proc, pass_proc + fail_proc)
1093
1094 if fail_proc != 0:
1095 res_str += "\nFailed processes: %s" % ', '.join(failed_proc_list)
1096 if no_check_proc:
1097 res_str += "\nNot checked processes: %s" % ', '.join(no_check_proc_list)
1098
1099 if output == 'text':
1100 return res_str
1101 else:
1102 return fail_proc
1103