/ test / test_gprinter.py
test_gprinter.py
  1  from __future__ import annotations
  2  
  3  import os
  4  import unittest
  5  import pytest
  6  import subprocess
  7  from pathlib import Path
  8  
  9  # Make SymPy available to this program:
 10  import sympy 
 11  from sympy import symbols, simplify, sin, cos
 12  
 13  # Make GAlgebra available to this program:
 14  from galgebra.ga import Ga  
 15  # from galgebra.mv import *
 16  from galgebra.printer import Fmt, GaPrinter, Format
 17  # Fmt:       sets the way that a multivector's basis expansion is output.
 18  # GaPrinter: makes GA output a little more readable.
 19  # Format:    turns on latex gprinter.
 20  from galgebra.gprinter import gFormat, gprint, gxpdf, gPrint_Function
 21  
 22  ROOT = Path(__file__).parent.parent
 23  DIR_TEST = ROOT / 'test'
 24  DIR_GENERATED = DIR_TEST / 'generated'
 25  DIR_FIXTURES = DIR_TEST / 'fixtures'
 26  DIR_DIFF = DIR_TEST / 'diff'
 27  
 28  
 29  def lin_tran():
 30      gFormat()
 31      gPrint_Function()
 32      (x, y, z) = xyz = symbols('x,y,z',real=True)
 33      (o3d, ex, ey, ez) = Ga.build('e_x e_y e_z', g=[1, 1, 1], coords=xyz)
 34      grad = o3d.grad
 35      (u, v) = uv = symbols('u,v',real=True)
 36      (g2d, eu, ev) = Ga.build('e_u e_v', coords=uv)
 37      grad_uv = g2d.grad
 38      v_xyz = o3d.mv('v','vector')
 39      A_xyz = o3d.mv('A','vector',f=True)
 40      A_uv = g2d.mv('A','vector',f=True)
 41      # gprint(r'\text{3d orthogonal ($A$ is vector function)}')
 42      gprint('A =', A_xyz)
 43      gprint('A^{2} =', A_xyz * A_xyz)
 44      gprint(r'\nabla \cdot A =', grad | A_xyz)
 45      gprint(r'\nabla A =', grad * A_xyz)
 46      gprint('v|(grad*A) =',v_xyz|(grad*A_xyz))
 47      gprint(r'\text{2d general ($A$ is vector function)}')
 48      gprint('A =', A_uv)
 49      gprint('A^{2} =', A_uv * A_uv)
 50      gprint(r'\nabla \cdot A =', grad_uv | A_uv)
 51      gprint(r'\nabla A =', grad_uv * A_uv)
 52      A = o3d.lt('A')
 53      gprint(r'\text{3d orthogonal ($A$, $B$ are linear transformations)}')
 54      gprint('A =', A)
 55      gprint(r'\f{mat}{A} =', A.matrix())
 56      gprint('\\f{\\det}{A} =', A.det())
 57      gprint('\\overline{A} =', A.adj())
 58      gprint('\\f{\\Tr}{A} =', A.tr())
 59      gprint('\\f{A}{e_x \\wedge e_y} =', A(ex^ey))
 60      gprint('\\f{A}{e_x} \\wedge \\f{A}{e_y} =', A(ex)^A(ey))
 61      B = o3d.lt('B')
 62      gprint('g =', o3d.g)
 63      gprint('g^{-1} =', o3d.g_inv)
 64  
 65      gprint('A + B =', A + B)
 66      gprint('AB =', A * B)
 67      gprint('A - B =', A - B)
 68      gprint('General Symmetric Linear Transformation')
 69      Asym = o3d.lt('A',mode='s')
 70      gprint('A =', Asym)
 71      gprint('General Antisymmetric Linear Transformation')
 72      Aasym = o3d.lt('A',mode='a')
 73      gprint('A =', Aasym)
 74      gprint(r'\text{2d general ($A,\\;B$ are linear transformations)}')
 75      A2d = g2d.lt('A')
 76      gprint('g =', g2d.g)
 77      gprint('g^{-1} =', g2d.g_inv)
 78      gprint('gg^{-1} =', simplify(g2d.g * g2d.g_inv))
 79      gprint('A =', A2d)
 80      gprint(r'\f{mat}{A} =', A2d.matrix())
 81      gprint('\\f{\\det}{A} =', A2d.det())
 82      A2d_adj = A2d.adj()
 83      gprint('\\overline{A} =', A2d_adj)
 84      gprint('\\f{mat}{\\overline{A}} =', simplify(A2d_adj.matrix()))
 85      gprint('\\f{\\Tr}{A} =', A2d.tr())
 86      gprint('\\f{A}{e_u \\wedge e_v} =', A2d(eu^ev))
 87      gprint('\\f{A}{e_u} \\wedge \\f{A}{e_v} =', A2d(eu)^A2d(ev))
 88      B2d = g2d.lt('B')
 89  
 90      gprint('B =', B2d)
 91      gprint('A + B =', A2d + B2d)
 92      gprint('A - B =', A2d - B2d)
 93      gprint('AB =', A2d * B2d)
 94      a = g2d.mv('a','vector')
 95      b = g2d.mv('b','vector')
 96      gprint(r'a|\f{\overline{A}}{b}-b|\f{\underline{A}}{a} =',((a|A2d.adj()(b))-(b|A2d(a))).simplify())
 97      m4d = Ga('e_t e_x e_y e_z', g=[1, -1, -1, -1],coords=symbols('t,x,y,z',real=True))
 98      T = m4d.lt('T')
 99      gprint('g =', m4d.g)
