Commit 7b4c3f2d authored by Martin Bauer's avatar Martin Bauer
Browse files

Refactoring of plotting and stencil plotting

- stencil plotting & transformation now in ps.stencil
- additional documentation & notebooks
parent 0998f2e1
Pipeline #15208 passed with stage
in 3 minutes and 34 seconds
[flake8]
max-line-length=120
exclude=pystencils/jupytersetup.py,
pystencils/plot2d.py
exclude=pystencils/jupyter.py,
pystencils/plot.py
pystencils/session.py
ignore = W293 W503 W291
......@@ -66,7 +66,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"3.84 ms ± 36.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
"3.93 ms ± 40 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
]
}
],
......@@ -132,7 +132,7 @@
],
"source": [
"plt.figure(figsize=(3,3))\n",
"ps.visualize_stencil_expression(symbolic_description.rhs)"
"ps.stencil.plot_expression(symbolic_description.rhs)"
]
},
{
......@@ -180,7 +180,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"639 µs ± 35 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
"643 µs ± 8.66 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
]
}
],
......@@ -615,7 +615,7 @@
"</svg>\n"
],
"text/plain": [
"<graphviz.files.Source at 0x7fc7dc51b2e8>"
"<graphviz.files.Source at 0x7ff8a018e7f0>"
]
},
"execution_count": 19,
......@@ -995,129 +995,129 @@
"<g id=\"graph0\" class=\"graph\" transform=\"scale(.9826 .9826) rotate(0) translate(4 472)\">\n",
"<title>%3</title>\n",
"<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-472 692.083,-472 692.083,4 -4,4\"/>\n",
"<!-- 140495254316984 -->\n",
"<!-- 140704680405368 -->\n",
"<g id=\"node1\" class=\"node\">\n",
"<title>140495254316984</title>\n",
"<title>140704680405368</title>\n",
"<ellipse fill=\"#a056db\" stroke=\"#000000\" cx=\"219.8449\" cy=\"-450\" rx=\"107.781\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"219.8449\" y=\"-446.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Func: kernel (dst,img,w_2)</text>\n",
"</g>\n",
"<!-- 140495254318440 -->\n",
"<!-- 140704680405256 -->\n",
"<g id=\"node11\" class=\"node\">\n",
"<title>140495254318440</title>\n",
"<title>140704680405256</title>\n",
"<ellipse fill=\"#dbc256\" stroke=\"#000000\" cx=\"219.8449\" cy=\"-378\" rx=\"31.6951\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"219.8449\" y=\"-374.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Block</text>\n",
"</g>\n",
"<!-- 140495254316984&#45;&gt;140495254318440 -->\n",
"<!-- 140704680405368&#45;&gt;140704680405256 -->\n",
"<g id=\"edge10\" class=\"edge\">\n",
"<title>140495254316984&#45;&gt;140495254318440</title>\n",
"<title>140704680405368&#45;&gt;140704680405256</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M219.8449,-431.8314C219.8449,-424.131 219.8449,-414.9743 219.8449,-406.4166\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"223.345,-406.4132 219.8449,-396.4133 216.345,-406.4133 223.345,-406.4132\"/>\n",
"</g>\n",
"<!-- 140495254317656 -->\n",
"<!-- 140704680405032 -->\n",
"<g id=\"node2\" class=\"node\">\n",
"<title>140495254317656</title>\n",
"<title>140704680405032</title>\n",
"<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"144.8449\" cy=\"-306\" rx=\"61.99\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"144.8449\" y=\"-302.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_img_22</text>\n",
"</g>\n",
"<!-- 140495254316256 -->\n",
"<!-- 140704680404416 -->\n",
"<g id=\"node3\" class=\"node\">\n",
"<title>140495254316256</title>\n",
"<title>140704680404416</title>\n",
"<ellipse fill=\"#3498db\" stroke=\"#000000\" cx=\"295.8449\" cy=\"-306\" rx=\"70.6878\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"295.8449\" y=\"-302.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Loop over dim 0</text>\n",
"</g>\n",
"<!-- 140495254316032 -->\n",
"<!-- 140704680404080 -->\n",
"<g id=\"node10\" class=\"node\">\n",
"<title>140495254316032</title>\n",
"<title>140704680404080</title>\n",
"<ellipse fill=\"#dbc256\" stroke=\"#000000\" cx=\"295.8449\" cy=\"-234\" rx=\"31.6951\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"295.8449\" y=\"-230.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Block</text>\n",
"</g>\n",
"<!-- 140495254316256&#45;&gt;140495254316032 -->\n",
"<!-- 140704680404416&#45;&gt;140704680404080 -->\n",
"<g id=\"edge7\" class=\"edge\">\n",
"<title>140495254316256&#45;&gt;140495254316032</title>\n",
"<title>140704680404416&#45;&gt;140704680404080</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M295.8449,-287.8314C295.8449,-280.131 295.8449,-270.9743 295.8449,-262.4166\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"299.345,-262.4132 295.8449,-252.4133 292.345,-262.4133 299.345,-262.4132\"/>\n",
"</g>\n",
"<!-- 140495254318496 -->\n",
"<!-- 140704681164528 -->\n",
"<g id=\"node4\" class=\"node\">\n",
"<title>140495254318496</title>\n",
"<title>140704681164528</title>\n",
"<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"57.8449\" cy=\"-162\" rx=\"57.6901\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"57.8449\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_dst_00</text>\n",
"</g>\n",
"<!-- 140495254316592 -->\n",
"<!-- 140704680403520 -->\n",
"<g id=\"node5\" class=\"node\">\n",
"<title>140495254316592</title>\n",
"<title>140704680403520</title>\n",
"<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"208.8449\" cy=\"-162\" rx=\"74.9875\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"208.8449\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_img_22_01</text>\n",
"</g>\n",
"<!-- 140495254317320 -->\n",
"<!-- 140704680403352 -->\n",
"<g id=\"node6\" class=\"node\">\n",
"<title>140495254317320</title>\n",
"<title>140704680403352</title>\n",
"<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"383.8449\" cy=\"-162\" rx=\"81.7856\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"383.8449\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_img_22_0m1</text>\n",
"</g>\n",
"<!-- 140495254318664 -->\n",
"<!-- 140704680404024 -->\n",
"<g id=\"node7\" class=\"node\">\n",
"<title>140495254318664</title>\n",
"<title>140704680404024</title>\n",
"<ellipse fill=\"#3498db\" stroke=\"#000000\" cx=\"554.8449\" cy=\"-162\" rx=\"70.6878\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"554.8449\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Loop over dim 1</text>\n",
"</g>\n",
"<!-- 140495254318776 -->\n",
"<!-- 140704680404360 -->\n",
"<g id=\"node9\" class=\"node\">\n",
"<title>140495254318776</title>\n",
"<title>140704680404360</title>\n",
"<ellipse fill=\"#dbc256\" stroke=\"#000000\" cx=\"554.8449\" cy=\"-90\" rx=\"31.6951\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"554.8449\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Block</text>\n",
"</g>\n",
"<!-- 140495254318664&#45;&gt;140495254318776 -->\n",
"<!-- 140704680404024&#45;&gt;140704680404360 -->\n",
"<g id=\"edge2\" class=\"edge\">\n",
"<title>140495254318664&#45;&gt;140495254318776</title>\n",
"<title>140704680404024&#45;&gt;140704680404360</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M554.8449,-143.8314C554.8449,-136.131 554.8449,-126.9743 554.8449,-118.4166\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"558.345,-118.4132 554.8449,-108.4133 551.345,-118.4133 558.345,-118.4132\"/>\n",
"</g>\n",
"<!-- 140495254317040 -->\n",
"<!-- 140704680403968 -->\n",
"<g id=\"node8\" class=\"node\">\n",
"<title>140495254317040</title>\n",
"<title>140704680403968</title>\n",
"<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"554.8449\" cy=\"-18\" rx=\"133.4768\" ry=\"18\"/>\n",
"<text text-anchor=\"middle\" x=\"554.8449\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_dst_00[_stride_dst_1*ctr_1]</text>\n",
"</g>\n",
"<!-- 140495254318776&#45;&gt;140495254317040 -->\n",
"<!-- 140704680404360&#45;&gt;140704680403968 -->\n",
"<g id=\"edge1\" class=\"edge\">\n",
"<title>140495254318776&#45;&gt;140495254317040</title>\n",
"<title>140704680404360&#45;&gt;140704680403968</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M554.8449,-71.8314C554.8449,-64.131 554.8449,-54.9743 554.8449,-46.4166\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"558.345,-46.4132 554.8449,-36.4133 551.345,-46.4133 558.345,-46.4132\"/>\n",
"</g>\n",
"<!-- 140495254316032&#45;&gt;140495254318496 -->\n",
"<!-- 140704680404080&#45;&gt;140704681164528 -->\n",
"<g id=\"edge3\" class=\"edge\">\n",
"<title>140495254316032&#45;&gt;140495254318496</title>\n",
"<title>140704680404080&#45;&gt;140704681164528</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M267.6085,-225.4579C228.6723,-213.6789 157.8187,-192.2442 109.3243,-177.5736\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"110.2227,-174.1888 99.6376,-174.6432 108.1957,-180.8889 110.2227,-174.1888\"/>\n",
"</g>\n",
"<!-- 140495254316032&#45;&gt;140495254316592 -->\n",
"<!-- 140704680404080&#45;&gt;140704680403520 -->\n",
"<g id=\"edge4\" class=\"edge\">\n",
"<title>140495254316032&#45;&gt;140495254316592</title>\n",
"<title>140704680404080&#45;&gt;140704680403520</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M277.8184,-219.0816C266.2777,-209.5306 251.0436,-196.9231 237.8284,-185.9864\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"239.8475,-183.1143 229.9121,-179.4349 235.3845,-188.507 239.8475,-183.1143\"/>\n",
"</g>\n",
"<!-- 140495254316032&#45;&gt;140495254317320 -->\n",
"<!-- 140704680404080&#45;&gt;140704680403352 -->\n",
"<g id=\"edge5\" class=\"edge\">\n",
"<title>140495254316032&#45;&gt;140495254317320</title>\n",
"<title>140704680404080&#45;&gt;140704680403352</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M314.0785,-219.0816C325.7519,-209.5306 341.1611,-196.9231 354.5282,-185.9864\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"357.0123,-188.4762 362.5355,-179.4349 352.5796,-183.0585 357.0123,-188.4762\"/>\n",
"</g>\n",
"<!-- 140495254316032&#45;&gt;140495254318664 -->\n",
"<!-- 140704680404080&#45;&gt;140704680404024 -->\n",
"<g id=\"edge6\" class=\"edge\">\n",
"<title>140495254316032&#45;&gt;140495254318664</title>\n",
"<title>140704680404080&#45;&gt;140704680404024</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M324.552,-226.0196C365.9645,-214.5073 443.366,-192.9903 496.9349,-178.0985\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"497.9488,-181.4495 506.646,-175.3989 496.0739,-174.7052 497.9488,-181.4495\"/>\n",
"</g>\n",
"<!-- 140495254318440&#45;&gt;140495254317656 -->\n",
"<!-- 140704680405256&#45;&gt;140704680405032 -->\n",
"<g id=\"edge8\" class=\"edge\">\n",
"<title>140495254318440&#45;&gt;140495254317656</title>\n",
"<title>140704680405256&#45;&gt;140704680405032</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M203.571,-362.3771C193.8398,-353.0351 181.2651,-340.9635 170.2498,-330.3888\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"172.5648,-327.7594 162.9271,-323.3589 167.7171,-332.8091 172.5648,-327.7594\"/>\n",
"</g>\n",
"<!-- 140495254318440&#45;&gt;140495254316256 -->\n",
"<!-- 140704680405256&#45;&gt;140704680404416 -->\n",
"<g id=\"edge9\" class=\"edge\">\n",
"<title>140495254318440&#45;&gt;140495254316256</title>\n",
"<title>140704680405256&#45;&gt;140704680404416</title>\n",
"<path fill=\"none\" stroke=\"#000000\" d=\"M236.3357,-362.3771C246.1257,-353.1023 258.7558,-341.137 269.86,-330.6172\"/>\n",
"<polygon fill=\"#000000\" stroke=\"#000000\" points=\"272.3977,-333.0344 277.2501,-323.6161 267.5835,-327.9527 272.3977,-333.0344\"/>\n",
"</g>\n",
......@@ -1125,7 +1125,7 @@
"</svg>\n"
],
"text/plain": [
"<graphviz.files.Source at 0x7fc798393fd0>"
"<graphviz.files.Source at 0x7ff84a432e10>"
]
},
"execution_count": 32,
......
......@@ -70,13 +70,6 @@
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"!\n"
]
},
{
"data": {
"image/png": "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\n",
......@@ -188,9 +181,8 @@
" timeloop(10)\n",
" result = None\n",
"else:\n",
" ps_notebook.set_display_mode('video')\n",
" ani = ps.plot2d.scalar_field_animation(timeloop, rescale=True, frames=300)\n",
" result = ps_notebook.display_animation(ani)\n",
" ani = ps.plot.scalar_field_animation(timeloop, rescale=True, frames=300)\n",
" result = ps.jupyter.display_as_html_video(ani)\n",
"result"
]
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -9,6 +9,7 @@ API Reference
datahandling.rst
configuration.rst
field.rst
stencil.rst
finite_differences.rst
plot.rst
ast.rst
......@@ -2,7 +2,7 @@
Plotting and Animation
**********************
.. automodule:: pystencils.plot2d
.. automodule:: pystencils.plot
:members:
*******
Stencil
*******
.. automodule:: pystencils.stencil
:members:
......@@ -15,6 +15,7 @@ It is a good idea to download them and run them directly to be able to play arou
/notebooks/05_tutorial_phasefield_spinodal_decomposition.ipynb
/notebooks/06_tutorial_phasefield_dentritic_growth.ipynb
/notebooks/demo_assignment_collection.ipynb
/notebooks/demo_plotting_and_animation.ipynb
/notebooks/demo_derivatives.ipynb
/notebooks/demo_benchmark.ipynb
/notebooks/demo_wave_equation.ipynb
......@@ -10,8 +10,8 @@ from .assignment import Assignment, assignment_from_stencil
from .sympyextensions import SymbolCreator
from .datahandling import create_data_handling
from .kernel_decorator import kernel
from .stencils import visualize_stencil_expression
from . import fd
from . import stencil as stencil
__all__ = ['Field', 'FieldType', 'fields',
......@@ -26,4 +26,4 @@ __all__ = ['Field', 'FieldType', 'fields',
'create_data_handling',
'kernel',
'fd',
'visualize_stencil_expression']
'stencil']
......@@ -159,8 +159,8 @@ class FiniteDifferenceStencilDerivation:
self.is_isotropic = is_isotropic
def visualize(self):
from pystencils.stencils import visualize_stencil
visualize_stencil(self.stencil, data=self.weights)
from pystencils.stencil import plot
plot(self.stencil, data=self.weights)
def apply(self, field_access: Field.Access):
f = field_access
......
......@@ -8,7 +8,7 @@ from sympy.core.cache import cacheit
from pystencils.alignedarray import aligned_empty
from pystencils.data_types import create_type, StructType
from pystencils.kernelparameters import FieldShapeSymbol, FieldStrideSymbol
from pystencils.stencils import offset_to_direction_string, direction_string_to_offset
from pystencils.stencil import offset_to_direction_string, direction_string_to_offset
from pystencils.sympyextensions import is_integer_sequence
import pickle
import hashlib
......
import pystencils.plot2d as plt
import pystencils.plot as plt
import matplotlib.animation as animation
from IPython.display import HTML
from tempfile import NamedTemporaryFile
......@@ -125,13 +125,13 @@ def display_in_extra_window(*_, **__):
# ------- Version 3: Animation is shown in images that are updated directly in website --------------
def display_as_html_image(animation, show=True, iterations=10000, *args, **kwargs):
def display_as_html_image(animation, show=True, *args, **kwargs):
from IPython import display
try:
if show:
animation._init_draw()
for i in range(iterations):
for _ in animation.frame_seq:
if show:
fig = plt.gcf()
display.display(fig)
......
......@@ -5,7 +5,6 @@ matplotlib normally uses.
"""
from matplotlib.pyplot import *
from itertools import cycle
from matplotlib.text import Text
def vector_field(array, step=2, **kwargs):
......@@ -67,6 +66,26 @@ def scalar_field(array, **kwargs):
return res
def scalar_field_surface(array, **kwargs):
"""Plots scalar field as 3D surface
Args:
array: the two dimensional numpy array to plot
kwargs: keyword arguments passed to :func:`mpl_toolkits.mplot3d.Axes3D.plot_surface`
"""
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
fig = gcf()
ax = fig.add_subplot(111, projection='3d')
x, y = np.meshgrid(np.arange(array.shape[0]), np.arange(array.shape[1]), indexing='ij')
kwargs.setdefault('rstride', 2)
kwargs.setdefault('cstride', 2)
kwargs.setdefault('color', 'b')
kwargs.setdefault('cmap', cm.coolwarm)
return ax.plot_surface(x, y, array, **kwargs)
def scalar_field_alpha_value(array, color, clip=False, **kwargs):
"""Plots an image with same color everywhere, using the array values as transparency.
......@@ -158,6 +177,7 @@ def phase_plot(phase_field: np.ndarray, linewidth=1.0, clip=True) -> None:
for i in range(phase_field.shape[-1]):
scalar_field_contour(phase_field[..., i], levels=[0.5], colors='k', linewidths=[linewidth])
def sympy_function(expr, x_values=None, **kwargs):
"""Plots the graph of a sympy term that depends on one symbol only.
......@@ -307,14 +327,12 @@ def scalar_field_animation(run_function, plot_setup_function=lambda *_: None, re
return animation.FuncAnimation(fig, update_figure, interval=interval, frames=frames)
def surface_plot_animation(run_function, frames=90, interval=30, **kwargs):
def surface_plot_animation(run_function, frames=90, interval=30, zlim=None, **kwargs):
"""Animation of scalar field as 3D plot."""
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from matplotlib import cm
fig = plt.figure()
fig = gcf()
ax = fig.add_subplot(111, projection='3d')
data = run_function()
x, y = np.meshgrid(np.arange(data.shape[0]), np.arange(data.shape[1]), indexing='ij')
......@@ -323,13 +341,15 @@ def surface_plot_animation(run_function, frames=90, interval=30, **kwargs):
kwargs.setdefault('color', 'b')
kwargs.setdefault('cmap', cm.coolwarm)
ax.plot_surface(x, y, data, **kwargs)
ax.set_zlim(-1.0, 1.0)
if zlim is not None:
ax.set_zlim(*zlim)
def update_figure(*_):
d = run_function()
ax.clear()
plot = ax.plot_surface(x, y, d, **kwargs)
ax.set_zlim(-1.0, 1.0)
if zlim is not None:
ax.set_zlim(*zlim)
return plot,
return animation.FuncAnimation(fig, update_figure, interval=interval, frames=frames, blit=False)
import pystencils.sympy_gmpy_bug_workaround
import pystencils.jupyter
import sympy as sp
import numpy as np
import pystencils as ps
import pystencils.plot2d as plt
import pystencils.jupytersetup as ps_notebook
import pystencils.plot as plt
__all__ = ['sp', 'np', 'ps', 'plt', 'ps_notebook']
__all__ = ['sp', 'np', 'ps', 'plt']
"""This submodule offers functions to work with stencils in expression an offset-list form."""
from typing import Sequence
import numpy as np
import sympy as sp
......@@ -5,15 +6,28 @@ from collections import defaultdict
def inverse_direction(direction):
"""Returns inverse i.e. negative of given direction tuple"""
"""Returns inverse i.e. negative of given direction tuple
Example:
>>> inverse_direction((1, -1, 0))
(-1, 1, 0)
"""
return tuple([-i for i in direction])
def is_valid_stencil(stencil, max_neighborhood=None):
def is_valid(stencil, max_neighborhood=None):
"""
Tests if a nested sequence is a valid stencil i.e. all the inner sequences have the same length.
If max_neighborhood is specified, it is also verified that the stencil does not contain any direction components
with absolute value greater than the maximal neighborhood.
Examples:
>>> is_valid([(1, 0), (1, 0, 0)]) # stencil entries have different length
False
>>> is_valid([(2, 0), (1, 0)])
True
>>> is_valid([(2, 0), (1, 0)], max_neighborhood=1)
False
"""
expected_dim = len(stencil[0])
for d in stencil:
......@@ -26,15 +40,30 @@ def is_valid_stencil(stencil, max_neighborhood=None):
return True
def is_symmetric_stencil(stencil):
"""Tests for every direction d, that -d is also in the stencil"""
def is_symmetric(stencil):
"""Tests for every direction d, that -d is also in the stencil
Examples:
>>> is_symmetric([(1, 0), (0, 1)])
False
>>> is_symmetric([(1, 0), (-1, 0)])
True
"""
for d in stencil:
if inverse_direction(d) not in stencil:
return False
return True
def stencils_have_same_entries(s1, s2):
def have_same_entries(s1, s2):
"""Checks if two stencils are the same
Examples:
>>> stencil1 = [(1, 0), (-1, 0), (0, 1), (0, -1)]
>>> stencil2 = [(-1, 0), (0, -1), (1, 0), (0, 1)]
>>> have_same_entries(stencil1, stencil2)
True
"""
if len(s1) != len(s2):
return False
return len(set(s1) - set(s2)) == 0
......@@ -43,7 +72,7 @@ def stencils_have_same_entries(s1, s2):
# -------------------------------------Expression - Coefficient Form Conversion ----------------------------------------
def stencil_coefficient_dict(expr):
def coefficient_dict(expr):
"""Extracts coefficients in front of field accesses in a expression.
Expression may only access a single field at a single index.
......@@ -57,12 +86,12 @@ def stencil_coefficient_dict(expr):
Examples:
>>> import pystencils as ps
>>> f = ps.fields("f(3) : double[2D]")
>>> field, coeffs, nonlinear_part = stencil_coefficient_dict(2 * f[0, 1](1) + 3 * f[-1, 0](1) + 123)
>>> field, coeffs, nonlinear_part = coefficient_dict(2 * f[0, 1](1) + 3 * f[-1, 0](1) + 123)
>>> assert nonlinear_part == 123 and field == f(1)
>>> sorted(coeffs.items())
[((-1, 0), 3), ((0, 1), 2)]
"""
from .field import Field
from pystencils import Field
expr = expr.expand()
field_accesses = expr.atoms(Field.Access)
fields = set(fa.field for fa in field_accesses)
......@@ -77,70 +106,70 @@ def stencil_coefficient_dict(expr):
field = fields.pop()
idx = accessed_indices.pop()
coefficients = defaultdict(lambda: 0)
coefficients.update({fa.offsets: expr.coeff(fa) for fa in field_accesses})
coeffs = defaultdict(lambda: 0)
coeffs.update({fa.offsets: expr.coeff(fa) for fa in field_accesses})
linear_part = sum(c * field[off](*idx) for off, c in coefficients.items())
linear_part = sum(c * field[off](*idx) for off, c in coeffs.items())
nonlinear_part = expr - linear_part
return field(*idx), coefficients, nonlinear_part
return field(*idx), coeffs, nonlinear_part
def stencil_coefficients(expr):
def coefficients(expr):
"""Returns two lists - one with accessed offsets and one with their coefficients.
Same restrictions as `stencil_coefficient_dict` apply. Expression must not have any nonlinear part
Same restrictions as `coefficient_dict` apply. Expression must not have any nonlinear part
>>> import pystencils as ps
>>> f = ps.fields("f(3) : double[2D]")
>>> coff = stencil_coefficients(2 * f[0, 1](1) + 3 * f[-1, 0](1))
>>> coff = coefficients(2 * f[0, 1](1) + 3 * f[-1, 0](1))
"""
field_center, coefficients, nonlinear_part = stencil_coefficient_dict(expr)
field_center, coeffs, nonlinear_part = coefficient_dict(expr)
assert nonlinear_part == 0
stencil = list(coefficients.keys())
entries = [coefficients[c] for c in stencil]
stencil = list(coeffs.keys())
entries = [coeffs[c] for c in stencil]
return stencil, entries
def stencil_coefficient_list(expr, matrix_form=False):
def coefficient_list(expr, matrix_form=False):
"""Returns stencil coefficients in the form of nested lists
Same restrictions as `stencil_coefficient_dict` apply. Expression must not have any nonlinear part
Same restrictions as `coefficient_dict` apply. Expression must not have any nonlinear part
Examples:
>>> import pystencils as ps
>>> f = ps.fields("f: double[2D]")
>>> stencil_coefficient_list(2 * f[0, 1] + 3 * f[-1, 0])
>>> coefficient_list(2 * f[0, 1] + 3 * f[-1, 0])
[[0, 0, 0], [3, 0, 0], [0, 2, 0]]
>>> stencil_coefficient_list(2 * f[0, 1] + 3 * f[-1, 0], matrix_form=True)
>>> coefficient_list(2 * f[0, 1] + 3 * f[-1, 0], matrix_form=True)
Matrix([
[0, 2, 0],
[3, 0, 0],
[0, 0, 0]])
"""
field_center, coefficients, nonlinear_part = stencil_coefficient_dict(expr)
field_center, coeffs, nonlinear_part = coefficient_dict(expr)
assert nonlinear_part == 0
field = field_center.field
dim = field.spatial_dimensions
max_offsets = defaultdict(lambda: 0)
for offset in coefficients.keys():
for offset in coeffs.keys():
for d, off in enumerate(offset):
max_offsets[d] = max(max_offsets[d], abs(off))
if dim == 1:
result = [coefficients[(i,)] for i in range(-max_offsets[0], max_offsets[0] + 1)]
result = [coeffs[(i,)] for i in range(-max_offsets[0], max_offsets[0] + 1)]