def test_constructor_errors(self): ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1]) # list lengths must match with pytest.raises(ValueError, match='same length'): Dop([ex], [], ga=ga) # the two conventions can't be mixed mixed_args = [ (ex, Pdop({})), (Sdop([]), ex), ] with pytest.raises(TypeError, match='pairs'): Dop(mixed_args, ga=ga) # ga must be non-none with pytest.raises(ValueError, match='must not be None'): Dop([], ga=None) # too few arguments with pytest.raises(TypeError, match='0 were given'): Dop(ga=ga) # too many arguments with pytest.raises(TypeError, match='3 were given'): Dop(1, 2, 3, ga=ga)
def test_multiply(self): coords = x, y, z = symbols('x y z', real=True) ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) p = Pdop(x) assert x * p == Sdop([(x, p)]) assert ex * p == Sdop([(ex, p)]) assert p * x == p(x) == S(1) assert p * ex == p(ex) == S(0) assert type(p(ex)) is Mv # These are not defined for consistency with Sdop for op in [operator.xor, operator.or_, operator.lt, operator.gt]: with pytest.raises(TypeError): op(ex, p) with pytest.raises(TypeError): op(p, ex)
def chain_with_pdop(self): x, y = symbols('x y', real=True) s = Sdop([(x, Pdop(x)), (y, Pdop(y))]) # right-multiplication by Pdop chains only the pdiffs sp = s * Pdop(x) assert sp == Sdop([(x, Pdop(x) * Pdop(x)), (y, Pdop(y) * Pdop(x))]) # left-multiplcation by Pdop invokes the product rule ps = Pdop(x) * s assert ps == Sdop([(x, Pdop(x) * Pdop(x)), (1, Pdop(x)), (y, Pdop(y) * Pdop(x))]) # implicit multiplication assert ps == Pdop(x)(s) assert sp == s(Pdop(x)) # no-op pdop assert s == Pdop({})(s) assert s == s(Pdop({}))
def chain_with_mv(self): coords = x, y, z = symbols('x y z', real=True) ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) s = Sdop([(x, Pdop(x)), (y, Pdop(y))]) assert type(ex * s) is Sdop assert type(s * ex) is Mv # type should be preserved even when the result is 0 assert type(ex * Sdop([])) is Sdop assert type(Sdop([]) * ex) is Mv # As discussed with brombo, these operations are not well defined - if # you need them, you should be using `Dop` not `Sdop`. for op in [operator.xor, operator.or_, operator.lt, operator.gt]: with pytest.raises(TypeError): op(ex, s) with pytest.raises(TypeError): op(s, ex)
def test_empty_sdop(self): """ Test that sdop with zero terms is equivalent to multiplying by zero """ coords = x, y, z = symbols('x y z', real=True) ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) v = ga.mv('v', 'vector', f=True) make_zero = Sdop([]) assert make_zero * v == 0 assert make_zero * make_zero * v == 0 assert (make_zero + make_zero) * v == 0 assert (-make_zero) * v == 0
def test_constructor_errors(self): coords = x, y, z = symbols('x y z', real=True) ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) # list lengths must match with pytest.raises(ValueError, match='same length'): Sdop([ex], []) # not a symbol or list with pytest.raises(TypeError, match='symbol or sequence is required'): Sdop(1) # not a pair of lists with pytest.raises(TypeError, match='must be lists'): Sdop([], 1) # too few arguments with pytest.raises(TypeError, match='0 were given'): Sdop() # too many arguments with pytest.raises(TypeError, match='3 were given'): Sdop(1, 2, 3)
def test_associativity_and_distributivity(self): coords = x, y, z = symbols('x y z', real=True) ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) v = ga.mv('v', 'vector', f=True) laplacian = Sdop((ga.grad * ga.grad).terms) # check addition distributes assert (laplacian + 20) * v == laplacian * v + 20 * v != 0 assert (20 + laplacian) * v == laplacian * v + 20 * v != 0 # check subtraction distributes assert (laplacian - 20) * v == laplacian * v - 20 * v != 0 assert (20 - laplacian) * v == 20 * v - laplacian * v != 0 # check unary subtraction distributes assert (-laplacian) * v == -(laplacian * v) != 0 # check multiplication is associative assert (20 * laplacian) * v == 20 * (laplacian * v) != 0 assert (laplacian * laplacian) * v == laplacian * (laplacian * v) != 0
def test_shorthand(self): coords = x, y, z = symbols('x y z', real=True) ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) assert Sdop(x) == Sdop([(S(1), Pdop({x: 1}))])