Buildings.Utilities.IO.Python27.UsersGuide
User's Guide
Information
This package contains classes that call Python functions. The classes can be used to send data to Python functions, and to obtain data from Python functions. This allows for example to use Python to communicate with web services, with hardware, or to do other computations inside a Python module.
The code has been tested with Python 2.7 on Linux 32 and 64 bit and Windows 32 and 64 bit.
Software configuration to use classes from this package
To use classes from this package, a Python 2.7
runtime environment must be installed.
Also, the system environment variable
PYTHONPATH
must be set in order for Python
to find the modules that contain the functions.
These modules are stored in the directory
Buildings/Resources/Python-Sources
.
In addition, an environment variable (LD_LIBRARY_PATH
on Linux
and PATH
on Windows) must be set in order for a simulation
environment to find the dynamically linked libraries.
The table below explains how to set these variables for
various system configurations.
Because some Python libraries may also link to compiled C code, we
recommend that if you are using a 64-bit operating system, you configure
Dymola to generate 64 bit code. Configuring the compilation
can be done by entering on the
Dymola command line the assignment
Advanced.CompileWith64=1
for 32-bit, or
Advanced.CompileWith64=2
for 64-bit.
System | Settings |
---|---|
Linux 32 bit, Dymola 2016 |
Enter on a console the commands export PYTHONPATH=${PYTHONPATH}:"Path_To_Buildings_Library"/Resources/Python-Sources export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:"Path_To_Buildings_Library"/Resources/Library/linux32
Alternatively, these lines could be added to the file |
Linux 64 bit, Dymola 2016 |
Use the same commands as for Linux 64 bit, Dymola 2016 because Dymola 2016 generates by default 32 bit code.
However, if you load other Python libraries such as numpy, you need to make sure
that Dymola compiles 64 bit and uses the 64 bit library from
export PYTHONPATH=${PYTHONPATH}:"Path_To_Buildings_Library"/Resources/Python-Sources export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:"Path_To_Buildings_Library"/Resources/Library/linux64
Alternatively, these lines could be added to the file Next, in the Dymola command window, set Advanced.CompileWith64=2; |
Linux 32 bit, Dymola 2014 |
Enter on a console the commands
export PYTHONPATH=${PYTHONPATH}:"Path_To_Buildings_Library"/Resources/Python-Sources export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:"Path_To_Buildings_Library"/Resources/Library/linux32Alternatively, these lines could be added to the file ~/.bashrc .
|
Linux 64 bit, Dymola 2014 | Use the same commands as for Linux 64 bit, Dymola 2014 because Dymola 2014 only generates 32 bit code. |
Linux 32 bit, Dymola 2013 FD01 |
Enter on a console the commands
export PYTHONPATH=${PYTHONPATH}:"Path_To_Buildings_Library"/Resources/Python-SourcesAlternatively, these lines could be added to the file ~/.bashrc .Next, modify /opt/dymola/bin/dymola.sh by replacing the line
export LD_LIBRARY_PATH=$DYMOLA/bin/libwith export LD_LIBRARY_PATH=$DYMOLA/bin/lib:"Path_To_Buildings_Library"/Resources/Library/linux32 export LD_LIBRARY_PATH=$DYMOLA/bin/lib:Resources/Library/linux32 |
Linux 64 bit, Dymola 2013 FD01 | Use the same commands as for Linux 32 bit, Dymola 2013 FD01 because Dymola 2013 FD01 only generates 32 bit code. |
Windows 32 bit, Dymola 2014
Windows 64 bit, Dymola 2014 Windows 32 bit, Dymola 2013 FD01 Windows 64 bit, Dymola 2013 FD01 |
Add to the system environment variable PYTHONPATH the directory
"Path_To_Buildings_Library"\Resources\Python-Sources .
|
Type of Python functions
Two different types of Python functions are supported: Functions that do not need to pass Python objects between one invocation to another, and functions that need to pass a Python object from one invocation to another. For the first case, a Python function may be
def returnTwiceTheInput(xR): return 2.*xR
For the second case, a Python function may be
def incrementAndReturnACounter(i, obj): if obj == None: # Initialize the Python object obj = {'counter': i} else: # Use the python object obj['counter'] = obj['counter'] + i return [i, obj]
For the first case, set in the function
Buildings.Utilities.IO.Python27.Functions.exchange
the input argument passPythonObject = false
,
and for the second case, set passPythonObject = true
.
The second case
allows for example to build up a Python data structure (or to instantiate a Python object),
and do computations on this object at each function invocation. For example,
a Model Predictive Control algorithm or a machine learning algorithm,
implemented in Python, could be fed with data at each time step.
It could then store this data
and use the current and its historical data to feed its algorithm.
Based on this algorithm, it could output a control signal for use in another Modelica model.
Number of values to read to Python and write from Python
The parameters nDblWri
(or nIntWri
or nStrWri
)
and nDblRea
(or nIntRea
) declare
how many double (integer or string) values should be written to, or read from, the Python function.
These values can be zero, in which case the Python function receives no
arguments for this data type, or it must return a list with zero elements.
However, because Modelica does not allow arrays with
zero elements, the arrays
dblWri
and dblRea
, respectively, must contain exactly one element
if nDblWri=0
or nDblRea=0
.
In this situation, dblWri
is a dummy argument that will not be written to Python,
and dblRea
contains a number that must not be used in any model.
Arguments of the Python function
The arguments of the python functions are, in this order,
floats, integers and strings (and the Python object if passPythonObject = true
).
If there is only one element of each data type, then a single value is passed.
If there are multiple elements of each data type, then they are stored in a list.
If there is no value of a data type (such as if nDblWri=0
), then the argument is not present.
Thus, if a data type is not present, then the function will not receive an empty list of this data type.
If there are no arguments at all, then the function takes no arguments
(except if passPythonObject = true
, in which case the only argument is the Python object).
The table below shows the list of arguments for various combinations where no, one or two double values, integers and strings are passed as an argument to a Python function.
- If
passPythonObject = false
:
nDblWri nIntWri nStrWri Arguments 1 0 0 1. 0 1 1 1, "a" 2 0 2 [1.0, 2.0], ["a", "b"] 1 1 1 1.0, 2, "a" 1 2 0 1.0 , [1, 2] 2 1 0 [1.0, 2.0], 1 2 2 2 [1.0, 2.0], [1, 2], ["a", "b"] - If
passPythonObject = true
:
nDblWri nIntWri nStrWri Arguments 1 0 0 1., pytObj 0 1 1 1, "a", pytObj 2 0 2 [1.0, 2.0], ["a", "b"], pytObj 1 1 1 1.0, 2, "a", pytObj 1 2 0 1.0 , [1, 2], pytObj 2 1 0 [1.0, 2.0], 1, pytObj 2 2 2 [1.0, 2.0], [1, 2], ["a", "b"], pytObj
wherepytObj
is the Python object.
Returns values of the Python function
The Python function must return their values in the following order:
-
If the function returns one or multiple double values, then the first return
value must be a double (if
nDblRea=1
) or a list of doubles (ifnDblRea > 1
). -
If the function returns one or multiple integer values, then the next return
value must be an integer (if
nIntRea=1
) or a list of integers (ifnIntRea > 1
). -
If
nDblRea = nIntRea = 0
, then the return values of the function, if any, are ignored.
The table below shows valid return types for various combinations where no, one or two double values and integer values are returned.
- If
passPythonObject = false
:
nDblRea nIntRea Return value 1 0 1. 0 1 1 2 0 [1.0, 2.0] 1 1 1.0, 2 1 2 1.0 , [1, 2] 2 1 [1.0, 2.0], 1 2 2 [1.0, 2.0], [1, 2] - If
passPythonObject = true
:
nDblRea nIntRea Return value 1 0 1., pytObj 0 1 1, pytObj 2 0 [1.0, 2.0], pytObj 1 1 1.0, 2, pytObj 1 2 1.0 , [1, 2], pytObj 2 1 [1.0, 2.0], 1, pytObj 2 2 [1.0, 2.0], [1, 2], pytObj
wherepytObj
is the Python object.
Pure Modelica functions (functions without side effects)
The functions that exchange data with Python are implemented as pure
Modelica functions.
Pure functions always return the same value if called repeatedly.
If these functions are used to call hardware sensors or web services,
they need to be called from a when
-equation.
See the Modelica language specification for an explanation of pure and impure functions.
Examples
Various examples are provided, and for each of these, the Python functions are stored in the directory
Buildings/Resources/Python-Sources
.
The examples Buildings.Utilities.IO.Python27.Functions.Examples.Exchange and Buildings.Utilities.IO.Python27.Functions.Examples.ExchangeWithPassPythonObject contains various calls to different Python functions without and with memory.
The example Buildings.Utilities.IO.Python27.Examples.KalmanFilter shows how to implement in a Modelica block a call to a Python function. This Python function stores its memory on disk between invocations (which, in general, is not recommended).
The example Buildings.Utilities.IO.Python27.Examples.SimpleRoom shows a similiar example. However, rather than using a file to store the room temperature and energy between invocations, the function returns an object with this information, and receives this object again in the next invocation.
Implementation notes
String values cannot be returned from a Python function.
The reason is that Dymola 2013 FD01 generates a compile time error
if a Modelica function returns (Real[nR], Integer[nI], String)
.
This will be fixed in Dymola 2014.
(Support request #14983.)
Known Issues
The Python installation of Ubuntu 14.04 has a bug that causes Dymola to produce output of the following form:
Traceback (most recent call last): File "/usr/lib/python2.7/site.py", line 563, in <module> main() File "/usr/lib/python2.7/site.py", line 545, in main known_paths = addusersitepackages(known_paths) File "/usr/lib/python2.7/site.py", line 272, in addusersitepackages user_site = getusersitepackages() File "/usr/lib/python2.7/site.py", line 247, in getusersitepackages user_base = getuserbase() # this will also set USER_BASE File "/usr/lib/python2.7/site.py", line 237, in getuserbase USER_BASE = get_config_var('userbase') File "/usr/lib/python2.7/sysconfig.py", line 578, in get_config_var return get_config_vars().get(name) File "/usr/lib/python2.7/sysconfig.py", line 524, in get_config_vars _init_posix(_CONFIG_VARS) File "/usr/lib/python2.7/sysconfig.py", line 408, in _init_posix from _sysconfigdata import build_time_vars File "/usr/lib/python2.7/_sysconfigdata.py", line 6, in <module> from _sysconfigdata_nd import * ImportError: No module named _sysconfigdat ...(message truncated)
As a work-around, type in a shell the commands
$ cd /usr/lib/python2.7 $ sudo ln -s plat-x86_64-linux-gnu/_sysconfigdata_nd.py .
See also https://bugs.launchpad.net/ubuntu/+source/python2.7/+bug/1115466.
Extends from Modelica.Icons.Information (Icon for general information packages).