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 99 if set(key) != set(parameter_dict.keys()): 100 # the two card are different. check if this critical 101 fail = True 102 missing_set = set(parameter_dict.keys()).difference(set(key)) 103 unknow_set = set(key).difference(set(parameter_dict.keys())) 104 missing_block = ','.join(missing_set) 105 unknow_block = ','.join(unknow_set) 106 107 108 msg = '''Invalid restriction card (not same block) 109 %s != %s. 110 Missing block: %s 111 Unknown block : %s''' % (set(key), set(parameter_dict.keys()), 112 missing_block, unknow_block) 113 apply_conversion = [] 114 115 if not missing_block: 116 logger.warning("Unknow type of information in the card: %s" % unknow_block) 117 fail = False 118 elif self['name'].startswith('mssm-') or self['name'] == 'mssm': 119 if not missing_set: 120 fail = False 121 else: 122 apply_conversion.append('to_slha2') 123 overwrite = False 124 elif missing_set == set(['fralpha']) and 'alpha' in unknow_set: 125 apply_conversion.append('alpha') 126 elif self.need_slha2(missing_set, unknow_set): 127 apply_conversion.append('to_slha2') 128 overwrite = True 129 130 if apply_conversion: 131 try: 132 if 'to_slha2' in apply_conversion: 133 if overwrite: 134 logger.error('Convention for the param_card seems to be wrong. Trying to automatically convert your file to SLHA2 format. \n'+\ 135 "Please check that the conversion occurs as expected (The converter is not fully general)") 136 import time 137 time.sleep(5) 138 139 param_card = param_card.input_path 140 param_card = card_reader.convert_to_mg5card(param_card, 141 writting=overwrite) 142 key = [k for k in param_card.keys() if not k.startswith('qnumbers ') 143 and not k.startswith('decay_table')] 144 if not set(parameter_dict.keys()).difference(set(key)): 145 fail = False 146 if 'alpha' in apply_conversion: 147 logger.info("Missing block fralpha but found a block alpha, apply automatic conversion") 148 param_card.rename_blocks({'alpha':'fralpha'}) 149 param_card['fralpha'].rename_keys({(): (1,)}) 150 param_card.write(param_card.input_path) 151 key = [k for k in param_card.keys() if not k.startswith('qnumbers ') 152 and not k.startswith('decay_table')] 153 if not set(parameter_dict.keys()).difference(set(key)): 154 fail = False 155 except Exception: 156 raise 157 raise MadGraph5Error, msg 158 159 160 if fail: 161 raise MadGraph5Error, msg 162 163 for block in key: 164 if block not in parameter_dict: 165 continue 166 for pid in parameter_dict[block]: 167 try: 168 value = param_card[block].get(pid).value 169 except: 170 raise MadGraph5Error, '%s %s not define' % (block, pid) 171 else: 172 if isinstance(value, str) and value.lower() == 'auto': 173 value = '0.0' 174 if scale and parameter_dict[block][pid].name == 'aS': 175 runner = Alphas_Runner(value, nloop=2) 176 try: 177 value = runner(scale) 178 except ValueError, err: 179 if str(err) == 'math domain error' and scale < 1: 180 value = 0.0 181 else: 182 raise 183 exec("locals()[\'%s\'] = %s" % (parameter_dict[block][pid].name, 184 value)) 185 parameter_dict[block][pid].value = float(value) 186 187 else: 188 # No param_card, use default values 189 for param in external_parameters: 190 if scale and parameter_dict[block][id].name == 'aS': 191 runner = Alphas_Runner(value, nloop=3) 192 value = runner(scale) 193 exec("locals()[\'%s\'] = %s" % (param.name, param.value)) 194 195 196 # Define all functions used 197 for func in self['functions']: 198 exec("def %s(%s):\n return %s" % (func.name, 199 ",".join(func.arguments), 200 func.expr)) 201 202 # Extract derived parameters 203 derived_parameters = [] 204 keys = [key for key in self['parameters'].keys() if \ 205 key != ('external',)] 206 keys.sort(key=len) 207 for key in keys: 208 derived_parameters += self['parameters'][key] 209 210 # Now calculate derived parameters 211 for param in derived_parameters: 212 try: 213 exec("locals()[\'%s\'] = %s" % (param.name, param.expr)) 214 except Exception as error: 215 msg = 'Unable to evaluate %s = %s: raise error: %s' % (param.name,param.expr, error) 216 raise MadGraph5Error, msg 217 param.value = complex(eval(param.name)) 218 if not eval(param.name) and eval(param.name) != 0: 219 logger.warning("%s has no expression: %s" % (param.name, 220 param.expr)) 221 222 # Correct width sign for Majorana particles (where the width 223 # and mass need to have the same sign) 224 for particle in self.get('particles'): 225 if particle.is_fermion() and particle.get('self_antipart') and \ 226 particle.get('width').lower() != 'zero' and \ 227 eval(particle.get('mass')).real < 0: 228 exec("locals()[\'%(width)s\'] = -abs(%(width)s)" % \ 229 {'width': particle.get('width')}) 230 231 # Extract couplings 232 couplings = sum(self['couplings'].values(), []) 233 # Now calculate all couplings 234 for coup in couplings: 235 #print "I execute %s = %s"%(coup.name, coup.expr) 236 exec("locals()[\'%s\'] = %s" % (coup.name, coup.expr)) 237 coup.value = complex(eval(coup.name)) 238 if not eval(coup.name) and eval(coup.name) != 0: 239 logger.warning("%s has no expression: %s" % (coup.name, 240 coup.expr)) 241 242 # Set parameter and coupling dictionaries 243 self.set('parameter_dict', dict([(param.name, param.value) \ 244 for param in external_parameters + \ 245 derived_parameters])) 246 247 # Add "zero" 248 self.get('parameter_dict')['ZERO'] = complex(0.) 249 250 self.set('coupling_dict', dict([(coup.name, coup.value) \ 251 for coup in couplings])) 252 253 return locals()
254
255 - def get_mass(self, pdg_code):
256 """easy way to have access to a mass value""" 257 258 if isinstance(pdg_code, (int,str)): 259 return self.get('parameter_dict')[self.get_particle(pdg_code).get('mass')].real 260 else: 261 return self.get('parameter_dict')[pdg_code.get('mass')].real
262
263 - def get_width(self, pdg_code):
264 """easy way to have access to a width value""" 265 if isinstance(pdg_code, (int,str)): 266 return self.get('parameter_dict')[self.get_particle(pdg_code).get('width')].real 267 else: 268 return self.get('parameter_dict')[pdg_code.get('mass')].real
269
270 - def need_slha2(self, missing_set, unknow_set):
271 272 return all([b in missing_set for b in ['te','msl2','dsqmix','tu','selmix','msu2','msq2','usqmix','td', 'mse2','msd2']]) and\ 273 all(b in unknow_set for b in ['ae','ad','sbotmix','au','modsel','staumix','stopmix'])
274
275 -class Alphas_Runner(object):
276 """Evaluation of strong coupling constant alpha_S""" 277 # Author: Olivier Mattelaer translated from a fortran routine 278 # written by R. K. Ellis 279 # 280 # q -- scale at which alpha_s is to be evaluated 281 # 282 # asmz -- value of alpha_s at the mass of the Z-boson 283 # nloop -- the number of loops (1,2, or 3) at which beta 284 # 285 # function is evaluated to determine running. 286 # the values of the cmass and the bmass should be set 287 #--------------------------------------------------------------------------- 288
289 - def __init__(self, asmz, nloop, zmass=91.188, cmass=1.4, bmass=4.7):
290 291 self.asmz = asmz 292 self.nloop = nloop 293 self.zmass = zmass 294 self.cmass = cmass 295 self.bmass = bmass 296 297 assert asmz > 0 298 assert cmass > 0 299 assert bmass > 0 300 assert nloop > -1 301 t = 2 * math.log(bmass/zmass) 302 self.amb = self.newton1(t, asmz, 5) 303 t = 2 * math.log(cmass/bmass) 304 self.amc = self.newton1(t, self.amb, 4)
305
306 - def __call__(self, scale):
307 """Evaluation of strong coupling constant alpha_S at scale 'scale'.""" 308 assert scale > 0 309 310 311 if scale < 0.188775276209: 312 return 0 313 elif scale < self.cmass: 314 t = 2 * math.log(scale/self.cmass) 315 return self.newton1(t, self.amc, 3) 316 elif scale < self.bmass: 317 t = 2 * math.log(scale/self.bmass) 318 return self.newton1(t, self.amb, 4) 319 else: 320 t = 2 * math.log(scale/self.zmass) 321 return self.newton1(t, self.asmz, 5)
322 323 # B0=(11.-2.*NF/3.)/4./PI 324 b0 = [0.716197243913527, 0.66314559621623, 0.61009394851893] 325 # C1=(102.D0-38.D0/3.D0*NF)/4.D0/PI/(11.D0-2.D0/3.D0*NF) 326 c1 = [0.565884242104515, 0.49019722472304, 0.40134724779695] 327 # C2=(2857.D0/2.D0-5033*NF/18.D0+325*NF**2/54)/16.D0/PI**2/(11.D0-2.D0/3.D0*NF) 328 c2 = [0.453013579178645, 0.30879037953664, 0.14942733137107] 329 # DEL=SQRT(4*C2-C1**2) 330 d = [1.22140465909230, 0.99743079911360, 0.66077962451190] 331 332 333
334 - def newton1(self, t, alphas, nf):
335 """calculate a_out using nloop beta-function evolution 336 with nf flavours, given starting value as-in 337 given alphas and logarithmic separation between 338 input scale and output scale t. 339 Evolution is performed using Newton's method, 340 with a precision given by tol.""" 341 nloop = self.nloop 342 tol = 5e-4 343 arg = nf-3 344 b0, c1, c2, d = self.b0[arg], self.c1[arg], self.c2[arg], self.d[arg] 345 346 if nloop == 2: 347 f = lambda AS: 1.0/AS+c1*math.log((c1*AS)/(1+c1*AS)) 348 elif nloop == 3: 349 f = lambda AS: 1.0/AS+0.5*c1*math.log((c2*AS**2)/(1+c1*AS+c2*AS**2)) \ 350 -(c1**2-2*c2)/d*math.atan((2*c2*AS+c1)/d) 351 352 a_out = alphas / (1 + alphas * b0 * t) 353 if nloop == 1: 354 return a_out 355 356 a_out = alphas/(1+b0*alphas*t+c1*alphas*math.log(1+alphas*b0*t)) 357 if a_out < 0: 358 a_out = 0.3 359 360 while 1: 361 AS = a_out 362 F = b0 * t + f(alphas) -f(AS) 363 if nloop == 2: 364 FP=1/(AS**2*(1+c1*AS)) 365 elif nloop == 3: 366 FP=1/(AS**2*(1+c1*AS + c2 * AS**2)) 367 if FP == 0: 368 return AS 369 a_out = AS - F/FP 370 delta = abs(F/FP/AS) 371 if delta < tol: 372 break 373 return a_out
374