|
| 1 | +from sympy import symbols |
| 2 | +import pytest |
| 3 | + |
| 4 | +from galgebra.ga import Ga |
| 5 | +from galgebra.mv import Dop |
| 6 | + |
| 7 | + |
| 8 | +class TestDop(object): |
| 9 | + |
| 10 | + def test_associativity_and_distributivity(self): |
| 11 | + coords = x, y, z = symbols('x y z', real=True) |
| 12 | + ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) |
| 13 | + v = ga.mv('v', 'vector', f=True) |
| 14 | + laplacian = ga.grad * ga.grad |
| 15 | + rlaplacian = ga.rgrad * ga.rgrad |
| 16 | + |
| 17 | + # check addition distributes |
| 18 | + assert (laplacian + ga.grad) * v == laplacian * v + ga.grad * v != 0 |
| 19 | + assert (laplacian + 1234567) * v == laplacian * v + 1234567 * v != 0 |
| 20 | + # check subtraction distributes |
| 21 | + assert (laplacian - ga.grad) * v == laplacian * v - ga.grad * v != 0 |
| 22 | + assert (laplacian - 1234567) * v == laplacian * v - 1234567 * v != 0 |
| 23 | + # check unary subtraction distributes |
| 24 | + assert (-ga.grad) * v == -(ga.grad * v) != 0 |
| 25 | + # check division is associative |
| 26 | + assert v * (ga.rgrad / 2) == (v * ga.rgrad) / 2 != 0 |
| 27 | + # check multiplication is associative |
| 28 | + assert (20 * ga.grad) * v == 20 * (ga.grad * v) != 0 |
| 29 | + assert v * (ga.rgrad * 20) == (v * ga.rgrad) * 20 != 0 |
| 30 | + assert (ex ^ ga.grad) ^ v == ex ^ (ga.grad ^ v) != 0 |
| 31 | + assert (20 ^ ga.grad) ^ v == 20 ^ (ga.grad ^ v) != 0 |
| 32 | + assert v ^ (ga.rgrad ^ ex) == (v ^ ga.rgrad) ^ ex != 0 |
| 33 | + assert v ^ (ga.rgrad ^ 20) == (v ^ ga.rgrad) ^ 20 != 0 |
| 34 | + |
| 35 | + @pytest.mark.xfail(raises=IndexError) |
| 36 | + def test_empty_dop(self): |
| 37 | + """ Test that dop with zero terms is equivalent to multiplying by zero """ |
| 38 | + coords = x, y, z = symbols('x y z', real=True) |
| 39 | + ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) |
| 40 | + v = ga.mv('v', 'vector', f=True) |
| 41 | + |
| 42 | + make_zero = Dop([], ga=ga) |
| 43 | + assert make_zero * v == 0 |
| 44 | + assert make_zero * make_zero * v == 0 |
| 45 | + assert (make_zero + make_zero) * v == 0 |
| 46 | + assert (-make_zero) * v == 0 |
| 47 | + |
| 48 | + def test_misc(self): |
| 49 | + """ Other miscellaneous tests """ |
| 50 | + coords = x, y, z = symbols('x y z', real=True) |
| 51 | + ga, ex, ey, ez = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords) |
| 52 | + v = ga.mv('v', 'vector', f=True) |
| 53 | + laplacian = ga.grad * ga.grad |
| 54 | + rlaplacian = ga.rgrad * ga.rgrad |
| 55 | + |
| 56 | + # laplacian is a scalar operator, so applying it from either side |
| 57 | + # is the same |
| 58 | + assert laplacian * v == v * rlaplacian |
| 59 | + |
| 60 | + assert laplacian.is_scalar() |
| 61 | + assert not ga.grad.is_scalar() |
| 62 | + |
| 63 | + # inconsistent cmpflg, not clear which side the operator goes on |
| 64 | + with pytest.raises(ValueError): |
| 65 | + ga.grad + ga.rgrad |
| 66 | + with pytest.raises(ValueError): |
| 67 | + ga.grad * ga.rgrad |
| 68 | + |
| 69 | + def test_mixed_algebras(self): |
| 70 | + coords = x, y, z = symbols('x y z', real=True) |
| 71 | + ga1, ex1, ey1, ez1 = Ga.build('e1*x|y|z', g=[1, 1, 1], coords=coords) |
| 72 | + ga2, ex2, ey2, ez2 = Ga.build('e2*x|y|z', g=[1, 1, 1], coords=coords) |
| 73 | + assert ga1 != ga2 |
| 74 | + |
| 75 | + v1 = ga1.mv('v', 'vector', f=True) |
| 76 | + v2 = ga2.mv('v', 'vector', f=True) |
| 77 | + |
| 78 | + with pytest.raises(ValueError): |
| 79 | + ga1.grad * v2 |
| 80 | + with pytest.raises(ValueError): |
| 81 | + v1 * ga2.rgrad |
| 82 | + with pytest.raises(ValueError): |
| 83 | + ga1.grad * ga2.grad |
0 commit comments