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