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