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