ATLAS Offline Software
Loading...
Searching...
No Matches
powheg_base.py
Go to the documentation of this file.
1# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2
3from AthenaCommon import Logging
4from .configurable import Configurable
5from ..utility import check_svn_revision, FileParser
6import math
7import os
8import glob
9
10
11logger = Logging.logging.getLogger("PowhegControl")
12
13
15 """! Base class for PowhegBox processes.
16
17 All process types inherit from this class.
18
19 @author James Robinson <james.robinson@cern.ch>
20 @author Stefan Richter <stefan.richter@cern.ch>
21 """
22
23 def hoppet_info(self):
24 '''
25 Returns a list of strings to be treated as info messages in the log
26 They otherwise throw an error with HOPPET v. 1.2.0
27 Cf. AGENE-2016
28 '''
29 return ["-----------------------------------------------------------",
30 "Welcome to HOPPET v. 1.2.0",
31 "Higher Order Perturbative Parton Evolution Toolkit",
32 "Written by Gavin P. Salam (2001-2012)",
33 "with contributions from Juan Rojo",
34 "Frederic Dreyer and Alexander Karlberg",
35 "It is made available under the GNU public license,",
36 "with the additional request that if you use it or any",
37 "derivative of it in scientific work then you should cite:",
38 "G.P. Salam & J. Rojo, CPC 180(2009)120 (arXiv:0804.3755).",
39 "You are also encouraged to cite the original references,",
40 "for LO, NLO and NNLO splitting functions, the QCD",
41 "1, 2 and 3 loop beta functions and the coupling and",
42 "PDF and coupling mass threshold matching functions."]
43
44 def hoppet_warning(self):
45 '''
46 Returns a list of strings to be treated as warning messages in the log
47 They otherwise throw an error
48 '''
49 return ["WARNING in InitMTMNNLO: using parametrisation (less accuracte) for A2PShg"]
50
51 def openloops_error(self):
52 '''
53 Returns a list of strings to be treated as error messages in the log
54 They otherwise do not throw an error
55 '''
56 return ["[POWHEG-BOX+OpenLoops] Process not found!"]
57
58 def __init__(self, base_directory, version, executable_name, cores, powheg_executable="pwhg_main", is_reweightable=True, warning_output = [], info_output = [], error_output = [], **kwargs):
59 """! Constructor.
60
61 @param base_directory path to PowhegBox code.
62 @param version PowhegBox version.
63 @param executable_name folder containing appropriate PowhegBox executable.
64 @param powheg_executable name of the powheg executable.
65 @param warning_output list of patterns which if found in the output will be treated as warning in the log.
66 @param error_output list of patterns which if found in the output will be treated as error in the log.
67 @param info_output list of patterns which if found in the output will be treated as info in the log.
68 """
69 super(PowhegBase, self).__init__()
70
71
72 self.executable = os.path.join(base_directory, version, executable_name, powheg_executable)
73 # Check if the file exists, if not, prepend "bin" to the path
74 if not os.path.exists(self.executable):
75 self.executable = os.path.join(base_directory, version, executable_name, "bin", powheg_executable)
76 if os.path.exists(self.executable):
77 logger.info('Executable exists = {0}'.format(self.executable))
78 else:
79 logger.info('Executable does not exist = {0}'.format(self.executable))
80
81
82 os.environ["PYTHONPATH"] = os.path.join(base_directory, version, executable_name, "python") + ":" + os.environ.get("PYTHONPATH", "")
83
84
85 os.environ["LD_LIBRARY_PATH"] = os.path.join(base_directory, version, executable_name, "amplitudes", "obj-gnu") + ":" + os.environ.get("LD_LIBRARY_PATH", "")
86 os.environ["LD_LIBRARY_PATH"] = os.path.join(base_directory, version, executable_name, "QCDLoop-1.95", "ff", "obj-gnu") + ":" + os.environ.get("LD_LIBRARY_PATH", "")
87 os.environ["LD_LIBRARY_PATH"] = os.path.join(base_directory, version, executable_name, "Virtuals", "obj-gnu") + ":" + os.environ.get("LD_LIBRARY_PATH", "")
88 os.environ["LD_LIBRARY_PATH"] = os.path.join(base_directory, version, executable_name, "obj-gfortran") + ":" + os.environ.get("LD_LIBRARY_PATH", "")
89 os.environ["LD_LIBRARY_PATH"] = os.path.join(base_directory, version, executable_name, "obj-gfortran", "proclib") + ":" + os.environ.get("LD_LIBRARY_PATH", "")
90 os.environ["LD_LIBRARY_PATH"] = os.path.join(base_directory, version, executable_name, "obj-gnu") + ":" + os.environ.get("LD_LIBRARY_PATH", "")
91 os.environ["LD_LIBRARY_PATH"] = os.path.join(base_directory, version, executable_name, "obj-gnu", "proclib") + ":" + os.environ.get("LD_LIBRARY_PATH", "")
92
93
94
95 directories = ['obj-gfortran', 'OpenLoops2', 'obj-gnu']
96 logger.info("OpenLoopsPath (before) = {0}".format(os.getenv('OpenLoopsPath')))
97 for directory in directories:
98 if os.path.isdir(os.path.join(base_directory, version, executable_name, directory, 'proclib')):
99 OLPath = os.path.join(base_directory, version, executable_name, directory)
100 os.environ['OpenLoopsPath'] = OLPath
101 logger.info("OpenLoopsPath (after) = {0}".format(os.getenv('OpenLoopsPath')))
102 break
103
104
105 self.process_revision = check_svn_revision(os.path.dirname(self.executable))
106
107
109 one_character_version = self.powheg_version.replace('V', '')[0]
110 POWHEGVER = '{v}_r{rev}'.format(v=one_character_version, rev=self.process_revision)
111 logger.info('MetaData: POWHEGVER = {0}'.format(POWHEGVER))
112 os.environ["POWHEGVER"] = POWHEGVER # does not export to parent shell, but might be sufficient inside job?
113
114
115 self.powhegbox_revision = check_svn_revision(os.path.dirname(os.path.dirname(self.executable)))
116
117
118 self.cores = cores
119
120
121 self.algorithms = []
122
123
124 self.externals = {}
125
126
128
129 # Universal keywords that are set from the run arguments
130 self.add_keyword("ebeam1", kwargs.get("beam_energy", None))
131 self.add_keyword("ebeam2", kwargs.get("beam_energy", None))
132 self.add_keyword("iseed", int(kwargs.get("random_seed", None)))
133 self.add_keyword("numevts", kwargs.get("nEvents", None))
134
135 # Add parameter validation functions
136 self.validation_functions.append("validate_integration_parameters")
137
138
139 self.is_reweightable = is_reweightable
140
141
143
144
146
147
148 self.warning_output = warning_output
149 self.info_output = info_output
150 self.error_output = error_output
151
152
155
156 def add_algorithm(self, alg_or_process):
157 """! Add an algorithm or external process to the sequence.
158
159 @param process Algorithm or external process to add.
160 """
161 # Either add to the list of algorithms to schedule
162 if isinstance(alg_or_process, str):
163 self.algorithms.append(alg_or_process)
164 # ... or add as an external process
165 else:
166 self.externals[alg_or_process.name] = alg_or_process
167
168 @property
170 """! Wildcarded list of files created by this process that can be deleted."""
171 raise AttributeError("Names of unneeded files are not known for this process!")
172
173 @property
175 """! Wildcarded list of integration files that might be created by this process."""
176 raise AttributeError("Integration file names are not known for this process!")
177
178 @property
180 """! Wildcarded list of integration files that are needed for this process."""
181 raise AttributeError("Integration file names are not known for this process!")
182
183 @property
184 def powheg_version(self):
185 """! Version of PowhegBox process."""
186 raise AttributeError("Powheg version is not known!")
187
188 @property
189 def default_PDFs(self):
190 """! Default PDFs for this process."""
191 raise AttributeError("Default PDFs are not known for this process!")
192
193 @property
194 def default_scales(self):
195 """! Default scale variations for this process."""
196 raise AttributeError("Default scales are not known for this process!")
197
198 def prepare_to_parallelise(self, n_cores):
199 """! Scale calculation parameters by n_cores."""
200 __nEvents_unscaled = self.parameters_by_keyword("numevts")[0].value
201 for keyword in ["ncall1", "ncall1rm", "ncall2", "ncall2rm", "nubound", "numevts"]:
202 for parameter in self.parameters_by_keyword(keyword):
203 if int(parameter.value) > 0:
204 parameter.value = int(math.ceil(float(parameter.value) / n_cores))
205 __nEvents_scaled = self.parameters_by_keyword("numevts")[0].value
206 logger.info("Scaling number of events per job from {} down to {}".format(__nEvents_unscaled, __nEvents_scaled))
207 # Freeze parallelstage parameters before printing list for user
208 [parameter.freeze() for parameter in self.parameters_by_name("parallelstage")]
209
210 def stage_is_completed(self, stage):
211 """! Set whether the specified POWHEG-BOX generation stage is complete."""
212 # Perform manual check to allow re-use of grids in multicore mode
213 return False
214
216 """! Validate any parameters which need it before preparing runcard."""
217 for function_name in self.validation_functions:
218 getattr(self, function_name)()
219
221 """! Validate integration keywords by forcing to integer values."""
222 self.expose() # convenience call to simplify syntax
223 for name in ("foldcsi", "foldphi", "foldy", "itmx1", "itmx2", "ncall1", "ncall2", "nEvents"):
224 for parameter in self.parameters_by_name(name):
225 try:
226 parameter.value = int(parameter.value)
227 except TypeError:
228 logger.fatal("Failed to validate {} with value {}".format(name, parameter.value))
229 raise
230
231 def check_decay_mode(self, decay_mode, allowed_decay_modes=None):
232 """! Check whether a decay mode is allowed an raise an exception if it is not."""
233 if allowed_decay_modes is None:
234 allowed_decay_modes = self.allowed_decay_modes
235 if decay_mode not in allowed_decay_modes:
236 logger.warning("Decay mode {} not recognised!".format(decay_mode))
237 logger.info("Allowed decay modes are:")
238 for allowed_decay_mode in allowed_decay_modes:
239 logger.info("... {}".format(allowed_decay_mode))
240 raise ValueError("Decay mode {} not recognised!".format(decay_mode))
241
243
244 search_strings = [] # list of filename patters to be searched for
245 found_files = [] # list of found files will be printed out for info
246 missing_patterns = [] # list of filename patters which hasn't been found but would be needed for pre-made integration grids
247 try:
248 search_strings = self.mandatory_integration_file_names
249 except AttributeError:
250 logger.fatal("No integration grid file name patterns defined for this process.")
251 raise
252 for s in search_strings:
253 found = glob.glob(s)
254 if found != []:
255 found_files += found
256 else:
257 missing_patterns.append(s)
258 if missing_patterns == []:
259 logger.info("Integration grid files found locally. Event generation shall continue, skipping the integration step.")
260 logger.info("Integration grid files found locally: {}".format(found_files))
261 else:
262 logger.info("Integration grid files needed were not found locally. Event generation shall continue, starting by the integration step.")
263 logger.info("Missing integration grid files with these patterns: {}".format(missing_patterns))
264 logger.info("Integration grid files found locally (if any): {}".format(found_files))
265
266
267 def modify_parameter(self, stage = 0):
268
269 #skip modifying if dict is empty
270 if not bool(self.parameterStageDict):
271 return
272
273 logger.info("Modifying parameters for the stages : {0}".format(self.parameterStageDict))
274
275
276 for key in self.parameterStageDict:
277 settingsList = self.parameterStageDict[key]
278 if abs(settingsList[2] - stage) <=1e-09:
279 self.set_parameter_in_config(key,settingsList[1])
280 else:
281 self.set_parameter_in_config(key,settingsList[0])
282
283 def set_parameter_in_config(self, key, value):
284 FileParser("powheg.input").text_replace(key+".*", key+" {}".format(value))
Class for any process which can be configured.
add_keyword(self, keyword, value=None, name=None, frozen=None, hidden=None, description=None, **kwargs)
Register configurable parameter that is exposed to the user.
expose(self)
Add all names to the interface of this object.
parameters_by_name(self, name)
Retrieve all parameters that use a given name.
parameters_by_keyword(self, keyword)
Retrieve all parameters that use a given keyword.
Base class for PowhegBox processes.
dict parameterStageDict
Dictionary used to change parameters of the Powheg input.
remove_oldStyle_rwt_comments
Switch to determine if the rwgt and pdf comments should be kept in lhe files despite using xml reweig...
validate_integration_parameters(self)
Validate integration keywords by forcing to integer values.
prepare_to_parallelise(self, n_cores)
Scale calculation parameters by n_cores.
use_XML_reweighting
Switch to determine whether XML reweighting should be used.
executable
Powheg executable that will be used.
integration_file_names(self)
Wildcarded list of integration files that might be created by this process.
dict externals
List of external processes to schedule.
powhegbox_revision
SVN revision of PowhegBox code.
list validation_functions
List of validation functions to run before preparing runcard.
process_revision
SVN revision of process code.
powheg_version(self)
Version of PowhegBox process.
add_algorithm(self, alg_or_process)
Add an algorithm or external process to the sequence.
list algorithms
List of additional algorithms to schedule.
warning_output
Special treatment for some log messages.
is_reweightable
Switch to determine whether reweighting is allowed.
validate_parameters(self)
Validate any parameters which need it before preparing runcard.
files_for_cleanup(self)
Wildcarded list of files created by this process that can be deleted.
stage_is_completed(self, stage)
Set whether the specified POWHEG-BOX generation stage is complete.
mandatory_integration_file_names(self)
Wildcarded list of integration files that are needed for this process.
check_decay_mode(self, decay_mode, allowed_decay_modes=None)
Check whether a decay mode is allowed an raise an exception if it is not.
__init__(self, base_directory, version, executable_name, cores, powheg_executable="pwhg_main", is_reweightable=True, warning_output=[], info_output=[], error_output=[], **kwargs)
Constructor.
default_scales(self)
Default scale variations for this process.
default_PDFs(self)
Default PDFs for this process.
Utility class to perform simple operations on files.
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310