100      gprint(r'\underline{T} =',T)
101      gprint(r'\overline{T} =',T.adj())
102      gprint(r'\f{\det}{\underline{T}} =',T.det())
103      gprint(r'\f{\mbox{tr}}{\underline{T}} =',T.tr())
104      a = m4d.mv('a','vector')
105      b = m4d.mv('b','vector')
106      gprint(r'a|\f{\overline{T}}{b}-b|\f{\underline{T}}{a} =',((a|T.adj()(b))-(b|T(a))).simplify())
107      coords = (r, th, phi) = symbols('r,theta,phi', real=True)
108      (sp3d, er, eth, ephi) = Ga.build('e_r e_th e_ph', g=[1, r**2, r**2*sin(th)**2], coords=coords)
109      grad = sp3d.grad
110      sm_coords = (u, v) = symbols('u,v', real=True)
111      smap = [1, u, v]  # Coordinate map for sphere of r = 1
112      sph2d = sp3d.sm(smap,sm_coords,norm=True)
113      (eu, ev) = sph2d.mv()
114      grad_uv = sph2d.grad
115      F = sph2d.mv('F','vector',f=True)
116      f = sph2d.mv('f','scalar',f=True)
117      gprint('f =',f)
118      gprint(r'\nabla f =',grad_uv * f)
119      gprint('F =',F)
120      gprint(r'\nabla F =',grad_uv * F)
121      tp = (th,phi) = symbols('theta,phi',real=True)
122      smap = [sin(th)*cos(phi),sin(th)*sin(phi),cos(th)]
123      sph2dr = o3d.sm(smap,tp,norm=True)
124      (eth, ephi) = sph2dr.mv()
125      grad_tp = sph2dr.grad
126      F = sph2dr.mv('F','vector',f=True)
127      f = sph2dr.mv('f','scalar',f=True)
128      gprint('f =',f)
129      gprint(r'\nabla f =',grad_tp * f)
130      gprint('F =',F)
131      gprint(r'\nabla F =',grad_tp * F)
132      return
133  
134  
135  class TestGprinter(unittest.TestCase):
136      def setUp(self):
137          os.makedirs(DIR_GENERATED, exist_ok=True)
138          os.makedirs(DIR_DIFF, exist_ok=True)
139          os.chdir(DIR_GENERATED)
140  
141      def gen_pdf(self, name, documentclass):
142          gxpdf('%s.tex' % name, pdfprog='tectonic', rm=False, null=False, evince=False, documentclass=documentclass)
143  
144      def check_pdf(self, name, expected_retcode=0):
145          retcode = subprocess.call([
146              'diff-pdf',
147              '--output-diff=%s' % (DIR_DIFF / ('%s-diff.pdf' % name)),
148              DIR_FIXTURES / ('%s.pdf' % name),
149              DIR_GENERATED / ('%s.pdf' % name)
150          ])
151          assert retcode == expected_retcode
152  
153      @pytest.mark.skipif("TEST_GXPDF" not in os.environ, reason="Only run if TEST_GXPDF is set")
154      def test_gxpdf(self):
155          gFormat()
156          # Set up standard G^3 geometric algebra
157          g3coords = (x, y, z) = symbols('x y z', real=True)  # Without real=True, symbols are complex
158          g3 = Ga(r'\mathbf{e}', g=[1, 1, 1], coords=g3coords)
159          (ex, ey, ez) = g3.mv()      # Program names of basis vectors.
160          (exr, eyr, ezr) = g3.mvr()  # Program names of reciprocal basis vectors.
161  
162          B = g3.mv('B', 'bivector')
163          Fmt(1)  # Set Fmt globally
164          gprint(r'\mathbf{B} =', B)         # B will be bold.
165          gprint(r'\mathbf{B} =', B.Fmt(3))  # Fmt(3) here only.
166          gprint(r'\mathbf{B} =', B)         # Global Fmt remembered.
167  
168          gprint(r'\mathbf{B}^2 =', B*B)
169  
170          M = g3.mv('M', 'mv')
171          gprint(r'\langle \mathbf{M} \rangle_2 =', M.grade(2)) 
172          # grade(2) could be replaced by, e.g., odd(), or omitted altogether.
173  
174          gprint(r'\alpha_1\mathbf{X}/\gamma_r^3')
175  
176          grad = g3.grad
177  
178          gprint(r'{\nabla} = ', grad)
179  
180          self.gen_pdf('test_gprinter', documentclass='book')
181          self.check_pdf('test_gprinter')
182  
183      # This test is a POC, and should skip for now
184      @pytest.mark.skip
185      def test_lt_pdf(self):
186          lin_tran()
187          self.gen_pdf('test_lt_pdf', documentclass='report')
188          self.check_pdf('test_lt_pdf', expected_retcode=1)