1
2
3
4
5 import os
6
7 try:
8 from madgraph.madweight.MW_fct import *
9 import madgraph.madweight.diagram_class as diagram_class
10 import madgraph.madweight.mod_file as mod_file
11 import madgraph.madweight.Cards as Cards
12 import madgraph.various.misc as misc
13 except ImportError:
14 from internal.madweight.MW_fct import *
15 import internal.madweight.diagram_class as diagram_class
16 import internal.madweight.mod_file as mod_file
17 import internal.madweight.Cards as Cards
18 import internal.misc as misc
19
20
21 pjoin = os.path.join
23 """goes in each subprocess and creates the fortran code in each of them"""
24
25 template = mod_file.Mod_file(rule_file='./Source/MadWeight/mod_file/mod_main_code')
26
27 for MW_dir in MW_info.MW_listdir:
28 print 'treating', MW_dir, 'directory'
29 diag = MG_diagram('./SubProcesses/' + MW_dir, 'param_card_1.dat', './Source/MadWeight/transfer_function/ordering_file.inc', i, MW_info)
30 diag.create_all_fortran_code()
31 diag.write_code(template)
32
33
34
35
36
37
38
39
40
41
43 """ add the write routine for fortran code in this file """
44
45 - def __init__(self, dir_file, param_card, tf_file, config, opt='default'):
53
77
78
110
112 """Define the function to associate a initial weight to each permutation.
113 Those weight can be use both to remove permutation and/or to initialize the grid
114 on the permutation."""
115
116 def get_all_child(mother):
117 if mother.external:
118 return [mother]
119 else:
120 output = []
121 for child in mother.des:
122 output += get_all_child(child)
123 return output
124
125 fsock = open(pjoin(self.directory, 'permutation_weight.f'), 'w')
126 if self.MWparam['mw_perm']['preselect'].lower() == 'none':
127 fsock.write("""
128 subroutine GET_PERM_WEIGHT()
129 return
130 end
131 """
132 )
133 return
134
135
136 template = """ subroutine GET_PERM_WEIGHT()
137 implicit none
138 include 'nexternal.inc'
139 include 'coupl.inc'
140 include 'permutation.inc'
141 integer perm
142 integer perm_id(nexternal-2)
143 integer content(nexternal)
144 integer i
145 double precision WEIGHT
146 double precision weight_perm_global, weight_perm_BW
147 external weight_perm_global, weight_perm_BW
148
149
150 do perm = 1, NPERM
151 curr_perm = perm
152 call get_perm(perm, perm_id)
153 call assign_perm(perm_id)
154
155
156 weight = weight_perm_global(perm,perm_id)
157 %s
158 perm_value(perm, 1) = weight
159 enddo
160 return
161 end
162 """
163
164 data = []
165
166 for part in self.prop_content:
167 if part.mass and part.level > 0:
168 mass = self.dict_Fmass[abs(part.pid)]
169 width = self.dict_Fwidth[abs(part.pid)]
170 content = [p.MG for p in get_all_child(part)]
171 if 1 in content or 2 in content:
172 continue
173 content.append(0)
174 initcontent = "\n".join(""" content(%i) = %i""" % (a+1, b) for a,b in enumerate(content))
175 if mass.lower() == 'zero' or width.lower() == 'zero':
176 continue
177 dico = {'pid': part.pid,
178 'mass': mass,
179 'width': width,
180 'initcontent': initcontent
181 }
182
183 line = """%(initcontent)s
184 weight = weight * weight_perm_BW(perm, perm_id, %(mass)s, %(width)s, content, %(pid)i)
185 """ % dico
186 data.append(line)
187
188 text = template % '\n'.join(data)
189 fsock.write(text)
190
191 if self.MWparam['mw_perm']['preselect'] == 'default':
192 fsock.write(open(pjoin(self.directory, '../permutation_weight_default.dat')).read())
193 else:
194 fsock.write(open(pjoin(self.directory,'../..',self.MWparam['mw_perm']['preselect'])).read())
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
218 """ return the text for the definition of external routine and
219 local variable needed for the multichannel routine
220 """
221
222 text=''
223 i=0
224 deal_with=[]
225 for unaligned,nb in all_peak.items():
226 if not nb:
227 continue
228 i+=1
229 text+=' double precision local_%s \n' % (i)
230 if isinstance(unaligned, basestring):
231 name = 'tf_E_for_part\n'
232 elif unaligned.external:
233 name= 'tf_E_for_%s \n'% (unaligned.MG)
234 else:
235 pid=abs(unaligned.pid)
236 name= ' Breit_Wigner_for_part'
237 if name not in deal_with:
238 deal_with.append(name)
239 text += ' double precision %s\n' %name
240 text += ' external %s \n' %name
241
242 return text
243
245 """ all peak contains the list of the dictionary {peak:nb_of_appearance} each associated
246 to a specific channel.
247 label is the tag for the channel under study
248 returns the text defining, in fortran, the weight for this channel
249 the sum of the peaks ponderate by the appearance
250 """
251
252 def write_call_for_peak(obj,peak):
253 """ return the text on how to return the weight associted to this peak """
254
255 if isinstance(peak, basestring):
256 text = 'tf_E_for_part(%s)' % ( peak )
257 elif peak.external:
258 text = 'tf_E_for_%s() '% (peak.MG)
259 else:
260 pid=abs(peak.pid)
261 text = 'Breit_Wigner_for_part( %s, %s, %s)' % \
262 (peak.MG,obj.dict_Fmass[pid],obj.dict_Fwidth[pid])
263 return text
264
265 def product_of_peak(unaligned_peak,all_peak,peak_to_prov):
266 """ Return the product of local_XX associated to this set of
267 unaligned peak
268 """
269 text='1d0'
270 for unaligned,nb in all_peak.items():
271 if nb == 0:
272 continue
273 if unaligned not in unaligned_peak.keys():
274 text+=' * local_%s' %(peak_to_prov[unaligned])
275 return text
276
277
278 text = ''
279 den_text = ' den = 0d0'
280 num_text = ' num = 1d0'
281 i=0
282 peak_to_prov={}
283
284
285 for unaligned,nb in all_peak.items():
286 if nb == 0:
287 continue
288 i+=1
289 text += ' local_%s = %s \n' %(i,write_call_for_peak(self,unaligned))
290 peak_to_prov[unaligned]=i
291
292
293 if 'restrict_channel' in self.MWparam['mw_gen']:
294 if isinstance(self.MWparam['mw_gen']['restrict_channel'], list):
295 allowed_channel = [int(i)-1 for i in self.MWparam['mw_gen']['restrict_channel']]
296 elif self.MWparam['mw_gen']['restrict_channel'] in ['','0','F']:
297 allowed_channel = range(0,len(peak_by_channel))
298 else:
299 allowed_channel = [int(self.MWparam['mw_gen']['restrict_channel'])-1]
300 else:
301 allowed_channel = range(0,len(peak_by_channel))
302 for j in xrange(0,len(peak_by_channel)):
303 if j in allowed_channel:
304 den_text += ' + '+product_of_peak(peak_by_channel[j],all_peak,peak_to_prov)
305 if j == label:
306 num_text += ' * '+product_of_peak(peak_by_channel[j],all_peak,peak_to_prov)
307 elif j ==label:
308 if num_text.startswith(' num=0d0'):
309 num_text += ' * '+product_of_peak(peak_by_channel[j],all_peak,peak_to_prov)
310 else:
311 num_text = ' num=0d0 ! '+product_of_peak(peak_by_channel[j],all_peak,peak_to_prov)
312
313
314 if not num_text.startswith(' num=0d0'):
315 text+='\n'
316 text+=num_text+'\n'
317 text+=den_text+'\n'
318 if i:
319 text+=' multi_channel_weight = num/den\n'
320 else:
321 value=str(1.0/len(peak_by_channel))
322 value=value.replace('e','d')
323 text=' multi_channel_weight = %s\n' % value
324 else:
325 text+='\n'
326 text+=num_text+'\n'
327 text+=den_text+'\n'
328 text = 'c'+text.replace('\n','\nc')
329 text += '\n multi_channel_weight = 0d0\n'
330 return text
331
333 """ create the fortran code defining the weighting of each integration channel """
334
335
336
337
338
339 write_text=''
340
341 if num_sol == 1:
342 write_text += '''\n if (config.eq.1) then \n'''
343 else:
344 write_text += '\n elseif (config.eq.' + str(num_sol) + ') then \n'
345
346
347
348
349 tmp_text = self.write_channel_weight(self.unaligned_in_sol,self.unaligned,label)
350 write_text+=tmp_text
351 return write_text
352
353 - def create_MadWeight_main(self, full_sol_obj, num_sol):
354 """ create the main_code_$i.inc for all solution
355 and the associate d_choices(.f)(.inc)
356 """
357
358
359 ECS=full_sol_obj[0]
360 blob_sol_list=full_sol_obj[1]
361 self.num_fuse=self.ext_part + 3
362 self.fuse_dict={}
363 self.use_propa = set()
364
365 write_text=''
366
367
368
369
370 if num_sol == 1:
371 write_text += ''' if (config_pos.eq.1) then '''
372 else:
373 write_text += ' elseif (config_pos.eq.' + str(num_sol) + ') then '
374 write_text += '\n$B$ S-COMMENT_C $B$\n'
375 write_text += full_sol_obj[0].info()
376 write_text += '\n$E$ S-COMMENT_C $E$\n'
377
378
379
380 step=0
381 for blob_sol in blob_sol_list:
382
383 if len(blob_sol.step) == 1:
384 if blob_sol.step[0].chgt_var == '0':
385 continue
386 for block in blob_sol.step:
387 if blob_sol.step.index(block):
388 write_text += 'C ++++++++++++ \n'
389 step += 1
390 if block.chgt_var in ['1', '2', '3']:
391 block_name=' call fuse('
392 elif block.chgt_var == '0':
393 continue
394 else:
395 block_name=' call block_' + block.chgt_var.lower() + '(x,'
396
397
398 line=block_name
399 for particle in block.order_content:
400 if particle.MG < 0:
401 self.use_propa.add(particle.MG)
402 if block.chgt_var in ['D']:
403 line += self.write_d_choices(block.order_content)+' '
404 for particle in block.order_content:
405 if particle.MG < 0:
406 self.use_propa.add(particle.MG)
407 break
408 if type(particle.MG) == int:
409 line += str(particle.MG) + ','
410 elif isinstance(particle.MG, basestring):
411 if self.fuse_dict.has_key(particle.MG):
412 line += str(self.fuse_dict[particle.MG]) + ','
413 del self.fuse_dict[particle.MG]
414 else:
415 line += str(self.num_fuse) + ','
416 self.fuse_dict[particle.MG]=self.num_fuse
417 self.num_fuse += 1
418 line=line[:-1] + ')\n'
419 line=put_in_fortran_format(line)
420 write_text += line
421 if(block.chgt_var not in ['1', '2', '3']):
422 text=' if (jac.le.0d0) return\n'
423 else:
424 continue
425 write_text += put_in_fortran_format(text)
426
427
428
429
430
431
432
433 for block in ECS.step:
434 step += 1
435 if block.chgt_var == '2':
436 line=' call fuse('
437
438
439 else:
440 line=' call class_' + ECS.chgt_var.lower() + '(x,'
441 for particle in block.order_content:
442 if particle.MG < 0:
443 self.use_propa.add(particle.MG)
444 if type(particle.MG) == int:
445 line += str(particle.MG) + ','
446 elif isinstance(particle.MG, basestring):
447 if self.fuse_dict.has_key(particle.MG):
448 line += str(self.fuse_dict[particle.MG]) + ','
449 del self.fuse_dict[particle.MG]
450 else:
451 line += str(self.num_fuse) + ','
452 self.fuse_dict[particle.MG]=self.num_fuse
453 self.num_fuse += 1
454
455 line=line[:-1] + ')\n'
456 line=put_in_fortran_format(line)
457 write_text += line
458 if block.chgt_var not in ['1','2']:
459 text=' if (jac.le.0d0) return\n'
460 else:
461 text='\n'
462 write_text += put_in_fortran_format(text)
463
464 self.nb_block=step
465
466
467
468 out=self.check_invisible_decay()
469 if out:
470 write_text += '\n' + out
471
472
473
474 text = ''
475 for i in range(1, len(self.prop_content)):
476 pos = -1 * i
477 if pos not in self.use_propa:
478 for particle in self.prop_content:
479 if particle.channel.startswith('T'):
480 continue
481 if particle.MG == pos:
482 text += ' call fuse(%s,%s,%s)\n' %(particle.des[0].MG, particle.des[1].MG, pos)
483 break
484
485
486 text+='\n jac=jac*multi_channel_weight(%s)\n'%(num_sol)
487 write_text += put_in_fortran_format(text)
488 return write_text
489
491 """ create the data_$i.inc for all solution """
492
493
494
495
496
497 ECS=full_sol_obj[0]
498 blob_sol_list=full_sol_obj[1]
499 mapping = [0] * ((3*len(self.ext_content))+2)
500 m_random, p_random = 0, 0
501 var2mrandom = {'a':0,'b':1,'c':2,'d':4,'e':3,'f':2, 'g':2,
502 'A':3,'B':2,'C':1,'D':1,'E':2,
503 '0':0,'1':0,'2':0}
504
505
506
507 blob_sol=[]
508 for b_sol in blob_sol_list:
509 blob_sol += b_sol.step
510 write_text=''
511
512
513
514 write_text='\n$B$ S-COMMENT_C $B$\n'
515 write_text += full_sol_obj[0].info()
516 write_text += '\n$E$ S-COMMENT_C $E$\n'
517 num_vis=0
518 vis_str=''
519 vis_list=[]
520 part_treated = set()
521 ambiguous_external = set()
522 for block in ECS.step + blob_sol:
523 m_random += var2mrandom[block.chgt_var]
524 if block.chgt_var == '0':
525 particle = block.in_part[0]
526 if particle.external and not particle.neutrino:
527 ambiguous_external.add(particle.MG)
528 if mapping[3*particle.MG-7] == 0 and particle.tf_level:
529 mapping[3*particle.MG-7] = p_random+1
530 p_random += 1
531 continue
532 else:
533 [part_treated.add(part.MG) for part in block.in_part]
534
535 if block.chgt_var == 'e':
536 mapping[0] = p_random+1
537 p_random += 1
538 elif block.chgt_var in ['f','g']:
539 mapping[0] = p_random+1
540 mapping[1] = p_random+2
541 p_random += 2
542
543
544 if block.chgt_var == 'B':
545 neut = block.neut_content[0]
546 mapping[3*neut.MG-6] = p_random + 1
547 p_random +=1
548 elif block.chgt_var == 'C':
549 neut = block.neut_content[0]
550 mapping[3*neut.MG-6] = p_random + 1
551 mapping[3*neut.MG-5] = p_random + 2
552 p_random += 2
553
554 if block.chgt_var not in ['D', 'E', 'a', 'c']:
555 for particle in block.in_part:
556 if particle.external and not particle.neutrino:
557 if particle.MG not in vis_list:
558 num_vis += 1
559 vis_str += str(particle.MG) + ','
560 vis_list.append(particle.MG)
561 if mapping[3*particle.MG-7] == 0 and particle.tf_level:
562 mapping[3*particle.MG-7] = p_random+1
563 p_random += 1
564
565 elif block.chgt_var in ['E', 'c']:
566 if block.chgt_var == 'E':
567 particle=block.in_part[2]
568 elif block.chgt_var == 'c':
569 particle=block.in_part[1]
570 if particle.external and not particle.neutrino:
571 if particle.MG not in vis_list:
572 num_vis += 1
573 vis_str += str(particle.MG) + ','
574 vis_list.append(particle.MG)
575 if mapping[3*particle.MG-7] == 0 and particle.tf_level:
576 mapping[3*particle.MG-7] = p_random+1
577 p_random += 1
578 elif block.chgt_var in ['D']:
579 p1 = block.in_part[0]
580 p2 = block.in_part[1]
581 if hasattr(p1, 'tf_level') and hasattr(p2,'tf_level'):
582
583 if mapping[3*p1.MG-7] == 0 and p1.tf_level:
584 mapping[3*p1.MG-7] = p_random+1
585 if mapping[3*p2.MG-7] == 0 and p2.tf_level:
586 mapping[3*p2.MG-7] = p_random+1
587 p_random+=1
588
589
590 for particle in ambiguous_external:
591 if particle not in part_treated:
592
593 num_vis += 1
594 vis_str += str(particle) + ','
595 vis_list.append(particle)
596
597 text=' data num_vis(' + str(num_sol) + ') /' + str(num_vis) + '/\n'
598 if num_vis:
599 vis_list.sort()
600 vis_str=','.join([str(MG) for MG in vis_list])
601 text += ' data (vis_nb(label,' + str(num_sol) + '),label=1,' + str(num_vis) + ') /' + vis_str + '/\n'
602 text += ' data nb_block(' + str(num_sol) + ') / ' + str(self.nb_block) + '/\n'
603
604 for particle in self.ext_content:
605 if hasattr(particle,'has_theta_tf') and particle.has_theta_tf:
606 mapping[3*particle.MG-5] = p_random+1
607 p_random += 1
608 if hasattr(particle,'has_phi_tf') and particle.has_phi_tf:
609 mapping[3*particle.MG-6] = p_random+1
610 p_random += 1
611
612 if ECS.step[0].chgt_var == 'a':
613 for particle in ECS.step[0].in_part:
614 mapping[3*particle.MG-7] = p_random+1
615 p_random+=1
616
617 mapping = [str(i+m_random) if i else str(i) for i in mapping]
618 text += 'data (var2random(label, %(num_sol)s), label=1,%(size)s) / %(data)s/\n\n\n' % \
619 {'num_sol': num_sol, 'size':len(mapping),'data':','.join(mapping)}
620 write_text += put_in_fortran_format(text)
621
622
623
624
625
626 propa_list=self.collect_generated_propa(ECS, blob_sol_list)
627
628 text=' data num_propa(' + str(num_sol) + ') /' + str(len(propa_list)) + '/ \n'
629 if propa_list:
630 text += ' data (propa_cont(label,' + str(num_sol) + '),label=1,' + str(len(propa_list)) + ') /'
631 for particle in propa_list:
632 text += str(particle.MG) + ','
633 text=text[:-1] + '/\n'
634 else:
635 text += '\n$B$ S-COMMENT_C $B$\n No propagator aligned\n$E$ S-COMMENT_C $E$\n'
636
637 for i in range(0, len(propa_list)):
638 text += self.return_propa_generation(propa_list, i, num_sol)
639 text=put_in_fortran_format(text)
640 write_text += text
641
642 return write_text
643
644
645
646
647
648
649
650
651
652
653
654
655
656
658 """ check if this code is new or already defined """
659
660 for i in range(0, len(self.code)):
661 if self.code[i][0] == code[0]:
662 if self.code[i][1] == code[1]:
663 return 0
664 return 1
665
667 """ write the data_file and the main_code file """
668
669 self.close_d_choices_file(template)
670 self.check_redondant_peak(self.unaligned, self.unaligned_in_sol)
671
672 write_main=template.dico['INTRO_FOR_MAIN']
673 write_main += template.dico['START_ROUTINE']
674
675 write_data=template.dico['INTRO_FOR_DATA']
676 write_data += self.write_f77_parameter()
677 write_data += template.dico['COMMON_DEF']
678
679 write_mchannel=template.dico['INTRO_FOR_MULTICHANNEL']
680 write_mchannel+=self.def_text_for_channel_weight(self.unaligned)
681 for i in range(0, len(self.code)):
682 write_main += self.code[i][0].replace('elseif (config_pos.eq.1)','if (config_pos.eq.1)')
683 write_data += self.code[i][1]
684 write_mchannel += self.create_multi_channel_weight(i,self.sol_nb[i])
685 write_main += ' endif\n'
686 write_main += ' return\n'
687 write_main += ' end\n'
688
689
690
691
692 write_mchannel += template.dico['END_FOR_MULTICHANNEL']
693 write_mchannel= put_in_fortran_format(write_mchannel)
694
695
696 dico = {'nb_sol_config':len(self.code),
697 'values':[]}
698 if 'restrict_channel' in self.MWparam['mw_gen']:
699 if isinstance(self.MWparam['mw_gen']['restrict_channel'], list):
700 allowed_channel = [int(i) for i in self.MWparam['mw_gen']['restrict_channel']]
701 elif self.MWparam['mw_gen']['restrict_channel'] in ['','0','F']:
702 allowed_channel = range(1,len(self.allowed_channel)+1)
703 else:
704 allowed_channel = [int(self.MWparam['mw_gen']['restrict_channel'])]
705 full = allowed_channel + [0] * (len(self.code) - len(allowed_channel))
706 dico['values'] = ','.join(map(str, full))
707 else:
708 dico['values'] = ','.join(map(str, range(1, len(self.code)+1)))
709
710 write_data += put_in_fortran_format("""
711 C+-----------------------------------------------------------------------+
712 C| ORDERING OF THE CONFIGURATION |
713 C+-----------------------------------------------------------------------+
714 C| order from the most important to the least important |
715 C| 0 means that the configuration is bypassed |
716 C+-----------------------------------------------------------------------+
717 data (config_ordering(label),label=1,%(nb_sol_config)i) /%(values)s/
718 C+-----------------------------------------------------------------------+
719 """ % dico)
720
721
722 mod_file.mod_text(write_main, template.dico, self.directory + '/main_code.f')
723 mod_file.mod_text(write_data, template.dico, self.directory + '/data.inc')
724 mod_file.mod_text(write_mchannel, template.dico, self.directory + '/multi_channel.f')
725
726
727 self.write_permutations_file()
728
729
731 """ define the f77 parameter for the data file """
732
733
734
735 text = ' integer nb_vis_part\n'
736 text += ' parameter (nb_vis_part=' + str(len(self.ext_content) - self.num_neut) + ')\n'
737 text += ' integer nb_sol_config\n'
738 text += ' parameter (nb_sol_config=' + str(len(self.code)) + ')\n'
739 text += ' integer dim_phase_space\n parameter (dim_phase_space=%i)\n' % ((3*len(self.ext_content))+2)
740 text += ' integer nb_channel\n'
741 if self.MWparam['mw_perm']['montecarlo']:
742 text += ' parameter (nb_channel=%i)\n' % len(self.code)
743 else:
744 text += ' parameter (nb_channel=%i)\n' % (len(self.code) * 48)
745
746 text+=" integer config_ordering(nb_sol_config)\n "
747
748
749 text = put_in_fortran_format(text)
750 return text
751
752
754 """ updates/creates the files d_choices.inc, d_choices.f
755 return the three particle tag needed to call the block d
756 """
757
758 tag1 = listpart[0].MG
759 tag2 = listpart[1].MG
760 if tag1 > tag2:
761 tag1, tag2 = tag2, tag1
762
763 tag3 = listpart[2].MG
764 if tag1 < 0:
765 return '%s, %s, %s' % (tag2, tag1, tag3)
766
767
768 if 'first_d_' + str(tag1) + '_' + str(tag2) not in self.d_block:
769 self.d_block.append('first_d_' + str(tag1) + '_' + str(tag2))
770 self.d_block.append('second_d_' + str(tag1) + '_' + str(tag2))
771 else:
772 return 'first_d_' + str(tag1) + '_' + str(tag2) + ', second_d_' + str(tag1) + '_' + str(tag2) + ',' + str(tag3)
773
774
775 inc_text = '\n $B$ S-COMMENT_C $B$\n variable for block d containing:\n ' + \
776 str(tag1) + ' ' + str(tag2) + ' ' + str(tag3) + '\n$E$ S-COMMENT_C $E$\n'
777 inc_text += '\n integer first_d_' + str(tag1) + '_' + str(tag2) + '\n'
778 inc_text += '\n integer second_d_' + str(tag1) + '_' + str(tag2) + '\n'
779 inc_text = put_in_fortran_format(inc_text)
780 self.D_inc_text += inc_text
781
782
783 f_text = '\n $B$ S-COMMENT_C $B$\n variable for block d containing:\n ' + \
784 str(tag1) + ' ' + str(tag2) + ' ' + str(tag3) + '\n$E$ S-COMMENT_C $E$\n'
785 f_text += '\n call init_block_d_alignment(' + str(tag1) + ',' + str(tag2) + ',' + \
786 'first_d_' + str(tag1) + '_' + str(tag2) + ', second_d_' + str(tag1) + '_' + str(tag2) + ')\n'
787 f_text = put_in_fortran_format(f_text)
788 self.D_f_text += f_text
789
790 return 'first_d_' + str(tag1) + '_' + str(tag2) + ', second_d_' + str(tag1) + '_' + str(tag2) + ',' + str(tag3)
791
792
794 """ write the permutations.inc file """
795
796
797 pid_list = []
798 for i in range(3, 100):
799 if i not in self.content:
800 break
801 pid_list.append(self.content[i].pid)
802
803
804 permutations = get_perms_from_id(pid_list, self.MWparam['mw_perm']['bjet_is_jet'])
805
806
807
808 check = set([tuple(i) for i in permutations])
809 assert len(check) == len(permutations)
810 if not self.MWparam['mw_perm']['permutation']:
811 permutations = permutations[0:1]
812
813 text = open(self.directory + '/../permutation_template.f', 'r').read()
814
815 text += '\n subroutine get_perm(nb, perm)\n'
816 text += ' implicit none\n'
817 text += ' integer i,j\n'
818 text += ' include \'nexternal.inc\'\n'
819 text += ' INTEGER NB\n'
820 text += ' INTEGER PERM(NEXTERNAL-2)\n'
821 text += ' include \'permutation.inc\'\n'
822 text += ' INTEGER PERMS(NPERM, NEXTERNAL-2)\n'
823 for i, perm in enumerate(permutations):
824 text += " DATA (PERMS(%s,I),I=1,%s) /%s/\n" % (i+1, len(perm),
825 ','.join([str(j) for j in perm]))
826 text += ' do i=1, NEXTERNAL-2\n'
827 text += ' perm(i) = PERMS(nb, i)\n'
828 text += ' enddo\n'
829 text += ' return\n'
830 text += ' end\n\n'
831 text = put_in_fortran_format(text)
832 open(self.directory + '/permutation.f', 'w').write(text)
833
834
835 text = ' INTEGER NPERM\n'
836 text += ' PARAMETER (NPERM=%s)\n' % len(permutations)
837 text += ' include \'nb_tf.inc\'\n'
838 text += ' integer nb_channel2\n'
839 text += ' integer min_perm(%i)\n' % len(self.code)
840 if self.MWparam['mw_perm']['montecarlo']:
841 text += ' parameter (nb_channel2=%i)\n' % len(self.code)
842 else:
843 text += ' parameter (nb_channel2=%i)\n' % (len(self.code) * 48)
844
845 text += ''' double precision perm_value(NPERM, nb_tf)
846 double precision perm_error(NPERM,nb_tf)
847 double precision perm_value_it(NPERM, nb_tf)
848 double precision perm_error_it(NPERM, nb_tf)
849 double precision tf_value_it(nb_tf)
850 double precision tf_error_it(nb_tf)
851 integer curr_perm, nb_point_by_perm(NPERM), perm_order(NPERM,nb_channel2)
852 common/mw_perm_value/ perm_order,perm_value, perm_error, nb_point_by_perm, curr_perm, min_perm
853 common/mc_value_error/perm_value_it, perm_error_it, tf_value_it,tf_error_it
854 '''
855 text = put_in_fortran_format(text)
856 open(self.directory + '/permutation.inc', 'w').write(text)
857
858
859 template = """
860 C*********************************************************************
861 double precision function fct(x,wgt)
862 implicit none
863
864 include 'phasespace.inc'
865 include 'nexternal.inc'
866 include 'run.inc'
867 include 'coupl.inc'
868 include 'madweight_param.inc'
869 integer curr_tf
870 common/transfer_fct_curr_tf/curr_tf
871
872 c
873 c this is the function which is called by the integrator
874
875 c
876 c parameter
877 c
878 double precision pi
879 parameter (pi=3.141592653589793d0)
880 c
881 c arguments
882 c
883 double precision x(20),wgt
884 c
885 c local
886 c
887 c integer i,j ! debug mode
888 double precision twgt
889 integer new_perm
890 c
891 c global
892 c
893 double precision S,X1,X2,PSWGT,JAC
894 common /PHASESPACE/ S,X1,X2,PSWGT,JAC
895 double precision momenta(0:3,-max_branches:2*max_particles) ! momenta of external/intermediate legs (MG order)
896 double precision mvir2(-max_branches:2*max_particles) ! squared invariant masses of intermediate particles (MG order)
897 common /to_diagram_kin/ momenta, mvir2
898
899 include 'permutation.inc'
900
901 DOUBLE PRECISION Xl(20),XU(20),ACC
902 INTEGER NDIM,NCALL,ITMX,NPRN
903 COMMON/BVEG1/XL,XU,ACC, NDIM,NCALL,ITMX,NPRN
904 integer perm_id(nexternal-2) !permutation of 1,2,...,nexternal-2
905 C
906 C Keep track of whether cuts already calculated for this event
907 C
908 LOGICAL CUTSDONE,CUTSPASSED
909 COMMON/TO_CUTSDONE/CUTSDONE,CUTSPASSED
910 c
911 c external
912 c
913 double precision dsig
914 external dsig
915 double precision fct_before_tf, fct2
916 double precision alphas
917 external alphas
918 logical passcuts
919 external passcuts
920 include 'data.inc'
921
922 c choose the permutation (point by point in the ps)
923 curr_tf = 1
924 %(perm_init)s
925 nb_point_by_perm(curr_perm) = nb_point_by_perm(curr_perm) + 1
926 call get_PS_point(x)
927
928 if (jac.gt.0d0) then
929 %(use_cuts)s
930 %(jac_scaling)s
931 xbk(1)=X1
932 xbk(2)=X2
933 fct_before_tf=jac*dsig(momenta(0,1),wgt)
934
935 do curr_tf=1,nb_tf
936 call transfer_fct(momenta(0,1),TWGT)
937 if (curr_tf.eq.1)then
938 fct = fct_before_tf*twgt
939 fct2 = fct
940 else
941 fct2 = fct_before_tf*twgt
942 endif
943
944
945 %(histo)s
946 perm_value(curr_perm, curr_tf) = perm_value(curr_perm, curr_tf) + fct2*wgt
947 perm_error(curr_perm, curr_tf) = perm_error(curr_perm, curr_tf) + fct**2*wgt**2
948 enddo
949 else
950 fct=0d0
951 endif
952 curr_tf = 1
953
954 end
955 """
956
957 data = {'perm_init': '', 'perm_storing':'',
958 'histo':'', 'use_cuts':'', 'jac_scaling': ''}
959
960 if self.MWparam['mw_perm']['permutation'] and len(permutations) >1:
961 data['perm_init'] = """
962 new_perm = perm_order(min_perm(config_pos) + int(((NPERM - min_perm(config_pos) +1) * x(NDIM))), config_pos)
963 if (new_perm.ne.curr_perm) then
964 call get_perm(new_perm, perm_id)
965 call assign_perm(perm_id)
966 curr_perm = new_perm
967 endif
968 """
969 data['jac_scaling'] = """
970 jac = jac * (NPERM - min_perm(config_pos) +1)/NPERM
971 """
972 if not self.MWparam['mw_perm']['montecarlo'] and len(permutations) >1:
973 data['perm_init'] = ""
974
975 if self.MWparam['mw_run']['histo']:
976 data['histo'] = """
977 if (histo) then
978 call FILL_plot(fct,wgt,perm_pos*nb_sol_config+config_pos,nexternal)
979 endif
980 """
981
982 if self.MWparam['mw_run']['use_cut']:
983 data['use_cuts'] = """
984 CUTSPASSED=.FALSE.
985 CUTSDONE=.FALSE.
986 if (.not.passcuts(momenta(0,1))) then
987 fct = 0d0
988 return
989 endif
990 """
991 else:
992 data['use_cuts'] = """
993 if(.not.fixed_ren_scale) then
994 call set_ren_scale(momenta(0,1),scale)
995 if(scale.gt.0) G = SQRT(4d0*PI*ALPHAS(scale))
996 call UPDATE_AS_PARAM()
997 endif
998 if(.not.fixed_fac_scale) then
999 call set_fac_scale(momenta(0,1),q2fact)
1000 endif
1001 """
1002
1003 text = put_in_fortran_format(template % data)
1004 open(self.directory + '/main_code.f', 'a').write(text)
1005
1006
1008 """ write banner in the fortran/inc file """
1009
1010 self.d_block = []
1011 self.D_f_text = '$B$ INTRO_FOR_D_SWITCH_F $E$\n'
1012 self.D_inc_text = '$B$ INTRO_FOR_D_SWITCH_INC $E$\n'
1013 self.D_f_text += '\n subroutine init_d_assignement() \n include \'d_choices.inc\' \n'
1014
1016 """write the end of the D block related files """
1017
1018 text = '\n return \n end\n'
1019 text = put_in_fortran_format(text)
1020 self.D_f_text += text
1021
1022
1023 text = '\n$B$ S-COMMENT_C $B$\n Definition of the common\n$E$ S-COMMENT_C $E$\n'
1024 if self.d_block:
1025 text += '\n common/to_d_block/' + ','.join(self.d_block) + '\n'
1026 text = put_in_fortran_format(text)
1027 self.D_inc_text += text
1028
1029
1030 self.D_f_text = put_in_fortran_format(self.D_f_text)
1031 self.D_inc_text = put_in_fortran_format(self.D_inc_text)
1032 mod_file.mod_text(self.D_inc_text, template.dico, self.directory + '/d_choices.inc')
1033 mod_file.mod_text(self.D_f_text, template.dico, self.directory + '/d_choices.f')
1034
1036 """ return all the propagator that must be generated following BW distibution """
1037
1038 def id_from_plist(plist):
1039 return [particle.MG for particle in plist]
1040
1041 plist = []
1042 for particle in ECS.step[-1].order_content:
1043 if not particle.external and type(particle.MG) == int and \
1044 particle not in plist:
1045 if not particle in [b.main for b in ECS.blob_content if hasattr(b, 'main')]:
1046 plist.append(particle)
1047 for blob_sol in blob_sol_list:
1048 for block in blob_sol.step:
1049 if block.chgt_var in ['A', 'B', 'C', 'D', 'E']:
1050 for particle in block.order_content:
1051 if not particle.external and type(particle.MG) == int and \
1052 particle not in plist and particle not in block.in_part:
1053 plist.append(particle)
1054
1055
1056 list2 = []
1057 list3 = []
1058 while plist:
1059 propa = plist.pop()
1060 if propa.channel == 'S':
1061 list2.append(propa)
1062 else:
1063 list3.append(propa)
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073 return list2 + list3
1074
1076 """ first create for each solution a list of all unaligned peaks
1077 secondly make a full list for the full set of solution
1078 check if a specific peak is never aligned
1079 """
1080
1081 def add_peaks(unaligned, peak):
1082 """ add a peak in obj.unaligned """
1083
1084 if type(peak) == list:
1085 for one_peak in peak:
1086 add_peaks(unaligned, one_peak)
1087 return
1088
1089 if unaligned.has_key(peak):
1090 unaligned[peak] += 1
1091 else:
1092 if isinstance(peak, str) or peak.external:
1093 unaligned[peak] = 1
1094 elif isinstance(peak.MG, str):
1095 pass
1096 elif peak.external==0 and peak.channel.startswith('S'):
1097 unaligned[peak] = 1
1098
1099
1100
1101
1102 return
1103
1104 def print_(list_local):
1105 """ return a readable content of unaligned peak"""
1106 text=''
1107 if type(list_local)!=list:
1108 list_local=[list_local]
1109 for one_sol in list_local:
1110 for key in one_sol.keys():
1111 text+=str(key)+':'+str(one_sol[key])+'\n'
1112 text+='\n'
1113 return text
1114
1115
1116 if not hasattr(self,'unaligned'):
1117 self.unaligned = {}
1118 self.unaligned_in_sol = []
1119
1120 self.full_sol = []
1121
1122 for ECS in self.ECS_sol:
1123 full_solution_tag = [ECS, []]
1124 full_blob_sol = Multi_list()
1125 for BLOB in ECS.blob_content:
1126 full_blob_sol.append(BLOB.solution)
1127 full_blob_sol = full_blob_sol.give_combinaison()
1128 for one_full_solution in full_blob_sol:
1129 self.full_sol.append([ECS,one_full_solution])
1130 unaligned_in_this_sol = {}
1131 for block in ECS.step:
1132 add_peaks(unaligned_in_this_sol, block.unaligned)
1133 add_peaks(self.unaligned, block.unaligned)
1134 for blob in one_full_solution:
1135 for block in blob.step:
1136 add_peaks(unaligned_in_this_sol, block.unaligned)
1137 add_peaks(self.unaligned, block.unaligned)
1138 for particles in self.prop_content:
1139 if particles.channel == 'S_flat':
1140 add_peaks(unaligned_in_this_sol, particles)
1141 add_peaks(self.unaligned, particles)
1142 self.unaligned_in_sol.append(unaligned_in_this_sol)
1143
1144
1145
1147 """ correct self.unaligned from the fact that some solution was take into
1148 account more than once
1149 """
1150
1151 for i in self.already_existing_solution:
1152 for peak in self.unaligned_in_sol[i]:
1153 self.unaligned[peak] -= 1
1154
1155
1157 """return the line for the definition of how to generate the mass
1158 typical output are:
1159 data (propa_???($,label),label=1,$) /$,$,$,$,$,0/
1160 """
1161
1162
1163
1164 particle = list[pos]
1165 line1 = ' data (propa_max(' + str(pos + 1) + ',label,' + str(num_sol) + '),label=1,'
1166 line2 = ' data (propa_min(' + str(pos + 1) + ',label,' + str(num_sol) + '),label=1,'
1167 generated_mother = []
1168 generated_twin = []
1169 generated_son = []
1170 already_gen = list[:pos]
1171
1172 motherX = list[pos]
1173
1174 generated_son += self.already_generated_in_decay(motherX, already_gen)
1175 generated_son.append(0)
1176 while 1:
1177 motherXbut1 = motherX
1178 motherX = motherX.mother
1179 if motherX == 0:
1180 break
1181
1182 generated_twin += self.already_generated_in_decay(motherXbut1.twin, already_gen)
1183 if motherX in already_gen:
1184 generated_mother = [motherX.MG]
1185 generated_twin.append(0)
1186 break
1187 if not generated_mother:
1188 generated_mother = [0]
1189 generated_twin = []
1190
1191 gen = generated_mother + generated_twin
1192 line1 += str(len(gen)) + ') / '
1193 line2 += str(len(generated_son)) + ') / '
1194
1195 for MG_num in gen:
1196 line1 += str(MG_num) + ','
1197 line1 = line1[:-1] + '/\n'
1198
1199 for MG_num in generated_son:
1200 line2 += str(MG_num) + ','
1201 line2 = line2[:-1] + '/\n'
1202
1203 return line1 + line2
1204
1205
1206
1208 """give (recurently) all the first particle already generated in the branchs of desintegration"""
1209
1210 if particle.external:
1211 return [particle.MG]
1212 elif particle in generated_propa:
1213 return [particle.MG]
1214 else:
1215 part1 = self.already_generated_in_decay(particle.des[0], generated_propa)
1216 part2 = self.already_generated_in_decay(particle.des[1], generated_propa)
1217 return part1 + part2
1218
1220 """ check if one of the invisible particle decay in 2 invisible particle
1221 return 0 if not
1222 return a text with the call of the equivalent subroutine
1223 """
1224 decay_num = 0
1225 for particle in self.neut_content:
1226 if particle.external:
1227 continue
1228 decay_num += 1
1229 if not decay_num:
1230 out_text = self.template.comment_text('\t Invisible Propagator', 'C')
1231 text = ' decay(' + str(particle.MG) + ',' + str(particle.des[0].MG) + ',' + str(particle.des[1].MG) + ')'
1232
1233 out_text += put_in_fortran_format(text)
1234
1235 if decay_num:
1236 return out_text
1237 else:
1238 return 0
1239
1241 """ create output file containing the number of muon/electron/jet/bjet/invisible_part """
1242
1243
1244 content = self.output_type_info()
1245
1246 ff = open(self.directory + '/info_part.dat', 'w')
1247 text = ""
1248 for i in range(0, len(content)):
1249 text += '\t' + str(content[i])
1250 ff.writelines(text)
1251 ff.close()
1252
1254 """ check that in each solution each peaks appears at most one times and
1255 remove peaks present in all solution (if any)
1256 check also conflicts D/E peaks occur
1257 """
1258 list_d=[]
1259 dict_mg_to_peak={}
1260 for one_sol in list_local:
1261 local_mg={}
1262 for peak, value in one_sol.items():
1263 if isinstance(peak,basestring):
1264 value2=peak.split('_')[-2:]
1265 list_d.append(value2)
1266 else:
1267 dict_mg_to_peak[peak.MG]=peak
1268
1269 if value != 1:
1270 dict_all[peak] += 1 - value
1271 one_sol[peak] = 1
1272
1273 nb_sol = len(list_local)
1274 for peak, value in dict_all.items():
1275 if value == nb_sol:
1276 if isinstance(peak,basestring):
1277 print 'WARNING a peak associated to a visible particle is never '+ \
1278 'aligned. This will slow down the integration'
1279 elif peak.MG<0 and peak.external == 0 and peak.channel.startswith('S'):
1280 print 'WARNING a peak associated to '+str(peak.MG)+' is never '+ \
1281 'aligned. This will slow down the integration '
1282 dict_all[peak] = 0
1283 for list_peak in list_local:
1284 del list_peak[peak]
1285
1286 for peak1_MG,peak2_MG in list_d:
1287 try:
1288 peak1,peak2= dict_mg_to_peak[int(peak1_MG)],dict_mg_to_peak[int(peak2_MG)]
1289 except:
1290 continue
1291 for one_sol in list_local:
1292 if one_sol.has_key(peak1) and one_sol.has_key(peak2):
1293 del one_sol[peak1]
1294 del one_sol[peak2]
1295 name1, name2= 'first_d_%s_%s' % (peak1_MG,peak2_MG),'second_d_%s_%s' % (peak1_MG,peak2_MG)
1296 one_sol[name1] = 1
1297 one_sol[name2] = 1
1298 dict_all[peak1] -=1
1299 dict_all[peak2] -=1
1300 dict_all[name1] +=1
1301 if dict_all.has_key(name2):
1302 dict_all[name2] +=1
1303 else:
1304 dict_all[name2] =1
1305 return
1306
1307 if(__name__ == "__main__"):
1308 """ launched the generation """
1309 import MW_param
1310
1311 MW_param.go_to_main_dir()
1312 MW_opt = MW_param.MW_info('MadWeight_card.dat')
1313
1314 create_all_fortran_code(MW_opt)
1315