1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """Module to allow reading a param_card and setting all parameters and
16 couplings for a model"""
17
18 from __future__ import division
19
20 import array
21 import cmath
22 import copy
23 import itertools
24 import logging
25 import math
26 import os
27 import re
28 import aloha
29
30 import madgraph.core.base_objects as base_objects
31 import madgraph.loop.loop_base_objects as loop_base_objects
32 import models.check_param_card as card_reader
33 from madgraph import MadGraph5Error, MG5DIR
34 import madgraph.various.misc as misc
35
36 ZERO = 0
37
38
39
40
41
42 logger = logging.getLogger('madgraph.models')
43
44
45
46
47
49 """Object to read all parameters and couplings of a model
50 """
51
53 """The particles is changed to ParticleList"""
54 self['coupling_dict'] = {}
55 self['parameter_dict'] = {}
56 super(ModelReader, self).default_setup()
57
60 """Read a param_card and calculate all parameters and
61 couplings. Set values directly in the parameters and
62 couplings, plus add new dictionary coupling_dict from
63 parameter name to value."""
64
65 param_card_text = None
66
67 external_parameters = self['parameters'][('external',)]
68
69 if param_card:
70
71 parameter_dict = {}
72 for param in external_parameters:
73 try:
74 dictionary = parameter_dict[param.lhablock.lower()]
75 except KeyError:
76 dictionary = {}
77 parameter_dict[param.lhablock.lower()] = dictionary
78 dictionary[tuple(param.lhacode)] = param
79 if isinstance(param_card, basestring):
80
81 if not os.path.isfile(param_card):
82 raise MadGraph5Error, "No such file %s" % param_card
83 param_card_text = param_card
84 param_card = card_reader.ParamCard(param_card)
85
86
87
88 if complex_mass_scheme is None:
89 if aloha.complex_mass:
90 param_card.convert_to_complex_mass_scheme()
91 else:
92 if complex_mass_scheme:
93 param_card.convert_to_complex_mass_scheme()
94
95 key = [k for k in param_card.keys() if not k.startswith('qnumbers ')
96 and not k.startswith('decay_table')
97 and 'info' not in k]
98 param_key = [k for k in parameter_dict.keys() if 'info' not in k]
99
100 if set(key) != set(parameter_dict.keys()):
101
102 fail = True
103 missing_set = set(parameter_dict.keys()).difference(set(key))
104 unknow_set = set(key).difference(set(parameter_dict.keys()))
105 missing_block = ','.join(missing_set)
106 unknow_block = ','.join(unknow_set)
107
108
109 msg = '''Invalid restriction card (not same block)
110 %s != %s.
111 Missing block: %s
112 Unknown block : %s''' % (set(key), set(parameter_dict.keys()),
113 missing_block, unknow_block)
114 apply_conversion = []
115
116 if not missing_block:
117 logger.warning("Unknow type of information in the card: %s" % unknow_block)
118 fail = False
119 elif self['name'].startswith('mssm-') or self['name'] == 'mssm':
120 if not missing_set:
121 fail = False
122 else:
123 apply_conversion.append('to_slha2')
124 overwrite = False
125 elif missing_set == set(['fralpha']) and 'alpha' in unknow_set:
126 apply_conversion.append('alpha')
127 elif self.need_slha2(missing_set, unknow_set):
128 apply_conversion.append('to_slha2')
129 overwrite = True
130
131 if apply_conversion:
132 try:
133 if 'to_slha2' in apply_conversion:
134 if overwrite:
135 logger.error('Convention for the param_card seems to be wrong. Trying to automatically convert your file to SLHA2 format. \n'+\
136 "Please check that the conversion occurs as expected (The converter is not fully general)")
137 import time
138 time.sleep(5)
139
140 param_card = param_card.input_path
141 param_card = card_reader.convert_to_mg5card(param_card,
142 writting=overwrite)
143 key = [k for k in param_card.keys() if not k.startswith('qnumbers ')
144 and not k.startswith('decay_table')]
145 if not set(parameter_dict.keys()).difference(set(key)):
146 fail = False
147 if 'alpha' in apply_conversion:
148 logger.info("Missing block fralpha but found a block alpha, apply automatic conversion")
149 param_card.rename_blocks({'alpha':'fralpha'})
150 param_card['fralpha'].rename_keys({(): (1,)})
151 param_card.write(param_card.input_path)
152 key = [k for k in param_card.keys() if not k.startswith('qnumbers ')
153 and not k.startswith('decay_table')]
154 if not set(parameter_dict.keys()).difference(set(key)):
155 fail = False
156 except Exception:
157 raise
158 raise MadGraph5Error, msg
159
160
161 if fail:
162 raise MadGraph5Error, msg
163
164 for block in key:
165 if block not in parameter_dict:
166 continue
167 for pid in parameter_dict[block]:
168 try:
169 value = param_card[block].get(pid).value
170 except:
171 raise MadGraph5Error, '%s %s not define' % (block, pid)
172 else:
173 if isinstance(value, str) and value.lower() == 'auto':
174 value = '0.0'
175 if scale and parameter_dict[block][pid].name == 'aS':
176 runner = Alphas_Runner(value, nloop=2)
177 value = runner(scale)
178 exec("locals()[\'%s\'] = %s" % (parameter_dict[block][pid].name,
179 value))
180 parameter_dict[block][pid].value = float(value)
181
182 else:
183
184 for param in external_parameters:
185 if scale and parameter_dict[block][id].name == 'aS':
186 runner = Alphas_Runner(value, nloop=3)
187 value = runner(scale)
188 exec("locals()[\'%s\'] = %s" % (param.name, param.value))
189
190
191
192 for func in self['functions']:
193 exec("def %s(%s):\n return %s" % (func.name,
194 ",".join(func.arguments),
195 func.expr))
196
197
198 derived_parameters = []
199 keys = [key for key in self['parameters'].keys() if \
200 key != ('external',)]
201 keys.sort(key=len)
202 for key in keys:
203 derived_parameters += self['parameters'][key]
204
205
206 for param in derived_parameters:
207 try:
208 exec("locals()[\'%s\'] = %s" % (param.name, param.expr))
209 except Exception as error:
210 msg = 'Unable to evaluate %s = %s: raise error: %s' % (param.name,param.expr, error)
211 raise MadGraph5Error, msg
212 param.value = complex(eval(param.name))
213 if not eval(param.name) and eval(param.name) != 0:
214 logger.warning("%s has no expression: %s" % (param.name,
215 param.expr))
216
217
218
219 for particle in self.get('particles'):
220 if particle.is_fermion() and particle.get('self_antipart') and \
221 particle.get('width').lower() != 'zero' and \
222 eval(particle.get('mass')).real < 0:
223 exec("locals()[\'%(width)s\'] = -abs(%(width)s)" % \
224 {'width': particle.get('width')})
225
226
227 couplings = sum(self['couplings'].values(), [])
228
229 for coup in couplings:
230
231 exec("locals()[\'%s\'] = %s" % (coup.name, coup.expr))
232 coup.value = complex(eval(coup.name))
233 if not eval(coup.name) and eval(coup.name) != 0:
234 logger.warning("%s has no expression: %s" % (coup.name,
235 coup.expr))
236
237
238 self.set('parameter_dict', dict([(param.name, param.value) \
239 for param in external_parameters + \
240 derived_parameters]))
241
242
243 self.get('parameter_dict')['ZERO'] = complex(0.)
244
245 self.set('coupling_dict', dict([(coup.name, coup.value) \
246 for coup in couplings]))
247
248 return locals()
249
251 """easy way to have access to a mass value"""
252
253 if isinstance(pdg_code, (int,str)):
254 return self.get('parameter_dict')[self.get_particle(pdg_code).get('mass')].real
255 else:
256 return self.get('parameter_dict')[pdg_code.get('mass')].real
257
259 """easy way to have access to a width value"""
260 if isinstance(pdg_code, (int,str)):
261 return self.get('parameter_dict')[self.get_particle(pdg_code).get('width')].real
262 else:
263 return self.get('parameter_dict')[pdg_code.get('mass')].real
264
266
267 return all([b in missing_set for b in ['te','msl2','dsqmix','tu','selmix','msu2','msq2','usqmix','td', 'mse2','msd2']]) and\
268 all(b in unknow_set for b in ['ae','ad','sbotmix','au','modsel','staumix','stopmix'])
269
271 """Evaluation of strong coupling constant alpha_S"""
272
273
274
275
276
277
278
279
280
281
282
283
284 - def __init__(self, asmz, nloop, zmass=91.188, cmass=1.4, bmass=4.7):
285
286 self.asmz = asmz
287 self.nloop = nloop
288 self.zmass = zmass
289 self.cmass = cmass
290 self.bmass = bmass
291
292 assert asmz > 0
293 assert cmass > 0
294 assert bmass > 0
295 assert nloop > -1
296 t = 2 * math.log(bmass/zmass)
297 self.amb = self.newton1(t, asmz, 5)
298 t = 2 * math.log(cmass/bmass)
299 self.amc = self.newton1(t, self.amb, 4)
300
302 """Evaluation of strong coupling constant alpha_S at scale 'scale'."""
303 assert scale > 0
304
305
306 if scale < 0.188775276209:
307 return 0
308 elif scale < self.cmass:
309 t = 2 * math.log(scale/self.cmass)
310 return self.newton1(t, self.amc, 3)
311 elif scale < self.bmass:
312 t = 2 * math.log(scale/self.bmass)
313 return self.newton1(t, self.amb, 4)
314 else:
315 t = 2 * math.log(scale/self.zmass)
316 return self.newton1(t, self.asmz, 5)
317
318
319 b0 = [0.716197243913527, 0.66314559621623, 0.61009394851893]
320
321 c1 = [0.565884242104515, 0.49019722472304, 0.40134724779695]
322
323 c2 = [0.453013579178645, 0.30879037953664, 0.14942733137107]
324
325 d = [1.22140465909230, 0.99743079911360, 0.66077962451190]
326
327
328
330 """calculate a_out using nloop beta-function evolution
331 with nf flavours, given starting value as-in
332 given alphas and logarithmic separation between
333 input scale and output scale t.
334 Evolution is performed using Newton's method,
335 with a precision given by tol."""
336 nloop = self.nloop
337 tol = 5e-4
338 arg = nf-3
339 b0, c1, c2, d = self.b0[arg], self.c1[arg], self.c2[arg], self.d[arg]
340
341 if nloop == 2:
342 f = lambda AS: 1.0/AS+c1*math.log((c1*AS)/(1+c1*AS))
343 elif nloop == 3:
344 f = lambda AS: 1.0/AS+0.5*c1*math.log((c2*AS**2)/(1+c1*AS+c2*AS**2)) \
345 -(c1**2-2*c2)/d*math.atan((2*c2*AS+c1)/d)
346
347 a_out = alphas / (1 + alphas * b0 * t)
348 if nloop == 1:
349 return a_out
350
351 a_out = alphas/(1+b0*alphas*t+c1*alphas*math.log(1+alphas*b0*t))
352 if a_out < 0:
353 a_out = 0.3
354
355 while 1:
356 AS = a_out
357 F = b0 * t + f(alphas) -f(AS)
358 if nloop == 2:
359 FP=1/(AS**2*(1+c1*AS))
360 elif nloop == 3:
361 FP=1/(AS**2*(1+c1*AS + c2 * AS**2))
362 if FP == 0:
363 return AS
364 a_out = AS - F/FP
365 delta = abs(F/FP/AS)
366 if delta < tol:
367 break
368 return a_out
369