Loading [MathJax]/extensions/tex2jax.js
SyTen
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
pyten

The pyten_module directory contains .cpp files which, when compiled and linked into a shared library, make up the Python3 bindings for SyTen. These bindings allow calling SyTen from within Python at negligible speed differences. In a certain sense, the bindings are like another interface to the library next to the binary executables in bin/ and lat/. Most but not all functions are already available from Python. If a specific function you need is missing, it is generally straightforward to expose it to Python (and just not done yet due to lazyness/no need/etc.).

For obvious reasons, the Python3 module of SyTen is called pyten.

Installation and Use

Compile and install with make copy, make sure that your make.inc file defines a variable EXT_PYPDIR denoting a writable folder. Also make sure that this folder is contained in your PYTHONPATH environment variable.

Then, you can either use

from pyten import *

or

import pyten [as ptn]

to use the library from Python.

Structure & Code Organisation

To call a C++ function from Python, Python needs to learn about this function. The shared library cpp_pyten.so defined in cpp_pyten.cpp hence calls various init_*() functions which make C++ functions available to Python one-by-one. These init_*() functions are distributed over various .cpp files in the subdirectories here, corresponding loosely to the subdirectories of the main toolkit (with inc/ flattened away). Classes and enums are also made known to Python in a very similar fashion, numerous examples already exist.

However, it is also possible to extend the pyten module/package with native Python code. To this end, a package pyten is constructed as a directory tree (python_module/pyten). This directory tree firstly contains an __init__.py file. This file is executed/parsed when the pyten module is imported. In particular, it exposes the C++ functions defined in the cpp_pyten.so shared library directly below the pyten namespace and, in addition, also reads them all in and adds them to the special __all__ variable. This way, if you say

import pyten as ptn

e.g. the class TruncationType is available in the ptn namespace. Similarly, with

from pyten import *

the class TruncationType is injected in the global (current) namespace. On installation, the cpp_pyten.so library is copied into this directory tree and the whole thing is copied into the PYMOD_DIR directory (which is supposed to be contained in the PYTHONPATH environment variable).

Caveats

Copied STL containers

STL containers corresponding to built-in Python types are copied at the Python/C++ interface. This incurs a performance penalty and other unwanted things. In most cases, its still fine (e.g. vectors of MPOs transported this way into addLog()) but sometimes this overhead may be very large. A solution is outlined in the pybind11 docs.

Templates

Unfortunately, Python doesn’t know templates. Worse, it has no generic programming facility available to translate C++ templates. Hence, the needed templates have to be instantiated one-by-one if they are to be available on the Python side. This is not a problem for MPS etc. which are only internally-templated, but is seriously annoying for generic tensors. At the moment, python_module/dense/dense.cpp declares dense tensors of rank up to 8 with double and std::complex<double> scalars. It also declares all tensor product functions currently used in the toolkit library. Functions not declared there are not available to Python, e.g. it is not possible to declare a rank-13 dense tensor or a dense product of a rank-8 and rank-2 tensor (unless added there!). Unfortunately, simply declaring all possible products of tensors below e.g. rank-10 was not feasible due to memory and compile time constraints.

Remarks
This is not a problem for the syten::STensor class and its family of functions, as they are not externally-templated. You can hence use arbitrary-rank syten::STensor objects and their products from Python, as long as their rank is below the compile-time constant defined by SYTEN_STENSOR_MAX_RANK and you have enabled the syten::STensor class by defining SYTEN_STENSOR.

Function templates

In a similar vein to the above, it is not possible to declare function templates in Python. Since prodD<>() takes the number of summed-over legs as a template argument, it is necessary to transport this number as a type from C++ to Python to allow for correct overloading. For this reason, prodD() on the Python side takes an additional first argument, an array of the same size as the summed over dimensions. That is

@code{.cpp}
prodD<2>(a, b, {1, 2, -3, -5}, {-1, 1, -2, 2, -4})
@endcode

becomes

@code{.py}
prodD([1,2], a, b, [1, 2, -3, -5], [-1, 1, -2, 2, -4])
@endcode

An alternative solution would be a Python-side wrapper which could insert this argument based on the contents of the c_a and c_b arrays.

Example Python Code

Examples should be placed in python_module/examples, furthermore, at least one lattice in lat/ already exists using the Pyten interface. Over time, new binaries in bin/ or lat/ may be implemented in Python, if this is suitable.

Documentation

There are some small Python-only functions supplied in python_module/pyten. Doxygen is not very good at extracting the docstrings from them. To improve this formatting, consider installing doxypy (e.g. in Ubuntu's package repository) and then add a line

FILTER_PATTERNS        = *.py=doxypy

to your build/doxygen.conf.inc.