/usr/share/pyshared/FreeFOAM/run.py is in libfreefoam1 0.1.0+dfsg-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | #-------------------------------------------------------------------------------
# ______ _ ____ __ __
# | ____| _| |_ / __ \ /\ | \/ |
# | |__ _ __ ___ ___ / \| | | | / \ | \ / |
# | __| '__/ _ \/ _ ( (| |) ) | | |/ /\ \ | |\/| |
# | | | | | __/ __/\_ _/| |__| / ____ \| | | |
# |_| |_| \___|\___| |_| \____/_/ \_\_| |_|
#
# FreeFOAM: The Cross-Platform CFD Toolkit
#
# Copyright (C) 2008-2012 Michael Wild <themiwi@users.sf.net>
# Gerber van der Graaf <gerber_graaf@users.sf.net>
#-------------------------------------------------------------------------------
# License
# This file is part of FreeFOAM.
#
# FreeFOAM is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# FreeFOAM is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with FreeFOAM. If not, see <http://www.gnu.org/licenses/>.
#
# Description
# Useful Python functionality to run FreeFOAM cases
#
#-------------------------------------------------------------------------------
"""Classes and functions useful for running FreeFOAM applications."""
# want to be future proof
from FreeFOAM.compat import *
import os as _os
import os.path as _op
import FreeFOAM as _f
class ApplicationNotFoundError(Exception):
"""Thrown by run_job if the requested application could not be found."""
def __init__(self, appname):
"""Initializes the exception object.
Parameters
----------
appname : The name of the application
"""
Exception.__init__(self, "ERROR: Application not found: %s"%appname)
class BinDirCreationError(Exception):
"""Thrown if the creation of the binary directory by compile_application failed."""
def __init__(self, bindir, msg):
"""Initialize the exception object.
Parameters
----------
bindir : The directory that could not be created.
msg : A message describing the error condition in more detail.
"""
Exception.__init__(self, bindir, msg)
def __str__():
"""Return string representation of the error."""
return 'ERROR: Failed to create "%s": %s'%self.args
class EntryNotFoundError(Exception):
"""Thrown if an entry couldn't be found in a config file."""
def __init__(self, entry, filename):
"""Initialize the exception object.
Parameters
----------
entry : The entry that could not be found.
filename: Name of the config file.
"""
Exception.__init__(self, entry, filename)
def __str__(self):
"""Return string representation of the error."""
return ('ERROR: Failed to find entry %s in %s.'%self.args)
class NotDecomposedError(Exception):
"""Thrown if case should be run in parallel but is not decomposed."""
def __init__(self, case):
"""Initialize the exception object.
Parameters
----------
case : The case that isn't decomposed
"""
Exception.__init__(self, case)
def __str__(self):
"""Return string representation of the error."""
return ('ERROR: Cannot run case %s in parallel, '+
'because it is not decomposed.'%self.args)
class Runner:
"""A class to run FreeFOAM applications."""
def __init__(self, search_path=_f.search_path):
"""Initializes the Runner object.
Parameters
----------
path : The search path for FreeFOAM applications.
"""
# set up path
self._search_path = search_path
# holds the subprocess.Popen object of a running job
self._process = None
# the exit code of the last process that ran. None if the process is still
# running or if no process ran at all so far.
self.returncode = None
def _create_command(self, appname, case, parallel, args):
"""Assembles the command line (as a list, suitable for subprocess)"""
from FreeFOAM.path import locate_app
# find executable
app = locate_app(appname, self._search_path)
if not app:
raise ApplicationNotFoundError(appname)
# assemble command line
command = [app]
if case:
command.append('-case')
command.append(_op.normpath(case))
if parallel:
command.append('-parallel')
if type(args) == str:
args = [args]
if len(args):
command.extend(args)
return command
def _check_parallel(self, parallel):
"""Checks a few (currently OpenMPI) characteristics to
detect whether this is parallel run and issues a warning if the
`parallel` flag does not match."""
import sys
if 'OMPI_MCA_universe' in _os.environ:
if not parallel:
sys.stderr.write('Warning: Probably running in OpenMPI, '+
'but -parallel not specified\n')
else:
if parallel:
sys.stderr.write('Warning: Probably not running in OpenMPI, '+
'but -parallel specified\n')
def run(self, appname, background=False, case=None, parallel=False,
stdin=None, stdout=None, stderr=None, args=[]):
"""Run a FreeFOAM job.
Parameters
----------
appname : Name or full/relative path to the application to run.
background : Run the application in the background.
case : Path to the case to run. Defaults to the current directory.
parallel : If True, the '-parallel' flag will be passed to the
application.
stdin, stdout and stderr:
The program's standard input, output and error streams,
respectively. Valid values are a file descriptor, a
file object or None (in which case the system streams
will be used).
args : Iterable or string of additional arguments and options to be
passed to the application.
Returns
-------
result : The exit code of the application if 'background' is False,
None otherwise.
Throws
------
ApplicationNotFoundError : If the application 'appname' cannot be found.
"""
import subprocess
import sys
self._check_parallel(parallel)
command = self._create_command(appname, case=case,
parallel=parallel, args=args)
if stdin == None:
stdin = sys.stdin
if stdout == None:
stdout = sys.stdout
# make sure that the global controlDict is found
if 'FREEFOAM_CONFIG_DIR' not in _os.environ:
_os.environ['FREEFOAM_CONFIG_DIR'] = _f.config_dir
# run the command
self.returncode = None
self._process = subprocess.Popen(command, stdin=stdin, stdout=stdout,
stderr=stderr)
# should we run in the background?
if background:
return None
# nope, so we wait, delete the _process object and return the exit code
self._process.wait()
self.returncode = self._process.returncode
self._process = None
return self.returncode
def poll(self):
"""Check if child process has terminated.
Set and return returncode attribute. If the process terminated, the
object is freed.
Returns
-------
returncode : The exit code of the process or None if the process is still
running or no process has ever been run by this object.
"""
if self._process:
self.returncode = self._process.poll()
else:
self.returncode = None
return self.returncode
def getProcess(self):
"""Access the Popen object."""
return self._process
def command_str(self, appname, case=None, parallel=False, args=[]):
"""Return the command line to run a FreeFOAM job.
Parameters
----------
appname : Name or full/relative path to the application to run.
case : Path to the case to run. Defaults to the current directory.
parallel : If True, the '-parallel' flag will be passed to the
application.
args : Iterable or string of additional arguments and options to be
passed to the application.
Returns
-------
result : A string with the command line.
Throws
------
ApplicationNotFoundError : If the application 'appname' cannot be found.
"""
command = self._create_command(appname, case=case,
parallel=parallel, args=args)
return ' '.join(command)
class ParallelRunner(Runner):
"""Class to run FreeFOAM cases in parallel."""
# override the _create_command function
def _create_command(self, appname, case, parallel, args):
"""Assembles the command line (as a list, suitable for subprocess)"""
import re
import glob
import sys
# if parallel desired, check whether decomposed:
is_decomposed =_op.isdir(_op.join(case, 'processor0'))
cmd = None
if parallel and is_decomposed:
# count number of processors
nproc = len(glob.glob(_op.join(case,'processor*')))
# create command from the template in global controlDict
template = None
controlDict = _op.join(_f.config_dir, 'controlDict')
for l in open(controlDict, 'rt'):
m = re.match(r'\s*parRunTemplate\s+["\'](.*)["\']\s*;\s*$', l)
if m:
template = m.group(1)
if not template:
raise EntryNotFoundError('parRunTemplate', controlDict)
cmd = (template%{
'NPROCS': nproc,
'PAROPTS': '',
'APPLICATION': ' '.join(
Runner._create_command(self, appname, case, False, [])),
'ARGS': ' '.join(args),
}).split()
elif parallel and not is_decomposed:
raise NotDecomposedError(case)
if not cmd:
cmd = Runner._create_command(self, appname, case, False, args)
return cmd
def _check_parallel(self, parallel):
"""Do nothing."""
pass
# ------------------------- vim: set sw=3 sts=3 et: --------------- end-of-file
|