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