Commit 9604ddc5 authored by Rafal Skolasinski's avatar Rafal Skolasinski

fix compatibility problems with SymPy 1.2 and 1.3, closes #231, #225

parent 84d1e87f
Pipeline #12508 passed with stages
in 5 minutes and 37 seconds
......@@ -160,7 +160,15 @@ def sympify(expr, locals=None):
'"locals" will not be used.',
RuntimeWarning,
stacklevel=2)
return expr
# We assume that all present functions, like "sin", "cos", will be
# provided by user during the final evaluation through "params".
# Therefore we make sure they are defined as AppliedUndef, not built-in
# sympy types.
subs = {r: sympy.Function(str(r.func))(*r.args)
for r in expr.atoms(sympy.Function)}
return expr.subs(subs)
# if ``expr`` is not a "sympy" then we proceed with sympifying process
if locals is None:
......@@ -191,14 +199,6 @@ def sympify(expr, locals=None):
else:
del converter[list]
# We assume that all present functions, like "sin", "cos", will be
# provided by user during the final evaluation through "params".
# Therefore we make sure they are define as AppliedUndef, not built-in
# sympy types.
subs = {r: sympy.Symbol(str(r.func))(*r.args)
for r in hamiltonian.atoms(sympy.Function)}
hamiltonian = hamiltonian.subs(subs)
return hamiltonian
......
......@@ -458,9 +458,16 @@ def _discretize_expression(expression, coords):
class _NumericPrinter(LambdaPrinter):
def __init__(self):
LambdaPrinter.__init__(self)
if 'allow_unknown_functions' in LambdaPrinter._default_settings:
settings = {'allow_unknown_functions': True}
else:
# We're on Sympy without "allow_unknown_functions" setting
settings = {}
LambdaPrinter.__init__(self, settings=settings)
self.known_functions = {}
self.known_constants = {'pi': 'pi', 'Pi': 'pi'}
self.known_constants = {'pi': 'pi', 'Pi': 'pi', 'I': 'I'}
def _print_ImaginaryUnit(self, expr):
# prevent sympy from printing 'I' for imaginary unit
......@@ -638,7 +645,10 @@ def _builder_value(expr, coords, grid_spacing, onsite,
header = 'def {}({}):'.format(name, site_string)
func_code = separator.join([header] + list(lines))
namespace = {'pi': np.pi}
# Add "I" to namespace just in case sympy again would miss to replace it
# with Python's 1j as it was the case with SymPy 1.2 when I was argument
# of some function.
namespace = {'pi': np.pi, 'I': 1j}
namespace.update(_cache)
source = []
......
......@@ -23,17 +23,18 @@ from kwant.continuum._common import lambdify
com_A, com_B, com_C = sympy.symbols('A B C')
fA, fB, fC = sympy.symbols('A B C', cls=sympy.Function)
x_op, y_op, z_op = position_operators
kx, ky, kz = momentum_operators
@pytest.mark.parametrize('input_expr, output_expr', [
('k_x * A(x) * k_x', kx * com_A(x_op) * kx),
('[[k_x * A(x) * k_x]]', sympy.Matrix([kx * com_A(x_op) * kx])),
('k_x * A(x) * k_x', kx * fA(x_op) * kx),
('[[k_x * A(x) * k_x]]', sympy.Matrix([kx * fA(x_op) * kx])),
('k_x * sigma_y + k_y * sigma_x', kx * msigma(2) + ky * msigma(1)),
('[[k_x*A(x)*k_x, B(x, y)*k_x], [k_x*B(x, y), C*k_y**2]]',
sympy.Matrix([[kx*com_A(x_op)*kx, com_B(x_op, y_op)*kx],
[kx*com_B(x_op, y_op), com_C*ky**2]])),
sympy.Matrix([[kx*fA(x_op)*kx, fB(x_op, y_op)*kx],
[kx*fB(x_op, y_op), com_C*ky**2]])),
('kron(sigma_x, sigma_y)', TensorProduct(msigma(1), msigma(2))),
('identity(2)', sympy.eye(2)),
('eye(2)', sympy.eye(2)),
......@@ -49,7 +50,7 @@ def test_sympify(input_expr, output_expr):
('k_x', kx + ky, {'k_x': 'k_x + k_y'}),
('x', x_op + y_op, {'x': 'x + y'}),
('A', com_A + com_B, {'A': 'A + B'}),
('A', com_A + com_B(x_op), {'A': 'A + B(x)'}),
('A', com_A + fB(x_op), {'A': 'A + B(x)'}),
('A', msigma(2), {'A': "[[0, -1j], [1j, 0]]"}),
])
def test_sympify_substitutions(input_expr, output_expr, subs):
......@@ -106,7 +107,8 @@ expr2 = non_x*A*non_x + x**2 * A*2 * x + B*non_x/2 + non_x*B/2 + x + A + non_x +
def test_monomials():
f, g, a, b = sympy.symbols('f g a b')
a, b = sympy.symbols('a b')
f, g = sympy.symbols('f g', cls=sympy.Function)
assert monomials(expr2, x) == {x**3: 2*A, 1: A, x: 2 + A**(-1) + B, x**2: A}
assert monomials(expr1, x) == {x**2: A + B, x**3: A}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment