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 """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 # Extract external parameters 69 external_parameters = self['parameters'][('external',)] 70 # Read in param_card 71 if param_card: 72 # Create a dictionary from LHA block name and code to parameter name 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 # Check that param_card exists 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 #misc.sprint(type(param_card), card_reader.ParamCard, isinstance(param_card, card_reader.ParamCard)) 88 #assert isinstance(param_card, card_reader.ParamCard),'%s is not a ParamCard: %s' % (type(param_card), isinstance(param_card, card_reader.ParamCard)) 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 # the two card are different. check if this critical 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 # No param_card, use default values 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 # Define all functions used 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 # Extract derived parameters 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 # Now calculate derived parameters 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 # Correct width sign for Majorana particles (where the width 231 # and mass need to have the same sign) 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 # Extract couplings 240 couplings = sum(list(self['couplings'].values()), []) 241 # Now calculate all couplings 242 for coup in couplings: 243 #print "I execute %s = %s"%(coup.name, coup.expr) 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 # Set parameter and coupling dictionaries 251 self.set('parameter_dict', dict([(param.name, param.value) \ 252 for param in external_parameters + \ 253 derived_parameters])) 254 255 # Add "zero" 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
263 - def get_mass(self, pdg_code):
264 """easy way to have access to a mass value""" 265 266 if isinstance(pdg_code, (int,str)): 267 return self.get('parameter_dict')[self.get_particle(pdg_code).get('mass')].real 268 else: 269 return self.get('parameter_dict')[pdg_code.get('mass')].real
270
271 - def get_width(self, pdg_code):
272 """easy way to have access to a width value""" 273 if isinstance(pdg_code, (int,str)): 274 return self.get('parameter_dict')[self.get_particle(pdg_code).get('width')].real 275 else: 276 return self.get('parameter_dict')[pdg_code.get('mass')].real
277
278 - def need_slha2(self, missing_set, unknow_set):
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
283 -class Alphas_Runner(object):
284 """Evaluation of strong coupling constant alpha_S""" 285 # Author: Olivier Mattelaer translated from a fortran routine 286 # written by R. K. Ellis 287 # 288 # q -- scale at which alpha_s is to be evaluated 289 # 290 # asmz -- value of alpha_s at the mass of the Z-boson 291 # nloop -- the number of loops (1,2, or 3) at which beta 292 # 293 # function is evaluated to determine running. 294 # the values of the cmass and the bmass should be set 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
314 - def __call__(self, scale):
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 # B0=(11.-2.*NF/3.)/4./PI 332 b0 = [0.716197243913527, 0.66314559621623, 0.61009394851893] 333 # C1=(102.D0-38.D0/3.D0*NF)/4.D0/PI/(11.D0-2.D0/3.D0*NF) 334 c1 = [0.565884242104515, 0.49019722472304, 0.40134724779695] 335 # C2=(2857.D0/2.D0-5033*NF/18.D0+325*NF**2/54)/16.D0/PI**2/(11.D0-2.D0/3.D0*NF) 336 c2 = [0.453013579178645, 0.30879037953664, 0.14942733137107] 337 # DEL=SQRT(4*C2-C1**2) 338 d = [1.22140465909230, 0.99743079911360, 0.66077962451190] 339 340 341
342 - def newton1(self, t, alphas, nf):
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