Package models :: Module model_reader
[hide private]
[frames] | no frames]

Source Code for Module models.model_reader

  1  ################################################################################ 
  2  # 
  3  # Copyright (c) 2010 The MadGraph5_aMC@NLO Development team and Contributors 
  4  # 
  5  # This file is a part of the MadGraph5_aMC@NLO project, an application which  
  6  # automatically generates Feynman diagrams and matrix elements for arbitrary 
  7  # high-energy processes in the Standard Model and beyond. 
  8  # 
  9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
 10  # distribution. 
 11  # 
 12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
 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  # Logger for model_reader 
 42  #=============================================================================== 
 43   
 44  logger = logging.getLogger('madgraph.models') 
 45   
 46  #=============================================================================== 
 47  # ModelReader: Used to read a param_card and calculate parameters and 
 48  #              couplings of the model. 
 49  #=============================================================================== 
50 -class ModelReader(loop_base_objects.LoopModel):
51 """Object to read all parameters and couplings of a model 52 """ 53
54 - def default_setup(self):
55 """The particles is changed to ParticleList""" 56 self['coupling_dict'] = {} 57 self['parameter_dict'] = {} 58 super(ModelReader, self).default_setup()
59
60 - def set_parameters_and_couplings(self, param_card = None, scale=None, 61 complex_mass_scheme=None, 62 auto_width=None):
63 """Read a param_card and calculate all parameters and 64 couplings. Set values directly in the parameters and 65 couplings, plus add new dictionary coupling_dict from 66 parameter name to value.""" 67 68 param_card_text = None 69 # Extract external parameters 70 external_parameters = self['parameters'][('external',)] 71 # Read in param_card 72 if param_card: 73 # Create a dictionary from LHA block name and code to parameter name 74 parameter_dict = {} 75 for param in external_parameters: 76 try: 77 dictionary = parameter_dict[param.lhablock.lower()] 78 except KeyError: 79 dictionary = {} 80 parameter_dict[param.lhablock.lower()] = dictionary 81 dictionary[tuple(param.lhacode)] = param 82 if isinstance(param_card, six.string_types): 83 # Check that param_card exists 84 if not os.path.isfile(param_card): 85 raise MadGraph5Error("No such file %s" % param_card) 86 param_card_text = param_card 87 param_card = card_reader.ParamCard(param_card) 88 for param in param_card.get('decay'): 89 if str(param.value).lower() == 'auto': 90 param.value = auto_width(param_card, param.lhacode) 91 #misc.sprint(type(param_card), card_reader.ParamCard, isinstance(param_card, card_reader.ParamCard)) 92 #assert isinstance(param_card, card_reader.ParamCard),'%s is not a ParamCard: %s' % (type(param_card), isinstance(param_card, card_reader.ParamCard)) 93 94 if complex_mass_scheme is None: 95 if aloha.complex_mass: 96 param_card.convert_to_complex_mass_scheme() 97 else: 98 if complex_mass_scheme: 99 param_card.convert_to_complex_mass_scheme() 100 101 key = [k for k in param_card.keys() if not k.startswith('qnumbers ') 102 and not k.startswith('decay_table') 103 and 'info' not in k] 104 105 if set(key) != set(parameter_dict.keys()): 106 # the two card are different. check if this critical 107 fail = True 108 missing_set = set(parameter_dict.keys()).difference(set(key)) 109 unknow_set = set(key).difference(set(parameter_dict.keys())) 110 missing_block = ','.join(missing_set) 111 unknow_block = ','.join(unknow_set) 112 113 114 msg = '''Invalid restriction card (not same block) 115 %s != %s. 116 Missing block: %s 117 Unknown block : %s''' % (set(key), set(parameter_dict.keys()), 118 missing_block, unknow_block) 119 apply_conversion = [] 120 121 if 'loop' in missing_set: 122 key.append('loop') 123 fail = False 124 125 if not missing_block: 126 logger.warning("Unknow type of information in the card: %s" % unknow_block) 127 fail = False 128 elif self['name'].startswith('mssm-') or self['name'] == 'mssm': 129 if not missing_set: 130 fail = False 131 else: 132 apply_conversion.append('to_slha2') 133 overwrite = False 134 elif missing_set == set(['fralpha']) and 'alpha' in unknow_set: 135 apply_conversion.append('alpha') 136 elif self.need_slha2(missing_set, unknow_set): 137 apply_conversion.append('to_slha2') 138 overwrite = True 139 140 if apply_conversion: 141 try: 142 if 'to_slha2' in apply_conversion: 143 if overwrite: 144 logger.error('Convention for the param_card seems to be wrong. Trying to automatically convert your file to SLHA2 format. \n'+\ 145 "Please check that the conversion occurs as expected (The converter is not fully general)") 146 import time 147 time.sleep(5) 148 149 param_card = param_card.input_path 150 param_card = card_reader.convert_to_mg5card(param_card, 151 writting=overwrite) 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 if 'alpha' in apply_conversion: 157 logger.info("Missing block fralpha but found a block alpha, apply automatic conversion") 158 param_card.rename_blocks({'alpha':'fralpha'}) 159 param_card['fralpha'].rename_keys({(): (1,)}) 160 param_card.write(param_card.input_path) 161 key = [k for k in param_card.keys() if not k.startswith('qnumbers ') 162 and not k.startswith('decay_table')] 163 if not set(parameter_dict.keys()).difference(set(key)): 164 fail = False 165 except Exception: 166 raise 167 raise MadGraph5Error(msg) 168 169 170 if fail: 171 raise MadGraph5Error(msg) 172 173 for block in key: 174 if block not in parameter_dict: 175 continue 176 for pid in parameter_dict[block]: 177 try: 178 value = param_card[block].get(pid).value 179 except: 180 if block == 'loop': 181 value = param_card['mass'].get(23).value 182 else: 183 raise MadGraph5Error('%s %s not define' % (block, pid)) 184 185 if isinstance(value, str) and value.lower() == 'auto': 186 value = '0.0' 187 if scale and parameter_dict[block][pid].name == 'aS': 188 runner = Alphas_Runner(value, nloop=2) 189 try: 190 value = runner(scale) 191 except ValueError as err: 192 if str(err) == 'math domain error' and scale < 1: 193 value = 0.0 194 else: 195 raise 196 except OverflowError as err: 197 if scale < 1: 198 value = 0.0 199 else: 200 raise 201 202 exec("locals()[\'%s\'] = %s" % (parameter_dict[block][pid].name, 203 value)) 204 parameter_dict[block][pid].value = float(value) 205 206 else: 207 # No param_card, use default values 208 for param in external_parameters: 209 if scale and parameter_dict[block][id].name == 'aS': 210 runner = Alphas_Runner(value, nloop=3) 211 value = runner(scale) 212 exec("locals()[\'%s\'] = %s" % (param.name, param.value)) 213 214 215 # Define all functions used 216 for func in self['functions']: 217 exec("def %s(%s):\n return %s" % (func.name, 218 ",".join(func.arguments), 219 func.expr)) 220 221 # Extract derived parameters 222 derived_parameters = [] 223 keys = [key for key in self['parameters'].keys() if \ 224 key != ('external',)] 225 keys.sort(key=len) 226 for key in keys: 227 derived_parameters += self['parameters'][key] 228 229 # Now calculate derived parameters 230 for param in derived_parameters: 231 try: 232 exec("locals()[\'%s\'] = %s" % (param.name, param.expr)) 233 except Exception as error: 234 msg = 'Unable to evaluate %s = %s: raise error: %s' % (param.name,param.expr, error) 235 raise MadGraph5Error(msg) 236 param.value = complex(eval(param.name)) 237 if not eval(param.name) and eval(param.name) != 0: 238 logger.warning("%s has no expression: %s" % (param.name, 239 param.expr)) 240 241 # Correct width sign for Majorana particles (where the width 242 # and mass need to have the same sign) 243 for particle in self.get('particles'): 244 if particle.is_fermion() and particle.get('self_antipart') and \ 245 particle.get('width').lower() != 'zero' and \ 246 eval(particle.get('mass')).real < 0: 247 exec("locals()[\'%(width)s\'] = -abs(%(width)s)" % \ 248 {'width': particle.get('width')}) 249 250 # Extract couplings 251 couplings = sum(list(self['couplings'].values()), []) 252 # Now calculate all couplings 253 for coup in couplings: 254 #print "I execute %s = %s"%(coup.name, coup.expr) 255 exec("locals()[\'%s\'] = %s" % (coup.name, coup.expr)) 256 coup.value = complex(eval(coup.name)) 257 if not eval(coup.name) and eval(coup.name) != 0: 258 logger.warning("%s has no expression: %s" % (coup.name, 259 coup.expr)) 260 261 # Set parameter and coupling dictionaries 262 self.set('parameter_dict', dict([(param.name, param.value) \ 263 for param in external_parameters + \ 264 derived_parameters])) 265 266 # Add "zero" 267 self.get('parameter_dict')['ZERO'] = complex(0.) 268 269 self.set('coupling_dict', dict([(coup.name, coup.value) \ 270 for coup in couplings])) 271 272 return locals()
273
274 - def get_mass(self, pdg_code):
275 """easy way to have access to a mass value""" 276 277 if isinstance(pdg_code, (int,str)): 278 return self.get('parameter_dict')[self.get_particle(pdg_code).get('mass')].real 279 else: 280 return self.get('parameter_dict')[pdg_code.get('mass')].real
281
282 - def get_width(self, pdg_code):
283 """easy way to have access to a width value""" 284 if isinstance(pdg_code, (int,str)): 285 return self.get('parameter_dict')[self.get_particle(pdg_code).get('width')].real 286 else: 287 return self.get('parameter_dict')[pdg_code.get('mass')].real
288
289 - def need_slha2(self, missing_set, unknow_set):
290 291 return all([b in missing_set for b in ['te','msl2','dsqmix','tu','selmix','msu2','msq2','usqmix','td', 'mse2','msd2']]) and\ 292 all(b in unknow_set for b in ['ae','ad','sbotmix','au','modsel','staumix','stopmix'])
293
294 -class Alphas_Runner(object):
295 """Evaluation of strong coupling constant alpha_S""" 296 # Author: Olivier Mattelaer translated from a fortran routine 297 # written by R. K. Ellis 298 # 299 # q -- scale at which alpha_s is to be evaluated 300 # 301 # asmz -- value of alpha_s at the mass of the Z-boson 302 # nloop -- the number of loops (1,2, or 3) at which beta 303 # 304 # function is evaluated to determine running. 305 # the values of the cmass and the bmass should be set 306 #--------------------------------------------------------------------------- 307
308 - def __init__(self, asmz, nloop, zmass=91.188, cmass=1.4, bmass=4.7):
309 310 self.asmz = asmz 311 self.nloop = nloop 312 self.zmass = zmass 313 self.cmass = cmass 314 self.bmass = bmass 315 316 assert asmz > 0 317 assert cmass > 0 318 assert bmass > 0 319 assert nloop > -1 320 t = 2 * math.log(bmass/zmass) 321 self.amb = self.newton1(t, asmz, 5) 322 t = 2 * math.log(cmass/bmass) 323 self.amc = self.newton1(t, self.amb, 4)
324
325 - def __call__(self, scale):
326 """Evaluation of strong coupling constant alpha_S at scale 'scale'.""" 327 assert scale > 0 328 329 330 if scale < 0.188775276209: 331 return 0 332 elif scale < self.cmass: 333 t = 2 * math.log(scale/self.cmass) 334 return self.newton1(t, self.amc, 3) 335 elif scale < self.bmass: 336 t = 2 * math.log(scale/self.bmass) 337 return self.newton1(t, self.amb, 4) 338 else: 339 t = 2 * math.log(scale/self.zmass) 340 return self.newton1(t, self.asmz, 5)
341 342 # B0=(11.-2.*NF/3.)/4./PI 343 b0 = [0.716197243913527, 0.66314559621623, 0.61009394851893] 344 # C1=(102.D0-38.D0/3.D0*NF)/4.D0/PI/(11.D0-2.D0/3.D0*NF) 345 c1 = [0.565884242104515, 0.49019722472304, 0.40134724779695] 346 # C2=(2857.D0/2.D0-5033*NF/18.D0+325*NF**2/54)/16.D0/PI**2/(11.D0-2.D0/3.D0*NF) 347 c2 = [0.453013579178645, 0.30879037953664, 0.14942733137107] 348 # DEL=SQRT(4*C2-C1**2) 349 d = [1.22140465909230, 0.99743079911360, 0.66077962451190] 350 351 352
353 - def newton1(self, t, alphas, nf):
354 """calculate a_out using nloop beta-function evolution 355 with nf flavours, given starting value as-in 356 given alphas and logarithmic separation between 357 input scale and output scale t. 358 Evolution is performed using Newton's method, 359 with a precision given by tol.""" 360 nloop = self.nloop 361 tol = 5e-4 362 arg = nf-3 363 b0, c1, c2, d = self.b0[arg], self.c1[arg], self.c2[arg], self.d[arg] 364 365 if nloop == 2: 366 f = lambda AS: 1.0/AS+c1*math.log((c1*AS)/(1+c1*AS)) 367 elif nloop == 3: 368 f = lambda AS: 1.0/AS+0.5*c1*math.log((c2*AS**2)/(1+c1*AS+c2*AS**2)) \ 369 -(c1**2-2*c2)/d*math.atan((2*c2*AS+c1)/d) 370 371 a_out = alphas / (1 + alphas * b0 * t) 372 if nloop == 1: 373 return a_out 374 375 a_out = alphas/(1+b0*alphas*t+c1*alphas*math.log(1+alphas*b0*t)) 376 if a_out < 0: 377 a_out = 0.3 378 379 while 1: 380 AS = a_out 381 F = b0 * t + f(alphas) -f(AS) 382 if nloop == 2: 383 FP=1/(AS**2*(1+c1*AS)) 384 elif nloop == 3: 385 FP=1/(AS**2*(1+c1*AS + c2 * AS**2)) 386 if FP == 0: 387 return AS 388 a_out = AS - F/FP 389 delta = abs(F/FP/AS) 390 if delta < tol: 391 break 392 return a_out
393