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  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  # Logger for model_reader 
 40  #=============================================================================== 
 41   
 42  logger = logging.getLogger('madgraph.models') 
 43   
 44  #=============================================================================== 
 45  # ModelReader: Used to read a param_card and calculate parameters and 
 46  #              couplings of the model. 
 47  #=============================================================================== 
48 -class ModelReader(loop_base_objects.LoopModel):
49 """Object to read all parameters and couplings of a model 50 """ 51
52 - def default_setup(self):
53 """The particles is changed to ParticleList""" 54 self['coupling_dict'] = {} 55 self['parameter_dict'] = {} 56 super(ModelReader, self).default_setup()
57
58 - def set_parameters_and_couplings(self, param_card = None, scale=None, 59 complex_mass_scheme=None):
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 # Extract external parameters 67 external_parameters = self['parameters'][('external',)] 68 # Read in param_card 69 if param_card: 70 # Create a dictionary from LHA block name and code to parameter name 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 # Check that param_card exists 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 #misc.sprint(type(param_card), card_reader.ParamCard, isinstance(param_card, card_reader.ParamCard)) 86 #assert isinstance(param_card, card_reader.ParamCard),'%s is not a ParamCard: %s' % (type(param_card), isinstance(param_card, card_reader.ParamCard)) 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 # the two card are different. check if this critical 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 try: 178 value = runner(scale) 179 except ValueError, err: 180 if str(err) == 'math domain error' and scale < 1: 181 value = 0.0 182 else: 183 raise 184 except OverflowError, err: 185 if scale < 1: 186 value = 0.0 187 else: 188 raise 189 exec("locals()[\'%s\'] = %s" % (parameter_dict[block][pid].name, 190 value)) 191 parameter_dict[block][pid].value = float(value) 192 193 else: 194 # No param_card, use default values 195 for param in external_parameters: 196 if scale and parameter_dict[block][id].name == 'aS': 197 runner = Alphas_Runner(value, nloop=3) 198 value = runner(scale) 199 exec("locals()[\'%s\'] = %s" % (param.name, param.value)) 200 201 202 # Define all functions used 203 for func in self['functions']: 204 exec("def %s(%s):\n return %s" % (func.name, 205 ",".join(func.arguments), 206 func.expr)) 207 208 # Extract derived parameters 209 derived_parameters = [] 210 keys = [key for key in self['parameters'].keys() if \ 211 key != ('external',)] 212 keys.sort(key=len) 213 for key in keys: 214 derived_parameters += self['parameters'][key] 215 216 # Now calculate derived parameters 217 for param in derived_parameters: 218 try: 219 exec("locals()[\'%s\'] = %s" % (param.name, param.expr)) 220 except Exception as error: 221 msg = 'Unable to evaluate %s = %s: raise error: %s' % (param.name,param.expr, error) 222 raise MadGraph5Error, msg 223 param.value = complex(eval(param.name)) 224 if not eval(param.name) and eval(param.name) != 0: 225 logger.warning("%s has no expression: %s" % (param.name, 226 param.expr)) 227 228 # Correct width sign for Majorana particles (where the width 229 # and mass need to have the same sign) 230 for particle in self.get('particles'): 231 if particle.is_fermion() and particle.get('self_antipart') and \ 232 particle.get('width').lower() != 'zero' and \ 233 eval(particle.get('mass')).real < 0: 234 exec("locals()[\'%(width)s\'] = -abs(%(width)s)" % \ 235 {'width': particle.get('width')}) 236 237 # Extract couplings 238 couplings = sum(self['couplings'].values(), []) 239 # Now calculate all couplings 240 for coup in couplings: 241 #print "I execute %s = %s"%(coup.name, coup.expr) 242 exec("locals()[\'%s\'] = %s" % (coup.name, coup.expr)) 243 coup.value = complex(eval(coup.name)) 244 if not eval(coup.name) and eval(coup.name) != 0: 245 logger.warning("%s has no expression: %s" % (coup.name, 246 coup.expr)) 247 248 # Set parameter and coupling dictionaries 249 self.set('parameter_dict', dict([(param.name, param.value) \ 250 for param in external_parameters + \ 251 derived_parameters])) 252 253 # Add "zero" 254 self.get('parameter_dict')['ZERO'] = complex(0.) 255 256 self.set('coupling_dict', dict([(coup.name, coup.value) \ 257 for coup in couplings])) 258 259 return locals()
260
261 - def get_mass(self, pdg_code):
262 """easy way to have access to a mass value""" 263 264 if isinstance(pdg_code, (int,str)): 265 return self.get('parameter_dict')[self.get_particle(pdg_code).get('mass')].real 266 else: 267 return self.get('parameter_dict')[pdg_code.get('mass')].real
268
269 - def get_width(self, pdg_code):
270 """easy way to have access to a width value""" 271 if isinstance(pdg_code, (int,str)): 272 return self.get('parameter_dict')[self.get_particle(pdg_code).get('width')].real 273 else: 274 return self.get('parameter_dict')[pdg_code.get('mass')].real
275
276 - def need_slha2(self, missing_set, unknow_set):
277 278 return all([b in missing_set for b in ['te','msl2','dsqmix','tu','selmix','msu2','msq2','usqmix','td', 'mse2','msd2']]) and\ 279 all(b in unknow_set for b in ['ae','ad','sbotmix','au','modsel','staumix','stopmix'])
280
281 -class Alphas_Runner(object):
282 """Evaluation of strong coupling constant alpha_S""" 283 # Author: Olivier Mattelaer translated from a fortran routine 284 # written by R. K. Ellis 285 # 286 # q -- scale at which alpha_s is to be evaluated 287 # 288 # asmz -- value of alpha_s at the mass of the Z-boson 289 # nloop -- the number of loops (1,2, or 3) at which beta 290 # 291 # function is evaluated to determine running. 292 # the values of the cmass and the bmass should be set 293 #--------------------------------------------------------------------------- 294
295 - def __init__(self, asmz, nloop, zmass=91.188, cmass=1.4, bmass=4.7):
296 297 self.asmz = asmz 298 self.nloop = nloop 299 self.zmass = zmass 300 self.cmass = cmass 301 self.bmass = bmass 302 303 assert asmz > 0 304 assert cmass > 0 305 assert bmass > 0 306 assert nloop > -1 307 t = 2 * math.log(bmass/zmass) 308 self.amb = self.newton1(t, asmz, 5) 309 t = 2 * math.log(cmass/bmass) 310 self.amc = self.newton1(t, self.amb, 4)
311
312 - def __call__(self, scale):
313 """Evaluation of strong coupling constant alpha_S at scale 'scale'.""" 314 assert scale > 0 315 316 317 if scale < 0.188775276209: 318 return 0 319 elif scale < self.cmass: 320 t = 2 * math.log(scale/self.cmass) 321 return self.newton1(t, self.amc, 3) 322 elif scale < self.bmass: 323 t = 2 * math.log(scale/self.bmass) 324 return self.newton1(t, self.amb, 4) 325 else: 326 t = 2 * math.log(scale/self.zmass) 327 return self.newton1(t, self.asmz, 5)
328 329 # B0=(11.-2.*NF/3.)/4./PI 330 b0 = [0.716197243913527, 0.66314559621623, 0.61009394851893] 331 # C1=(102.D0-38.D0/3.D0*NF)/4.D0/PI/(11.D0-2.D0/3.D0*NF) 332 c1 = [0.565884242104515, 0.49019722472304, 0.40134724779695] 333 # C2=(2857.D0/2.D0-5033*NF/18.D0+325*NF**2/54)/16.D0/PI**2/(11.D0-2.D0/3.D0*NF) 334 c2 = [0.453013579178645, 0.30879037953664, 0.14942733137107] 335 # DEL=SQRT(4*C2-C1**2) 336 d = [1.22140465909230, 0.99743079911360, 0.66077962451190] 337 338 339
340 - def newton1(self, t, alphas, nf):
341 """calculate a_out using nloop beta-function evolution 342 with nf flavours, given starting value as-in 343 given alphas and logarithmic separation between 344 input scale and output scale t. 345 Evolution is performed using Newton's method, 346 with a precision given by tol.""" 347 nloop = self.nloop 348 tol = 5e-4 349 arg = nf-3 350 b0, c1, c2, d = self.b0[arg], self.c1[arg], self.c2[arg], self.d[arg] 351 352 if nloop == 2: 353 f = lambda AS: 1.0/AS+c1*math.log((c1*AS)/(1+c1*AS)) 354 elif nloop == 3: 355 f = lambda AS: 1.0/AS+0.5*c1*math.log((c2*AS**2)/(1+c1*AS+c2*AS**2)) \ 356 -(c1**2-2*c2)/d*math.atan((2*c2*AS+c1)/d) 357 358 a_out = alphas / (1 + alphas * b0 * t) 359 if nloop == 1: 360 return a_out 361 362 a_out = alphas/(1+b0*alphas*t+c1*alphas*math.log(1+alphas*b0*t)) 363 if a_out < 0: 364 a_out = 0.3 365 366 while 1: 367 AS = a_out 368 F = b0 * t + f(alphas) -f(AS) 369 if nloop == 2: 370 FP=1/(AS**2*(1+c1*AS)) 371 elif nloop == 3: 372 FP=1/(AS**2*(1+c1*AS + c2 * AS**2)) 373 if FP == 0: 374 return AS 375 a_out = AS - F/FP 376 delta = abs(F/FP/AS) 377 if delta < tol: 378 break 379 return a_out
380