From cb8e32d1881c1308fde8debdd913baf2335a16b9 Mon Sep 17 00:00:00 2001 From: Frederik Hennig <frederik.hennig@fau.de> Date: Tue, 2 Jul 2024 16:32:36 +0200 Subject: [PATCH] symbolic extensions export module + documentation --- docs/source/api/index.rst | 2 +- .../astnodes.rst | 0 .../field.rst | 6 +- docs/source/api/symbolic_language/index.rst | 70 +++++++++++++++++++ .../api/symbolic_language/sympyextensions.rst | 6 ++ docs/source/api/sympyextensions/index.rst | 10 --- src/pystencils/symb.py | 23 ++++++ .../sympyextensions/integer_functions.py | 4 +- 8 files changed, 105 insertions(+), 16 deletions(-) rename docs/source/api/{sympyextensions => symbolic_language}/astnodes.rst (100%) rename docs/source/api/{sympyextensions => symbolic_language}/field.rst (58%) create mode 100644 docs/source/api/symbolic_language/index.rst create mode 100644 docs/source/api/symbolic_language/sympyextensions.rst delete mode 100644 docs/source/api/sympyextensions/index.rst create mode 100644 src/pystencils/symb.py diff --git a/docs/source/api/index.rst b/docs/source/api/index.rst index 9af45d147..4763300a1 100644 --- a/docs/source/api/index.rst +++ b/docs/source/api/index.rst @@ -5,6 +5,6 @@ API Reference .. toctree:: :maxdepth: 2 - sympyextensions/index + symbolic_language/index kernelcreation/index types diff --git a/docs/source/api/sympyextensions/astnodes.rst b/docs/source/api/symbolic_language/astnodes.rst similarity index 100% rename from docs/source/api/sympyextensions/astnodes.rst rename to docs/source/api/symbolic_language/astnodes.rst diff --git a/docs/source/api/sympyextensions/field.rst b/docs/source/api/symbolic_language/field.rst similarity index 58% rename from docs/source/api/sympyextensions/field.rst rename to docs/source/api/symbolic_language/field.rst index a435c716c..a76d39a3a 100644 --- a/docs/source/api/sympyextensions/field.rst +++ b/docs/source/api/symbolic_language/field.rst @@ -1,6 +1,6 @@ -------------------------- -Fields (pystencils.field) -------------------------- +----------------------------- +Fields API (pystencils.field) +----------------------------- .. automodule:: pystencils.field :members: diff --git a/docs/source/api/symbolic_language/index.rst b/docs/source/api/symbolic_language/index.rst new file mode 100644 index 000000000..bf478414b --- /dev/null +++ b/docs/source/api/symbolic_language/index.rst @@ -0,0 +1,70 @@ +***************** +Symbolic Language +***************** + +.. toctree:: + :maxdepth: 1 + + field + astnodes + sympyextensions + +Pystencils allows you to define near-arbitrarily complex numerical kernels in its symbolic +language, which is based on the computer algebra system `SymPy <https://www.sympy.org>`_. +The pystencils code generator is able to parse and translate a large portion of SymPy's +symbolic expression toolkit, and furthermore extends it with its own features. +Among the supported SymPy features are: symbols, constants, arithmetic and logical expressions, +trigonometric and most transcendental functions, as well as piecewise definitions. + +Fields +====== + +The most important extension to SymPy brought by pystencils are *fields*. +Fields are a symbolic representation of multidimensional cartesian numerical arrays, +as used in many stencil algorithms. +They are represented by the `Field` class. + +Piecewise Definitions +===================== + +Pystencils can parse and translate piecewise function definitions using `sympy.Piecewise` +*only if* they have a default case. +So, for instance, + +.. code-block:: Python + + sp.Piecewise((0, x < 0), (1, x >= 0)) + +will result in an error from pystencils, while the equivalent + +.. code-block:: Python + + sp.Piecewise((0, x < 0), (1, True)) + +will be accepted. This is because pystencils cannot reason about whether or not +the given cases completely cover the entire possible input range. + +Integer Operations +================== + +Division and Remainder +---------------------- + +Care has to be taken when working with integer division operations in pystencils. +The python operators ``//`` and ``%`` work differently from their counterparts in the C family of languages. +Where in C, integer division always rounds toward zero, ``//`` performs a floor-divide (or euclidean division) +which rounds toward negative infinity. +These two operations differ whenever one of the operands is negative. +Accordingly, in Python ``a % b`` returns the *euclidean modulus*, +while C ``a % b`` computes the *remainder* of division. +The euclidean modulus is always nonnegative, while the remainder, if nonzero, always has the same sign as ``a``. + +When ``//`` and ``%`` occur in symbolic expressions given to pystencils, they are interpreted the Python-way. +This can lead to inefficient generated code, since Pythonic integer division does not map to the corresponding C +operators. +To achieve C behaviour (and efficient code), you can use `pystencils.symb.int_div` and `pystencils.symb.int_rem` +which translate to C ``/`` and ``%``, respectively. + +When expressions are translated in an integer type context, the Python ``/`` operator (or `sympy.Div`) +will also be converted to C-style ``/`` integer division. +Still, use of ``/`` for integers is discouraged, as it is designed to return a floating-point value in Python. diff --git a/docs/source/api/symbolic_language/sympyextensions.rst b/docs/source/api/symbolic_language/sympyextensions.rst new file mode 100644 index 000000000..413746cd4 --- /dev/null +++ b/docs/source/api/symbolic_language/sympyextensions.rst @@ -0,0 +1,6 @@ +------------------- +Extensions to SymPy +------------------- + +.. automodule:: pystencils.symb + :members: diff --git a/docs/source/api/sympyextensions/index.rst b/docs/source/api/sympyextensions/index.rst deleted file mode 100644 index 606a36771..000000000 --- a/docs/source/api/sympyextensions/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -***************** -Symbolic Language -***************** - -.. toctree:: - :maxdepth: 1 - - field - astnodes - diff --git a/src/pystencils/symb.py b/src/pystencils/symb.py new file mode 100644 index 000000000..0c682b261 --- /dev/null +++ b/src/pystencils/symb.py @@ -0,0 +1,23 @@ +"""pystencils extensions to the SymPy symbolic language.""" + +from .sympyextensions.integer_functions import ( + bitwise_and, + bitwise_or, + bitwise_xor, + bit_shift_left, + bit_shift_right, + int_div, + int_rem, + int_power_of_2, +) + +__all__ = [ + "bitwise_and", + "bitwise_or", + "bitwise_xor", + "bit_shift_left", + "bit_shift_right", + "int_div", + "int_rem", + "int_power_of_2", +] diff --git a/src/pystencils/sympyextensions/integer_functions.py b/src/pystencils/sympyextensions/integer_functions.py index 2f48b42b2..600562ad1 100644 --- a/src/pystencils/sympyextensions/integer_functions.py +++ b/src/pystencils/sympyextensions/integer_functions.py @@ -45,14 +45,14 @@ class bitwise_or(IntegerFunctionTwoArgsMixIn): # noinspection PyPep8Naming class int_div(IntegerFunctionTwoArgsMixIn): - """C-style integer division,""" + """C-style round-to-zero integer division""" def _eval_op(self, arg1, arg2): return int(arg1 / arg2) class int_rem(IntegerFunctionTwoArgsMixIn): - """C-style integer remainder""" + """C-style round-to-zero integer remainder""" def _eval_op(self, arg1, arg2): div = int(arg1 / arg2) -- GitLab