Skip to content
Snippets Groups Projects
Commit 4e87a215 authored by Markus Holzer's avatar Markus Holzer
Browse files

Merge branch 'FIX_sympy_1.6' into 'master'

Fix sympy 1.6

See merge request pycodegen/pystencils!157
parents e685321c 1078bd53
No related branches found
No related tags found
No related merge requests found
...@@ -13,6 +13,7 @@ tests-and-coverage: ...@@ -13,6 +13,7 @@ tests-and-coverage:
- $ENABLE_NIGHTLY_BUILDS - $ENABLE_NIGHTLY_BUILDS
image: i10git.cs.fau.de:5005/pycodegen/pycodegen/full image: i10git.cs.fau.de:5005/pycodegen/pycodegen/full
script: script:
- pip list
- export NUM_CORES=$(nproc --all) - export NUM_CORES=$(nproc --all)
- mkdir -p ~/.config/matplotlib - mkdir -p ~/.config/matplotlib
- echo "backend:template" > ~/.config/matplotlib/matplotlibrc - echo "backend:template" > ~/.config/matplotlib/matplotlibrc
...@@ -123,7 +124,9 @@ pycodegen-integration: ...@@ -123,7 +124,9 @@ pycodegen-integration:
- git fetch test - git fetch test
- git reset --hard $CI_COMMIT_SHA - git reset --hard $CI_COMMIT_SHA
- cd .. - cd ..
- export PYTHONPATH=`pwd`/pystencils:`pwd`/lbmpy:`pwd`/pygrandchem:`pwd`/pystencils_walberla:`pwd`/lbmpy_walberla - pip install -e pystencils/
- pip install -e lbmpy/
- pip install -e pygrandchem/
- ./install_walberla.sh - ./install_walberla.sh
- export NUM_CORES=$(nproc --all) - export NUM_CORES=$(nproc --all)
- mkdir -p ~/.config/matplotlib - mkdir -p ~/.config/matplotlib
...@@ -135,7 +138,11 @@ pycodegen-integration: ...@@ -135,7 +138,11 @@ pycodegen-integration:
- cd ../pygrandchem - cd ../pygrandchem
- py.test -v -n $NUM_CORES . - py.test -v -n $NUM_CORES .
- cd ../walberla/build/ - cd ../walberla/build/
- make CodegenJacobiCPU CodegenJacobiGPU MicroBenchmarkGpuLbm LbCodeGenerationExample - make CodegenJacobiCPU CodegenJacobiGPU CodegenPoisson MicroBenchmarkGpuLbm LbCodeGenerationExample UniformGridBenchmarkGPU_trt UniformGridBenchmarkGPU_entropic_kbc_n4
- cd apps/benchmarks/UniformGridGPU
- make -j $NUM_CORES
- cd ../UniformGridGenerated
- make -j $NUM_CORES
tags: tags:
- docker - docker
- cuda - cuda
......
...@@ -66,6 +66,7 @@ try: ...@@ -66,6 +66,7 @@ try:
if int(sympy_version[0]) <= 1 and int(sympy_version[1]) <= 4: if int(sympy_version[0]) <= 1 and int(sympy_version[1]) <= 4:
def hash_fun(self): def hash_fun(self):
return hash((self.lhs, self.rhs)) return hash((self.lhs, self.rhs))
Assignment.__hash__ = hash_fun Assignment.__hash__ = hash_fun
except Exception: except Exception:
pass pass
...@@ -94,16 +95,19 @@ def assignment_from_stencil(stencil_array, input_field, output_field, ...@@ -94,16 +95,19 @@ def assignment_from_stencil(stencil_array, input_field, output_field,
... [0, 6, 0]] ... [0, 6, 0]]
By default 'visual ordering is used - i.e. the stencil is applied as the nested lists are written down By default 'visual ordering is used - i.e. the stencil is applied as the nested lists are written down
>>> assignment_from_stencil(stencil, f, g, order='visual') >>> expected_output = Assignment(g[0, 0], 3*f[-1, 0] + 6*f[0, -1] + 4*f[0, 0] + 2*f[0, 1] + 5*f[1, 0])
Assignment(g_C, 3*f_W + 6*f_S + 4*f_C + 2*f_N + 5*f_E) >>> assignment_from_stencil(stencil, f, g, order='visual') == expected_output
True
'numpy' ordering uses the first coordinate of the stencil array for x offset, second for y offset etc. 'numpy' ordering uses the first coordinate of the stencil array for x offset, second for y offset etc.
>>> assignment_from_stencil(stencil, f, g, order='numpy') >>> expected_output = Assignment(g[0, 0], 2*f[-1, 0] + 3*f[0, -1] + 4*f[0, 0] + 5*f[0, 1] + 6*f[1, 0])
Assignment(g_C, 2*f_W + 3*f_S + 4*f_C + 5*f_N + 6*f_E) >>> assignment_from_stencil(stencil, f, g, order='numpy') == expected_output
True
You can also pass field accesses to apply the stencil at an already shifted position: You can also pass field accesses to apply the stencil at an already shifted position:
>>> assignment_from_stencil(stencil, f[1, 0], g[2, 0]) >>> expected_output = Assignment(g[2, 0], 3*f[0, 0] + 6*f[1, -1] + 4*f[1, 0] + 2*f[1, 1] + 5*f[2, 0])
Assignment(g_2E, 3*f_C + 6*f_SE + 4*f_E + 2*f_NE + 5*f_2E) >>> assignment_from_stencil(stencil, f[1, 0], g[2, 0]) == expected_output
True
""" """
from pystencils.field import Field from pystencils.field import Field
......
import itertools import itertools
import warnings
from collections import defaultdict from collections import defaultdict
import numpy as np import numpy as np
...@@ -172,18 +171,6 @@ class FiniteDifferenceStencilDerivation: ...@@ -172,18 +171,6 @@ class FiniteDifferenceStencilDerivation:
f = field_access f = field_access
return sum(f.get_shifted(*offset) * weight for offset, weight in zip(self.stencil, self.weights)) return sum(f.get_shifted(*offset) * weight for offset, weight in zip(self.stencil, self.weights))
def as_matrix(self):
warnings.warn("as_matrix is deprecated and may be removed in the near future."
"Please use as_array instead which will return an MutableDenseNDimArray."
"as_array therefore can also work in 3 dimensions", category=DeprecationWarning)
dim = len(self.stencil[0])
assert dim == 2
max_offset = max(max(abs(e) for e in direction) for direction in self.stencil)
result = sp.Matrix(2 * max_offset + 1, 2 * max_offset + 1, lambda i, j: 0)
for direction, weight in zip(self.stencil, self.weights):
result[max_offset - direction[1], max_offset + direction[0]] = weight
return result
def __array__(self): def __array__(self):
return np.array(self.as_array().tolist()) return np.array(self.as_array().tolist())
......
...@@ -21,10 +21,13 @@ def diffusion(scalar, diffusion_coeff, idx=None): ...@@ -21,10 +21,13 @@ def diffusion(scalar, diffusion_coeff, idx=None):
Examples: Examples:
>>> f = Field.create_generic('f', spatial_dimensions=2) >>> f = Field.create_generic('f', spatial_dimensions=2)
>>> d = sp.Symbol("d")
>>> dx = sp.Symbol("dx")
>>> diffusion_term = diffusion(scalar=f, diffusion_coeff=sp.Symbol("d")) >>> diffusion_term = diffusion(scalar=f, diffusion_coeff=sp.Symbol("d"))
>>> discretization = Discretization2ndOrder() >>> discretization = Discretization2ndOrder()
>>> discretization(diffusion_term) >>> expected_output = ((f[-1, 0] + f[0, -1] - 4*f[0, 0] + f[0, 1] + f[1, 0]) * d) / dx**2
(f_W*d + f_S*d - 4*f_C*d + f_N*d + f_E*d)/dx**2 >>> sp.simplify(discretization(diffusion_term) - expected_output)
0
""" """
if isinstance(scalar, Field): if isinstance(scalar, Field):
first_arg = scalar.center first_arg = scalar.center
...@@ -313,8 +316,9 @@ def discretize_center(term, symbols_to_field_dict, dx, dim=3): ...@@ -313,8 +316,9 @@ def discretize_center(term, symbols_to_field_dict, dx, dim=3):
>>> term >>> term
x*x^Delta^0 x*x^Delta^0
>>> f = Field.create_generic('f', spatial_dimensions=3) >>> f = Field.create_generic('f', spatial_dimensions=3)
>>> discretize_center(term, { x: f }, dx=1, dim=3) >>> expected_output = f[0, 0, 0] * (-f[-1, 0, 0]/2 + f[1, 0, 0]/2)
f_C*(-f_W/2 + f_E/2) >>> sp.simplify(discretize_center(term, { x: f }, dx=1, dim=3) - expected_output)
0
""" """
substitutions = {} substitutions = {}
for symbols, field in symbols_to_field_dict.items(): for symbols, field in symbols_to_field_dict.items():
...@@ -396,8 +400,10 @@ def discretize_divergence(vector_term, symbols_to_field_dict, dx): ...@@ -396,8 +400,10 @@ def discretize_divergence(vector_term, symbols_to_field_dict, dx):
>>> x, dx = sp.symbols("x dx") >>> x, dx = sp.symbols("x dx")
>>> grad_x = grad(x, dim=3) >>> grad_x = grad(x, dim=3)
>>> f = Field.create_generic('f', spatial_dimensions=3) >>> f = Field.create_generic('f', spatial_dimensions=3)
>>> sp.simplify(discretize_divergence(grad_x, {x : f}, dx)) >>> expected_output = (f[-1, 0, 0] + f[0, -1, 0] + f[0, 0, -1] -
(f_W + f_S + f_B - 6*f_C + f_T + f_N + f_E)/dx**2 ... 6*f[0, 0, 0] + f[0, 0, 1] + f[0, 1, 0] + f[1, 0, 0])/dx**2
>>> sp.simplify(discretize_divergence(grad_x, {x : f}, dx) - expected_output)
0
""" """
dim = len(vector_term) dim = len(vector_term)
result = 0 result = 0
......
...@@ -7,6 +7,7 @@ from typing import Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Ty ...@@ -7,6 +7,7 @@ from typing import Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Ty
import sympy as sp import sympy as sp
from sympy.functions import Abs from sympy.functions import Abs
from sympy.core.numbers import Zero
from pystencils.assignment import Assignment from pystencils.assignment import Assignment
from pystencils.data_types import cast_func, get_base_type, get_type_of_expression from pystencils.data_types import cast_func, get_base_type, get_type_of_expression
...@@ -260,8 +261,8 @@ def subs_additive(expr: sp.Expr, replacement: sp.Expr, subexpression: sp.Expr, ...@@ -260,8 +261,8 @@ def subs_additive(expr: sp.Expr, replacement: sp.Expr, subexpression: sp.Expr,
if not param_list: if not param_list:
return current_expr return current_expr
else: else:
if current_expr.func == sp.Mul and sp.numbers.Zero() in param_list: if current_expr.func == sp.Mul and Zero() in param_list:
return sp.numbers.Zero() return Zero()
else: else:
return current_expr.func(*param_list, evaluate=False) return current_expr.func(*param_list, evaluate=False)
......
This diff is collapsed.
...@@ -11,8 +11,11 @@ def test_sympy_optimizations(): ...@@ -11,8 +11,11 @@ def test_sympy_optimizations():
x, y, z = pystencils.fields('x, y, z: float32[2d]') x, y, z = pystencils.fields('x, y, z: float32[2d]')
# Triggers Sympy's expm1 optimization # Triggers Sympy's expm1 optimization
# Sympy's expm1 optimization is tedious to use and the behaviour is highly depended on the sympy version. In
# some cases the exp expression has to be encapsulated in brackets or multiplied with 1 or 1.0
# for sympy to work properly ...
assignments = pystencils.AssignmentCollection({ assignments = pystencils.AssignmentCollection({
x[0, 0]: sp.exp(y[0, 0]) - 1 x[0, 0]: 1.0 * (sp.exp(y[0, 0]) - 1)
}) })
assignments = optimize_assignments(assignments, optims_pystencils_cpu) assignments = optimize_assignments(assignments, optims_pystencils_cpu)
...@@ -28,7 +31,7 @@ def test_evaluate_constant_terms(): ...@@ -28,7 +31,7 @@ def test_evaluate_constant_terms():
for target in ('cpu', 'gpu'): for target in ('cpu', 'gpu'):
x, y, z = pystencils.fields('x, y, z: float32[2d]') x, y, z = pystencils.fields('x, y, z: float32[2d]')
# Triggers Sympy's expm1 optimization # Triggers Sympy's cos optimization
assignments = pystencils.AssignmentCollection({ assignments = pystencils.AssignmentCollection({
x[0, 0]: -sp.cos(1) + y[0, 0] x[0, 0]: -sp.cos(1) + y[0, 0]
}) })
...@@ -53,8 +56,6 @@ def test_do_not_evaluate_constant_terms(): ...@@ -53,8 +56,6 @@ def test_do_not_evaluate_constant_terms():
x[0, 0]: -sp.cos(1) + y[0, 0] x[0, 0]: -sp.cos(1) + y[0, 0]
}) })
optimize_assignments(assignments, optimizations)
ast = pystencils.create_kernel(assignments, target=target) ast = pystencils.create_kernel(assignments, target=target)
code = pystencils.get_code_str(ast) code = pystencils.get_code_str(ast)
assert 'cos(' in code assert 'cos(' in code
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment