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