diff --git a/docs/source/api/index.rst b/docs/source/api/index.rst index 9af45d147dd6b0c6f9b24cb7794bb8e87b67fed1..4763300a13d7ae5b363425977650f435f04fc0ec 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 a435c716c7fe044d8f56cef599ea247297fb4a75..a76d39a3a10df67e853558b52752a1cdf107562e 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 0000000000000000000000000000000000000000..bf478414ba09068e3bb3d0ca6a08a95f1a113c6c --- /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 0000000000000000000000000000000000000000..413746cd44a8d6da7645f8203e7a8938741d27b0 --- /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 606a36771e583f244d008483768ceae237ec8177..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..0c682b26113c70ca2304bc63a15a6aa7e8d8ad9f --- /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 2f48b42b29627c464a55557e1eec8c5c87a8155a..600562ad1bb9970b36c9963ff71fc24ecca01f28 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)