module-components.rst
1 Module Components 2 ================= 3 4 .. math:: 5 \newcommand{\bm}[1]{\boldsymbol{#1}} 6 \newcommand{\ubh}{\bm{\hat{u}}} 7 \newcommand{\ebh}{\bm{\hat{e}}} 8 \newcommand{\ebf}{\bm{e}} 9 \newcommand{\mat}[1]{\left [ {#1} \right ]} 10 \newcommand{\bra}[1]{{#1}_{\mathcal{G}}} 11 \newcommand{\ket}[1]{{#1}_{\mathcal{D}}} 12 \newcommand{\ds}{\displaystyle} 13 \newcommand{\bfrac}[2]{\displaystyle\frac{#1}{#2}} 14 \newcommand{\lp}{\left (} 15 \newcommand{\rp}{\right )} 16 \newcommand{\half}{\frac{1}{2}} 17 \newcommand{\llt}{\left <} 18 \newcommand{\rgt}{\right >} 19 \newcommand{\abs}[1]{\left |{#1}\right |} 20 \newcommand{\pdiff}[2]{\bfrac{\partial {#1}}{\partial {#2}}} 21 \newcommand{\pdifftwo}[3]{\bfrac{\partial^{2} {#1}}{\partial {#2}\partial {#3}}} 22 \newcommand{\lbrc}{\left \{} 23 \newcommand{\rbrc}{\right \}} 24 \newcommand{\set}[1]{\lbrc {#1} \rbrc} 25 \newcommand{\W}{\wedge} 26 \newcommand{\R}{\dagger} 27 \newcommand{\lbrk}{\left [} 28 \newcommand{\rbrk}{\right ]} 29 \newcommand{\com}[1]{\lbrk {#1} \rbrk} 30 \newcommand{\proj}[2]{\llt {#1} \rgt_{#2}} 31 %\newcommand{\bm}{\boldsymbol} 32 \newcommand{\braces}[1]{\left \{ {#1} \right \}} 33 \newcommand{\grade}[1]{\left < {#1} \right >} 34 \newcommand{\f}[2]{{#1}\lp {#2} \rp } 35 \newcommand{\paren}[1]{\lp {#1} \rp } 36 \newcommand{\eval}[2]{\left . {#1} \right |_{#2}} 37 \newcommand{\prm}[1]{{#1}'} 38 \newcommand{\ddt}[1]{\bfrac{d{#1}}{dt}} 39 \newcommand{\deriv}[3]{\bfrac{d^{#3}#1}{d{#2}^{#3}}} 40 \newcommand{\be}{\begin{equation}} 41 \newcommand{\ee}{\end{equation}} 42 \newcommand{\eb}{\bm{e}} 43 \newcommand{\ehb}{\bm{\hat{e}}} 44 \newcommand{\Tn}[2]{\f{\mathcal{T}_{#2}}{#1}} 45 \newcommand{\tr}{\mbox{tr}} 46 \newcommand{\T}[1]{\texttt{#1}} 47 \newcommand{\grd}{\bm{\nabla}} 48 \newcommand{\indices}[1]{#1} 49 \newcommand{\xRightarrow}[1]{\overset{#1}{\Rightarrow}} 50 51 .. currentmodule:: galgebra 52 53 .. warning:: 54 55 This page is converted from the original :math:`\LaTeX` documentation, but 56 may no longer reflect the current state of the library. See the API docs at 57 :doc:`api` for more up-to-date but less structured and in-depth descriptions. 58 59 If you would like to help with merging the descriptions on the API with a 60 description on this page, please head over to :issue:`300` on GitHub, where 61 there's an explanation of how to do so. Even merging just one function 62 explanation helps! 63 64 Any function or class below with a ``[source]`` link to its right is 65 guaranteed to be up-to-date already, as its documentation is identical on 66 both pages. 67 68 The geometric algebra module consists of the following files and classes 69 70 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 71 | File | Classes | Usage | 72 +================+============================================+======================================================================================================================================================+ 73 | ``metric.py`` | :class:`~galgebra.metric.Metric` | Instantiates metric tensor and derivatives of basis vectors. Normalized basis if required. | 74 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 75 | ``ga.py`` | :class:`~galgebra.ga.Ga` | Instantiates geometric algebra (inherits :class:`~galgebra.metric.Metric`), generates bases, blades, multiplication tables, reciprocal basis, and | 76 | | | left and right geometric derivative operators. | 77 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 78 | | :class:`~galgebra.ga.Sm` | Instantiates geometric algebra for submainfold (inherits :class:`~galgebra.ga.Ga`). | 79 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 80 | ``mv.py`` | :class:`~galgebra.mv.Mv` | Instantiates multivector. | 81 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 82 | | :class:`~galgebra.mv.Dop` | Instantiates linear multivector differential operator. | 83 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 84 | ``lt.py`` | :class:`~galgebra.lt.Lt` | Instantiates multivector linear transformation. | 85 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 86 | ``printer.py`` | :class:`~galgebra.printer.Eprint` | Starts enhanced text printing on ANSI terminal (requires ``ConEmu`` on Windows). | 87 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 88 | | :class:`~galgebra.printer.GaPrinter` | Text printer for all geometric algebra classes (inherits from :class:`sympy.printing.str.StrPrinter`). | 89 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 90 | | :class:`~galgebra.printer.GaLatexPrinter` | :math:`\LaTeX`\ printer for all geometric algebra classes (inherits from :class:`sympy.printing.latex.LatexPrinter`). | 91 +----------------+--------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 92 93 Instantiating a Geometric Algebra 94 --------------------------------- 95 96 The geometric algebra class is instantiated with 97 98 .. class:: galgebra.ga.Ga(basis, g=None, coords=None, X=None, norm=False, sig='e', Isq='-', wedge=True, debug=False) 99 :noindex: 100 101 The ``basis`` and ``g`` parameters were described in section :ref:`BasisMetric`. If the metric is a function of position, if we have multivector fields, or we wish to calculate geometric derivatives a coordinate set, ``coords``, is required. ``coords`` is a list of *sympy* symbols. For the case of instantiating a 3-d geometric algebra in spherical coordinates we have 102 103 .. code:: python 104 105 r, th, phi = coords = symbols('r,theta,phi', real=True) 106 basis = 'e_r e_theta e_phi' 107 g = [1, r**2, r**2*sin(th)**2] 108 sp3d = Ga(basis, g=g, coords=coords, norm=True) 109 110 The input ``X`` allows the metric to be input as a vector manifold. ``X`` is a list of functions of ``coords`` of dimension, :math:`m`, equal to or greater than the number of coordinates. If ``g=None`` it is assumed that ``X`` is a vector in an :math:`m`-dimensional orthonormal Euclidean vector space. If it is wished the embedding vector space to be non-Euclidean that condition is specified with ``g``. For example if we wish the embedding space to be a 5-dimensional Minkowski space then 111 ``g=[-1, 1, 1, 1, 1]``. Then the Ga class uses ``X`` to calculate the manifold basis vectors as a function of the coordinates and from them the metric tensor\ [12]_. 112 113 If ``norm=True`` the basis vectors of the manifold are normalized so that the absolute values of the squares of the basis vectors are one. *Currently you should only use this option for diagonal metric tensors, and even there due so with caution, due to the possible problems with taking the square root of a general*\ sympy\* expression (one that has an unknown sign).\* 114 115 **When a geometric algebra is created the unnormalized metric tensor is always saved so that submanifolds created from the normalized manifold can be calculated correctly.** 116 117 ``sig`` indicates the signature of the vector space in the following ways\ [13]_. 118 119 1. If the metric tensor is purely numerical (the components are not symbolic or functions of the coordinates) and is diagonal (orthogonal basis vectors) the signature is computed from the metric tensor. 120 121 2. If the metric tensor is not purely numerical and orthogonal the following hints are used (dimension of vector space is :math:`n`) 122 123 1. ``sig='e'`` the default hint assumes the signature is for a Euclidean space with signature :math:`(n,0)`. 124 125 2. ``sig='m+'`` assumes the signature if for the Minkowski space :math:`(n-1,1)`. 126 127 3. ``sig='m-'`` assumes the signature if for the Minkowski space :math:`(1,n-1)`. 128 129 4. ``sig=p`` where ``p`` is an integer :math:`p\le n` and the signature it :math:`(p,n-p)`. 130 131 If the metric tensor contains no symbolic constants, but is a function of the coordinates, it is possible to determine the signature of the metric numerically by specifying a allowed numerical coordinate tuple due to the invariance of the signature. This will be implemented in the future. 132 133 Currently one need not be concerned about inputting ``sig`` unless one in using the *Ga* member function ``Ga.I()`` or the functions ``Mv.dual()`` or ``cross()`` which also use ``Ga.I()``. 134 135 If :math:`I^{2}` is numeric it is calculated if it is not numeric then ``Isq='-'`` is the sign of the square of the pseudo-scalar. This is needed for some operations. The default is chosen for the case of a general 3D Euclidean metric. 136 137 If ``wedge=True`` the basis blades of a multivector are printed using the ``^`` symbol between basis vectors. If ``wedge=False`` the subscripts of each individual basis vector (assuming that the basis vector symbols are of the form root symbol with a subscript\ [14]_). For example in three dimensions if the basis vectors are :math:`{{\eb}}_{x}`, :math:`{{\eb}}_{y}`, and :math:`{{\eb}}_{z}` the grade 3 basis blade would be printed as :math:`{{\eb}}_{xyz}`. 138 139 If ``debug=True`` the data structures required to initialize the Ga class are printed out. 140 141 To get the basis vectors for ``sp3d`` we would have to use the member function ``Ga.mv()`` in the form 142 143 .. code:: python 144 145 er, eth, ephi = sp3d.mv() 146 147 To access the reciprocal basis vectors of the geometric algebra use the member function ``mvr()`` 148 149 .. method:: galgebra.ga.Ga.mvr(norm='True') 150 :noindex: 151 152 ``Ga.mvr(norm)`` returns the reciprocal basis vectors as a tuple. This allows the programmer to attach any python variable names to the reciprocal basis vectors that is convenient. For example (demonstrating the use of both ``mv()`` and ``mvr()``) 153 154 .. code:: python 155 156 e_x, e_y, e_z = o3d.mv() 157 e__x, e__y, e__z = o3d.mvr() 158 159 If ``norm='True'`` or the basis vectors are orthogonal the dot product of the basis vector and the corresponding reciprocal basis vector is one :math:`{\lp {e_{i}\cdot e^{j}=\delta_{i}^{j}} \rp }`. If ``norm='False'`` and the basis is non-orthogonal The dot product of the basis vector and the corresponding reciprocal basis vector is the square of the pseudo scalar, :math:`I^{2}`, of the geometric algebra :math:`{\lp {e_{i}\cdot e^{j}=E^{2}\delta_{i}^{j}} \rp }`. 160 161 In addition to the basis vectors, if coordinates are defined for the geometric algebra, the left and right geometric derivative operators are calculated and accessed with the ``Ga`` member function ``grads()``. 162 163 .. method:: galgebra.ga.Ga.grads() 164 :noindex: 165 166 ``Ga.grads()`` returns a tuple with the left and right geometric derivative operators. A typical usage would be 167 168 .. code:: python 169 170 grad, rgrad = sp3d.grads() 171 172 for the spherical 3-d geometric algebra. The left derivative :math:`{\lp {{\texttt{grad}} ={\boldsymbol{\nabla}}} \rp }` and the right derivative :math:`{\lp {{\texttt{rgrad}} = {\boldsymbol{\bar{\nabla}}}} \rp }` have been explained in section :ref:`ldops`. Again the names ``grad`` and ``rgrad`` used in a program are whatever the user chooses them to be. In the previous example ``grad`` and ``rgrad`` are used. 173 174 an alternative instantiation method is 175 176 .. method:: galgebra.ga.Ga.build(basis, g=None, coords=None, X=None, norm=False, debug=False) 177 :noindex: 178 179 The input parameters for ``Ga.build()`` are the same as for ``Ga()``. The difference is that in addition to returning the geometric algebra ``Ga.build()`` returns the basis vectors at the same time. Using ``Ga.build()`` in the previous example gives 180 181 .. code:: python 182 183 r, th, phi = coords = symbols('r,theta,phi', real=True) 184 basis = 'e_r e_theta e_phi' 185 g = [1, r**2, r**2*sin(th)**2] 186 sp3d, er, eth, ephi = Ga.build(basis, g=g, coord=coords, norm=True) 187 188 To access the pseudo scalar of the geometric algebra use the member function ``I()``. 189 190 .. method:: galgebra.ga.Ga.I() 191 :noindex: 192 193 ``Ga.I()`` returns the normalized pseudo scalar :math:`{\lp {{\left |{I^{2}}\right |}=1} \rp }` for the geometric algebra. For example :math:`I = \mbox{{\texttt{o3d.I()}}}` for the ``o3d`` geometric algebra. This function requires the signature of the vector space (see instantiating a geometric algebra). 194 195 .. method:: galgebra.ga.Ga.E() 196 :noindex: 197 198 ``Ga.E()`` returns the unnormalized pseudo scalar :math:`E_{n} = {\eb}_{1}{\wedge}\dots{\wedge}{\eb}_{n}` for the geometric algebra. 199 200 In general we have defined member functions of the ``Ga`` class that will instantiate objects of other classes since the objects of the other classes are all associated with a particular geometric algebra object. Thus we have 201 202 ===================== ========================= =========================== 203 Object Class ``Ga`` method 204 ===================== ========================= =========================== 205 multivector :class:`~galgebra.mv.Mv` :meth:`~galgebra.ga.Ga.mv` 206 submanifold :class:`~galgebra.ga.Sm` :meth:`~galgebra.ga.Ga.sm` 207 linear transformation :class:`~galgebra.lt.Lt` :meth:`~galgebra.ga.Ga.lt` 208 differential operator :class:`~galgebra.mv.Dop` :meth:`~galgebra.ga.Ga.dop` 209 ===================== ========================= =========================== 210 211 for the instantiation of various objects from the ``Ga`` class. This means that in order to instantiate any of these objects we need only to import ``Ga`` into our program. 212 213 .. _makeMV: 214 215 Instantiating a Multivector 216 --------------------------- 217 218 Since we need to associate each multivector with the geometric algebra that contains it we use a member function of Ga to instantiate every multivector\ [15]_ The multivector is instantiated with: 219 220 .. method:: galgebra.ga.Ga.mv(name, mode, f=False) 221 :noindex: 222 223 As an example of both instantiating a geometric algebra and multivectors consider the following code fragment for a 3-d Euclidean geometric algebra. 224 225 .. code:: python 226 227 from sympy import symbols 228 from ga import Ga 229 x, y, z = coords = symbols('x,y,z',real=True) 230 o3d = Ga('e_x e_y e_z', g=[1, 1, 1], coords=coords) 231 ex, ey, ez = o3d.mv() 232 V = o3d.mv('V', 'vector', f=True) 233 f = o3d.mv(x*y*z) 234 B = o3d.mv('B', 2) 235 236 First consider the multivector instantiation in line 6, 237 238 ``V = o3d.mv('V','vector',f=True)`` 239 240 .Here a 3-dimensional multivector field that is a function of ``x``, ``y``, and ``z`` (``f=True``) is being instantiated. If latex output were used (to be discussed later) the multivector ``V`` would be displayed as 241 242 .. math:: \be V^{x}\eb_{x} + V^{y}\eb_{y} + V^{z}\eb_{z} \ee 243 244 Where the coefficients of the basis vectors are generalized *sympy* functions of the coordinates. If ``f=(x,y)`` then the coefficients would be functions of ``x`` and ``y``. In general is ``f`` is a tuple of symbols then the coefficients of the basis would be functions of those symbols. The superscripts\ [16]_ are formed from the coordinate symbols or if there are no coordinates from the subscripts of the basis vectors. The types of name and modes available for multivector instantiation are 245 246 ======== ========================== =============================================== 247 ``name`` ``mode`` result 248 ======== ========================== =============================================== 249 string s ``scalar`` symbolic scalar of value Symbol(s) 250 string s ``vector`` symbolic vector 251 string s ``grade2`` or ``bivector`` symbolic bivector 252 string s ``r`` (integer) symbolic r-grade multivector 253 string s ``pseudo`` symbolic pseudoscalar 254 string s ``spinor`` symbolic even multivector 255 string s ``mv`` symbolic general multivector 256 scalar c None zero grade multivector with coefficient value c 257 ======== ========================== =============================================== 258 259 Line 5 of the previous listing illustrates the case of using the ``mv`` member function with no arguments. The code does not return a multivector, but rather a tuple or the basis vectors of the geometric algebra ``o3d``. The elements of the tuple then can be used to construct multivectors, or multivector fields through the operations of addition, subtraction, multiplication (geometric, inner, and outer products and left and right contraction). As an example we could construct the vector 260 function 261 262 .. code:: python 263 264 F = x**2*ex + z*ey + x*y*ez 265 266 or the bivector function 267 268 .. code:: python 269 270 B = z*(ex^ey) + y*(ey^ez) + y*(ex^ez). 271 272 Line 7 is an example of instantiating a multivector scalar function (a multivector with only a scalar part). If we print ``f`` the result is ``x*y*z``. Line 8 is an example of instantiating a grade :math:`r` (in the example a grade 2) multivector where 273 274 .. math:: \be B = B^{xy}{\eb}_{x}{\wedge}{\eb}_{y}+B^{yz}{\eb}_{y}{\wedge}{\eb}_{z}+B^{xz}{\eb}_{x}{\wedge}{\eb}_{z}. \ee 275 276 If one wished to calculate the left and right geometric derivatives of ``F`` and ``B`` the required code would be 277 278 .. code:: python 279 280 grad, rgrad = o3d.grads() 281 dF = grad*F 282 dB = grad*B 283 dFr = F*rgrad 284 dBr = B*rgrad 285 286 ``dF``, ``dB``, ``dFr``, and ``dBr`` are all multivector functions. For the code where the order of the operations are reversed 287 288 .. code:: python 289 290 grad, rgrad = o3d.grads() 291 dFop = F*grad 292 dBop = B*grad 293 dFrop = rgrad*F 294 dBrop = rgrad*B 295 296 ``dFop``, ``dBop``, ``dFrop``, and ``dBrop`` are all multivector differential operators (again see section :ref:`ldops`). 297 298 Backward Compatibility Class MV 299 ------------------------------- 300 301 In order to be backward compatible with older versions of *galgebra* we introduce the class :class:`~galgebra.deprecated.MV` which is inherits it’s functions from then class Mv. To instantiate a geometric algebra using MV use the static function 302 303 .. automethod:: galgebra.deprecated.MV.setup 304 :noindex: 305 306 .. class:: galgebra.deprecated.MV(base, mvtype, fct=False, blade_rep=True) 307 :noindex: 308 309 For the instantiation of multivector using ``MV`` the ``base`` and ``mvtype`` arguments are the same as for new methods of multivector instantiation. The ``fct`` input is the same and the ``g`` input in the new methods. ``blade_rep`` is not used in the new methods so setting ``blade_rep=False`` will do nothing. Effectively ``blade_rep=False`` was not used in the old examples. 310 311 .. automethod:: galgebra.deprecated.MV.Fmt 312 :noindex: 313 314 Basic Multivector Class Functions 315 --------------------------------- 316 317 If we can instantiate multivectors we can use all the multivector class functions as described as follows. 318 319 .. method:: galgebra.mv.Mv.blade_coefs(basis_lst) 320 :noindex: 321 322 Find coefficients (sympy expressions) of multivector basis blade expansion corresponding to basis blades in ``basis_lst``. For example if :math:`V = V^{x}{{\eb}}_{x}+V^{y}{{\eb}}_{x}+V^{z}{{\eb}}_{x}` Then :math:`V\text{.blade_coefs}([{{\eb}}_{z},{{\eb}}_{x}]) = [V^{z},V^{x}]` or if :math:`B = B^{xy}{{\eb}}_{x}{\wedge}{{\eb}}_{y}+V^{yz}{{\eb}}_{y}{\wedge}{{\eb}}_{z}` then :math:`B\text{.blade_coefs}([{{\eb}}_{x}{\wedge}{{\eb}}_{y}]) = [B^{xy}]`. 323 324 .. method:: galgebra.mv.Mv.convert_to_blades() 325 :noindex: 326 327 Convert multivector from the base representation to the blade representation. If multivector is already in blade representation nothing is done. 328 329 .. method:: galgebra.mv.Mv.convert_from_blades() 330 :noindex: 331 332 Convert multivector from the blade representation to the base representation. If multivector is already in base representation nothing is done. 333 334 .. method:: galgebra.mv.Mv.diff(var) 335 :noindex: 336 337 Calculate derivative of each multivector coefficient with respect to variable ``var`` and form new multivector from coefficients. 338 339 .. method:: galgebra.mv.Mv.dual() 340 :noindex: 341 342 The mode of the ``dual()`` function is set by the ``Ga`` class static member function, ``GA.dual_mode(mode='I+')`` of the ``GA`` geometric galgebra which sets the following return values (:math:`I` is the pseudo-scalar for the geometric algebra ``GA``) 343 344 =========== ================ 345 ``mode`` Return Value 346 =========== ================ 347 ``'+I'`` :math:`IA` 348 ``'I+'`` :math:`AI` 349 ``'-I'`` :math:`-IA` 350 ``'I-'`` :math:`-AI` 351 ``'+Iinv'`` :math:`I^{-1}A` 352 ``'Iinv+'`` :math:`AI^{-1}` 353 ``'-Iinv'`` :math:`-I^{-1}A` 354 ``'Iinv-'`` :math:`-AI^{-1}` 355 =========== ================ 356 357 For example if the geometric algebra is ``o3d``, ``A`` is a multivector in ``o3d``, and we wish to use ``mode='I-'``. We set the mode with the function ``o3d.dual('I-')`` and get the dual of ``A`` with the function ``A.dual()`` which returns :math:`-AI`. 358 359 If ``o3d.dual(mode)`` is not called the default for the dual mode is ``mode='I+'`` and ``A*I`` is returned. 360 361 Note that ``Ga.dual(mode)`` used the function ``Ga.I()`` to calculate the normalized pseudoscalar. Thus if the metric tensor is not numerical and orthogonal the correct hint for then ``sig`` input of the *Ga* constructor is required. 362 363 .. method:: galgebra.mv.Mv.even() 364 :noindex: 365 366 Return the even grade components of the multivector. 367 368 .. method:: galgebra.mv.Mv.exp(hint='-') 369 :noindex: 370 371 If :math:`A` is a multivector then :math:`e^{A}` is defined for any :math:`A` via the series expansion for :math:`e`. However as a practical matter we only have a simple closed form formula for :math:`e^{A}` if :math:`A^{2}` is a scalar\ [18]_. If :math:`A^{2}` is a scalar and we know the sign of :math:`A^{2}` we have the following formulas for :math:`e^{A}`. 372 373 .. math:: 374 375 $\begin{aligned} 376 A^{2} > 0 : & & &\\ 377 A &= \sqrt{A^{2}} {\displaystyle\frac{A}{\sqrt{A^{2}}}} ,& e^{A} &= {{\cosh}\lp {\sqrt{A^{2}}} \rp }+{{\sinh}\lp {\sqrt{A^{2}}} \rp }{\displaystyle\frac{A}{\sqrt{A^{2}}}} \\ 378 A^{2} < 0 : & & &\\ 379 A &= \sqrt{-A^{2}} {\displaystyle\frac{A}{\sqrt{-A^{2}}}} ,& e^{A} &= {{\cos}\lp {\sqrt{-A^{2}}} \rp }+{{\sin}\lp {\sqrt{-A^{2}}} \rp }{\displaystyle\frac{A}{\sqrt{-A^{2}}}} \\ 380 A^{2} = 0 : & & &\\ 381 A &=0 ,& e^{A} &= 1 + A 382 \end{aligned} 383 384 The hint is required for symbolic multivectors :math:`A` since in general *sympy* cannot determine if :math:`A^{2}` is positive or negative. If :math:`A` is purely numeric the hint is ignored since the sign can be calculated. 385 386 .. method:: galgebra.mv.Mv.expand() 387 :noindex: 388 389 Return multivector in which each coefficient has been expanded using *sympy* ``expand()`` function. 390 391 .. method:: galgebra.mv.Mv.factor() 392 :noindex: 393 394 Apply the ``sympy`` ``factor`` function to each coefficient of the multivector. 395 396 .. method:: galgebra.mv.Mv.Fmt(fmt=1, title=None) 397 :noindex: 398 399 Fuction to print multivectors in different formats where 400 401 ======= ============================================ 402 ``fmt`` 403 ======= ============================================ 404 1 Print entire multivector on one line. 405 2 Print each grade of multivector on one line. 406 3 Print each base of multivector on one line. 407 ======= ============================================ 408 409 ``title`` appends a title string to the beginning of the output. An equal sign in the title string is not required, but is added as a default. Note that ``Fmt`` only overrides the the global multivector printing format for the particular instance being printed. To reset the global multivector printing format use the function :func:`~galgebra.printer.Fmt` in the :mod:`galgebra.printer` module. 410 411 .. method:: galgebra.mv.Mv.func(fct) 412 :noindex: 413 414 Apply the ``sympy`` scalar function ``fct`` to each coefficient of the multivector. 415 416 .. method:: galgebra.mv.Mv.grade(igrade=0) 417 :noindex: 418 419 Return a multivector that consists of the part of the multivector of grade equal to ``igrade``. If the multivector has no ``igrade`` part return a zero multivector. 420 421 .. method:: galgebra.mv.Mv.inv() 422 :noindex: 423 424 Return the inverse of the multivector :math:`M` (``M.inv()``). If :math:`M` is a non-zero scalar return :math:`1/M`. If :math:`M^{2}` is a non-zero scalar return :math:`M/{\lp {M^{2}} \rp }`, If :math:`MM^{{\dagger}}` is a non-zero scalar return :math:`M^{{\dagger}}/{\lp {MM^{{\dagger}}} \rp }`. Otherwise exit the program with an error message. 425 426 All division operators (``/``, ``/=``) use right multiplication by the inverse. 427 428 .. method:: galgebra.mv.Mv.norm(hint='+') 429 :noindex: 430 431 Return the norm of the multivector :math:`M` (``M.norm()``) defined by :math:`\sqrt{{\left |{MM^{{\dagger}}}\right |}}`. If :math:`MM^{{\dagger}}` is a scalar (a *sympy* scalar is returned). If :math:`MM^{{\dagger}}` is not a scalar the program exits with an error message. If :math:`MM^{{\dagger}}` is a number *sympy* can determine if it is positive or negative and calculate the absolute value. If :math:`MM^{{\dagger}}` is a *sympy* expression (function) *sympy* cannot determine the sign of 432 the expression so that ``hint='+'`` or ``hint='-'`` is needed to determine if the program should calculate :math:`\sqrt{MM^{{\dagger}}}` or :math:`\sqrt{-MM^{{\dagger}}}`. For example if we are in a Euclidean space and ``M`` is a vector then ``hint='+'``, if ``M`` is a bivector then let ``hint='-'``. If ``hint='0'`` and :math:`MM^{{\dagger}}` is a symbolic scalar ``sqrt(Abs(M*M.rev()))`` is returned where ``Abs()`` is the *sympy* symbolic absolute value function. 433 434 .. method:: galgebra.mv.Mv.norm2() 435 :noindex: 436 437 Return the the scalar defined by :math:`MM^{{\dagger}}` if :math:`MM^{{\dagger}}` is a scalar. If :math:`MM^{{\dagger}}` is not a scalar the program exits with an error message. 438 439 .. method:: galgebra.mv.Mv.proj(bases_lst) 440 :noindex: 441 442 Return the projection of the multivector :math:`M` (``M.proj(bases_lst)``) onto the subspace defined by the list of bases (``bases_lst``). 443 444 .. method:: galgebra.mv.Mv.proj(lst) 445 :noindex: 446 447 Return the projection of the mutivector :math:`A` onto the list, :math:`lst`, of basis blades. For example if :math:`A = A^{x}{{\eb}}_{x}+A^{y}{{\eb}}_{y}+A^{z}{{\eb}}_{z}` then :math:`A.proj{\lp {[{{\eb}}_{x},{{\eb}}_{y}]} \rp } = A^{x}{{\eb}}_{x}+A^{y}{{\eb}}_{y}`. Similarly if :math:`A = A^{xy}{{\eb}}_{x}{\wedge}{{\eb}}_{y}+A^{yz}{{\eb}}_{y}{\wedge}{{\eb}}_{z}` then :math:`A.proj{\lp {[{{\eb}}_{x}{\wedge}{{\eb}}_{y}]} \rp } = A^{xy}{{\eb}}_{x}{\wedge}{{\eb}}_{y}`. 448 449 .. method:: galgebra.mv.Mv.project_in_blade(blade) 450 :noindex: 451 452 Return the projection of the mutivector :math:`A` in subspace defined by the blade, :math:`B`, using the formula :math:`{\lp {A\rfloor B} \rp }B^{-1}` in :cite:`Macdonald1`, page 121. 453 454 .. method:: galgebra.mv.Mv.pure_grade() 455 :noindex: 456 457 If the multivector :math:`A` is pure (only contains one grade) return, :math:`A.pure\_grade()`, the index ('0' for a scalar, '1' for vector, '2' for a bi-vector, etc.) of the non-zero grade. If :math:`A` is not pure return the negative of the highest non-zero grade index. 458 459 .. method:: galgebra.mv.Mv.odd() 460 :noindex: 461 462 Return odd part of multivector. 463 464 .. method:: galgebra.mv.Mv.reflect_in_blade(blade) 465 :noindex: 466 467 Return the reflection of the mutivector :math:`A` in the subspace defined by the :math:`r`-grade blade, :math:`B_{r}`, using the formula (extended to multivectors) :math:`\sum_{i} {\lp {-1} \rp }^{r{\lp {i+1} \rp }}{B}_{r}{\left < {A} \right >}_{i}B_{r}^{-1}` in :cite:`Macdonald1`, page 129. 468 469 .. method:: galgebra.mv.Mv.rev() 470 :noindex: 471 472 Return the reverse of the multivector. 473 474 .. method:: galgebra.mv.Mv.rotate_multivector(itheta, hint='-') 475 :noindex: 476 477 Rotate the multivector :math:`A` via the operation :math:`e^{-\theta i/2}Ae^{\theta i/2}` where itheta = :math:`\theta i`, :math:`\theta` is a scalar, and :math:`i` is a unit, :math:`i^{2} = \pm 1`, 2-blade. If :math:`{\lp {\theta i} \rp }^{2}` is not a number ``hint`` is required to determine the sign of the square of ``itheta``. The default chosen, ``hint='-'``, is correct for any Euclidean space. 478 479 .. method:: galgebra.mv.Mv.scalar() 480 :noindex: 481 482 Return the coefficient (*sympy* scalar) of the scalar part of a multivector. 483 484 .. method:: galgebra.mv.Mv.simplify(mode=simplify) 485 :noindex: 486 487 ``mode`` is a *sympy* simplification function of a list/tuple of *sympy* simplification functions that are applied in sequence (if more than one function) each coefficient of the multivector. For example if we wished to applied ``trigsimp`` and ``ratsimp`` *sympy* functions to the multivector ``F`` the code would be 488 489 .. code:: python 490 491 Fsimp = F.simplify(mode=[trigsimp, ratsimp]). 492 493 Actually ``simplify`` could be used to apply any scalar *sympy* function to the coefficients of the multivector. 494 495 .. method:: galgebra.mv.Mv.set_coef(grade, base, value) 496 :noindex: 497 498 Set the multivector coefficient of index ``(grade, base)`` to ``value``. 499 500 .. method:: galgebra.mv.Mv.subs(x) 501 :noindex: 502 503 Return multivector where *sympy* subs function has been applied to each coefficient of multivector for argument dictionary/list ``x``. 504 505 .. method:: galgebra.mv.Mv.trigsimp(**kwargs) 506 :noindex: 507 508 Apply the ``sympy`` trigonometric simplification function ``trigsimp`` to each coefficient of the multivector. ``**kwargs`` are the arguments of trigsimp. See ``sympy`` documentation on ``trigsimp`` for more information. 509 510 Basic Multivector Functions 511 --------------------------- 512 513 .. automethod:: galgebra.ga.Ga.com 514 :noindex: 515 516 .. autofunction:: galgebra.mv.cross 517 :noindex: 518 519 .. autofunction:: galgebra.printer.def_prec 520 :noindex: 521 522 .. autofunction:: galgebra.mv.dual 523 :noindex: 524 525 .. autofunction:: galgebra.mv.even 526 :noindex: 527 528 .. autofunction:: galgebra.mv.exp 529 :noindex: 530 531 .. autofunction:: galgebra.printer.GAeval 532 :noindex: 533 534 .. autofunction:: galgebra.mv.grade 535 :noindex: 536 537 .. autofunction:: galgebra.mv.inv 538 :noindex: 539 540 .. autofunction:: galgebra.mv.Nga 541 :noindex: 542 543 .. autofunction:: galgebra.mv.norm 544 :noindex: 545 546 .. autofunction:: galgebra.mv.norm2 547 :noindex: 548 549 .. autofunction:: galgebra.mv.odd 550 :noindex: 551 552 .. autofunction:: galgebra.mv.proj 553 :noindex: 554 555 .. automethod:: galgebra.ga.Ga.ReciprocalFrame 556 :noindex: 557 558 .. autofunction:: galgebra.mv.refl 559 :noindex: 560 561 .. autofunction:: galgebra.mv.rev 562 :noindex: 563 564 .. autofunction:: galgebra.mv.rot 565 :noindex: 566 567 .. _makeMVD: 568 569 Multivector Derivatives 570 ----------------------- 571 572 The various derivatives of a multivector function is accomplished by multiplying the gradient operator vector with the function. The gradient operation vector is returned by the ``Ga.grads()`` function if coordinates are defined. For example if we have for a 3-D vector space 573 574 .. code:: python 575 576 X = x, y, z = symbols('x y z') 577 o3d = Ga('e*x|y|z', metric=[1, 1, 1], coords=X) 578 ex, ey, ez = o3d.mv() 579 grad, rgrad = o3d.grads() 580 581 Then the gradient operator vector is ``grad`` (actually the user can give it any name he wants to). The derivatives of the multivector function ``F = o3d.mv('F', 'mv', f=True)`` are given by multiplying by the left geometric derivative operator and the right geometric derivative operator (:math:`\T{grad} = \nabla` and :math:`\T{rgrad} = \bar{\nabla}`). Another option is to use the radiant operator members of the geometric algebra directly where we have :math:`\nabla = {\texttt{o3d.grad}}` and 582 :math:`\bar{\nabla} = {\texttt{o3d.rgrad}}`. 583 584 .. math:: 585 586 \begin{aligned} 587 \nabla F &= \texttt{grad*F} \\ 588 F \bar{\nabla} &= \texttt{F*rgrad} \\ 589 \nabla {\wedge}F &= \texttt{grad^F} \\ 590 F {\wedge}\bar{\nabla} &= \texttt{F^rgrad} \\ 591 \nabla \cdot F &= \texttt{grad|F} \\ 592 F \cdot \bar{\nabla} &= \texttt{F|rgrad} \\ 593 \nabla \rfloor F &= \texttt{grad<F} \\ 594 F \rfloor \bar{\nabla} &= \texttt{F<rgrad} \\ 595 \nabla \lfloor F &= \texttt{grad>F} \\ 596 F \lfloor \bar{\nabla} &= \texttt{F>rgrad} 597 \end{aligned} 598 599 The preceding list gives examples of all possible multivector derivatives of the multivector function ``F`` where the operation returns a multivector function. The complementary operations 600 601 .. math:: 602 603 \begin{aligned} 604 F \nabla &= \texttt{F*grad} \\ 605 \bar{\nabla} F &= \texttt{rgrad*F} \\ 606 F {\wedge}\nabla &= \texttt{F^grad} \\ 607 \bar{\nabla} {\wedge}F &= \texttt{rgrad^F} \\ 608 F \cdot \nabla &= \texttt{F|grad} \\ 609 \bar{\nabla}\cdot F &= \texttt{rgrad|F} \\ 610 F \rfloor \nabla &= \texttt{F<grad} \\ 611 \bar{\nabla} \rfloor F &= \texttt{rgrad<F} \\ 612 F \lfloor \nabla &= \texttt{F>grad} \\ 613 \bar{\nabla} \lfloor F &= \texttt{rgrad>F} 614 \end{aligned} 615 616 all return multivector linear differential operators. 617 618 Submanifolds 619 ------------ 620 621 In general the geometric algebra that the user defines exists on the tangent space of a manifold (see section :ref:`sect_manifold`). The submanifold class, ``Sm``, is derived from the ``Ga`` class and allows one to define a submanifold of a manifold by defining a coordinate mapping between the submanifold coordinates and the manifold coordinates. What is returned as the submanifold is the geometric algebra of the tangent space of the submanifold. The submanifold for a geometric algebra is 622 instantiated with 623 624 .. method:: galgebra.ga.Ga.sm(map, coords, root='e', norm=False) 625 :noindex: 626 627 To define the submanifold we must def a coordinate map from the coordinates of the submanifold to each of the coordinates of the base manifold. Thus the arguments ``map`` and ``coords`` are respectively lists of functions and symbols. The list of symbols, ``coords``, are the coordinates of the submanifold and are of length equal to the dimension of the submanifold. The list of functions, ``map``, define the mapping from the coordinate space of the submanifold to the coordinate space of the 628 base manifold. The length of ``map`` is equal to the dimension of the base manifold and each function in ``map`` is a function of the coordinates of the submanifold. ``root`` is the root of the string that is used to name the basis vectors of the submanifold. The default value of ``root`` is ``e``. The result of this is that if the *sympy* symbols for the coordinates are ``u`` and ``v`` (two dimensional manifold) the text symbols for the basis vectors are ``e_u`` and ``e_v`` or in LaTeX 629 :math:`e_{u}` and :math:`e_{v}`. As a concrete example consider the following code. 630 631 .. literalinclude:: python/submanifold.py 632 633 The output of this program (using LaTeX) is 634 635 |image0| 636 637 The base manifold, ``sp3d``, is a 3-d Euclidean space using standard spherical coordinates. The submanifold ``sph2d`` of ``sp3d`` is a spherical surface of radius :math:`1`. To take the sumanifold operation one step further the submanifold ``cir1d`` of ``sph2d`` is a circle in ``sph2d`` where the latitude of the circle is :math:`\pi/8`. 638 639 In each case, for demonstration purposes, a scalar and vector function on each manifold is defined (``f`` and ``F`` for the 2-d manifold and ``h`` and ``H`` for the 1-d manifold) and the geometric derivative of each function is taken. The manifold mapping and the metric tensor for ``cir1d`` of ``sph2d`` are also shown. Note that if the submanifold basis vectors are not normalized\ [21]_ the program output is 640 641 |image1| 642 643 Linear Transformations 644 ---------------------- 645 646 The mathematical background for linear transformations is in section :ref:`Ltrans`. Linear transformations on the tangent space of the manifold are instantiated with the ``Ga`` member function ``lt`` (the actual class being instantiated is ``Lt``) as shown in lines 12, 20, 26, and 44 of the code listing ``Ltrans.py``. In all of the examples in ``Ltrans.py`` the default instantiation is used which produces a general (all the coefficients of the linear transformation are symbolic constants) linear 647 transformation. *Note that to instantiate linear transformations coordinates, :math:`{\left \{ {{\eb}_{i}} \rbrc}`, must be defined when the geometric algebra associated with the linear transformation is instantiated. This is due to the naming conventions of the general linear transformation (coordinate names are used) and for the calculation of the trace of the linear transformation which requires taking a divergence.* To instantiate a specific linear transformation the usage of ``lt()`` is 648 649 .. method:: galgebra.ga.Ga.lt(M, f=False, mode='g') 650 :noindex: 651 652 ``M`` is an expression that can define the coefficients of the linear transformation in various ways defined as follows. 653 654 +----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 655 | ``M`` | Result | 656 +============================+===============================================================================================================================================================================================================================================================================================+ 657 | string ``M`` | Coefficients are symbolic constants with names :math:`\T{M}^{x_{i}x_{j}}` where :math:`x_{i}` and :math:`x_{j}` are the names of the :math:`i^{th}` and :math:`j^{th}` coordinates (see output of ``Ltrans.py``). | 658 +----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 659 | char ``mode`` | If ``M`` is a string then ``mode`` determines whether the linear transformation is general, ``mode='g'``, symmetric, ``mode='s'``, or antisymmetric, ``mode='a'``. The default is ``mode='g'``. | 660 +----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 661 | list ``M`` | If ``M`` is a list of vectors equal in length to the dimension of the vector space then the linear transformation is :math:`\f{L}{\ebf_{i}} = \T{M}\mat{i}`. If ``M``\ is a list of lists of scalars where all lists are equal in length to the dimension of the vector space then the linear | 662 | | transformation is\ :math:`\f{L}{\ebf_{i}} = \T{M}\mat{i}\mat{j}\ebf_{j}`. | 663 +----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 664 | dict ``M`` | If ``M`` is a dictionary the linear transformation is defined by :math:`\f{L}{\ebf_{i}} = \T{M}\mat{\ebf_{i}}`. If :math:`\ebf_{i}` is not in the dictionary then :math:`\f{L}{\ebf_{i}} =0`. | 665 +----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 666 | rotor ``M`` | If ``M`` is a rotor, :math:`\T{M}\T{M}^{\R}=1`, the linear transformation is defined by :math:`\f{L}{{\ebf}_{i}} = \T{M}{\ebf}_{i}\T{M}^{\R}` . | 667 +----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 668 | multivector function ``M`` | If ``M`` is a general multivector function, the function is tested for linearity, and if linear the coefficients of the linear transformation are calculated from :math:`\f{L}{\ebf_{i}} = \f{\T{M}}{\ebf_{i}}`. | 669 +----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 670 671 ``f`` is ``True`` or ``False``. If ``True`` the symbolic coefficients of the general linear transformation are instantiated as functions of the coordinates. 672 673 The different methods of instantiation are demonstrated in the code ``LtransInst.py`` 674 675 .. literalinclude:: python/LtransInst.py 676 677 with output 678 679 |image2| 680 681 The member function of the ``Lt`` class are 682 683 .. automethod:: galgebra.lt.Lt.__call__(A) 684 :noindex: 685 686 .. automethod:: galgebra.lt.Lt.det 687 :noindex: 688 689 .. automethod:: galgebra.lt.Lt.adj 690 :noindex: 691 692 .. automethod:: galgebra.lt.Lt.tr 693 :noindex: 694 695 .. automethod:: galgebra.lt.Lt.matrix 696 :noindex: 697 698 The ``Ltrans.py`` demonstrate the use of the various ``Lt`` member functions and operators. The operators that can be used with linear transformations are ``+``, ``-``, and ``*``. If :math:`A` and :math:`B` are linear transformations, :math:`V` a multivector, and :math:`\alpha` a scalar then :math:`{{{\lp {A\pm B} \rp }}\lp {V} \rp } = {{A}\lp {V} \rp }\pm{{B}\lp {V} \rp }`, :math:`{{{\lp {AB} \rp }}\lp {V} \rp } = {{A}\lp {{{B}\lp {V} \rp }} \rp }`, and 699 :math:`{{{\lp {\alpha A} \rp }}\lp {V} \rp } = \alpha{{A}\lp {V} \rp }`. 700 701 The ``matrix()`` member function returns a *sympy* ``Matrix`` object which can be printed in IPython notebook. To directly print an linear transformation in *ipython notebook* one must implement (yet to be done) a printing method similar to ``mv.Fmt()``. 702 703 Note that in ``Ltrans.py`` lines 30 and 49 are commented out since the latex output of those statements would run off the page. The use can uncomment those statements and run the code in the “LaTeX docs” directory to see the output. 704 705 .. literalinclude:: python/Ltrans.py 706 707 The output of this code is. 708 709 |image3| 710 711 Differential Operators 712 ---------------------- 713 714 For the mathematical treatment of linear multivector differential operators see section :ref:`ldops`. The is a differential operator class ``Dop``. However, one never needs to use it directly. The operators are constructed from linear combinations of multivector products of the operators ``Ga.grad`` and ``Ga.rgrad`` as shown in the following code for both orthogonal rectangular and spherical 3-d coordinate systems. 715 716 .. literalinclude:: python/Dop.py 717 718 The output of this code is. 719 720 |image4| 721 722 Note that for print an operator in the IPython notebook one must implement (yet to be done) a printing method similar to ``mv.Fmt()``. 723 724 Instantiating a Multi-linear Functions (Tensors) 725 ------------------------------------------------ 726 727 The mathematical background for multi-linear functions is in section :ref:`MLtrans`. To instantiate a multi-linear function use 728 729 .. class:: galgebra.lt.Mlt(f, Ga, nargs=None, fct=False) 730 :noindex: 731 732 Where the arguments are 733 734 +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 735 | ``f`` | Either a string for a general tensor (this option is included mainly for debugging of the ``Mlt`` class) or a multi-linear function of manifold tangent vectors (multi-vectors of grade one) to scalar. For example one could generate a custom | 736 | | python function such as shown in ``TensorDef.py`` . | 737 +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 738 | ``Ga`` | Geometric algebra that tensor is associated with. | 739 +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 740 | ``nargs`` | If ``f`` is a string then ``nargs`` is the number of vector arguments of the tensor. If ``f`` is anything other than a string ``nargs`` is not required since ``Mlt`` determines the number of vector arguments | 741 | | from ``f``. | 742 +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 743 | ``fct`` | If ``f`` is a string then ``fct=True`` forces the tensor to be a tensor field (function of the coordinates. If ``f`` anything other than a string ``fct`` is not required since ``Mlt`` determines whether the | 744 | | tensor is a tensor field from ``f`` . | 745 +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 746 747 .. literalinclude:: python/TensorDef.py 748 749 Basic Multilinear Function Class Functions 750 ------------------------------------------ 751 752 If we can instantiate multilinear functions we can use all the multilinear function class functions as described as follows. See section :ref:`MLtrans` for the mathematical description of each operation. 753 754 .. automethod:: galgebra.lt.Mlt.__call__ 755 :noindex: 756 757 .. automethod:: galgebra.lt.Mlt.contract 758 :noindex: 759 760 .. automethod:: galgebra.lt.Mlt.pdiff 761 :noindex: 762 763 .. automethod:: galgebra.lt.Mlt.cderiv 764 :noindex: 765 766 Standard Printing 767 ----------------- 768 769 Printing of multivectors is handled by the module :mod:`printer` which contains a string printer class derived from the *sympy* string printer class and a latex printer class derived from the *sympy* latex printer class. Additionally, there is an :class:`printer.Eprint` class that enhances the console output of *sympy* to make the printed output multivectors, functions, and derivatives more readable. :class:`printer.Eprint` requires an ansi console such as is supplied in linux or the program *ConEmu* replaces ``cmd.exe``. 770 771 For a windows user the simplest way to implement *ConEmu* is to use the *geany* editor and in the Edit\ :math:`\rightarrow`\ Preferences\ :math:`\rightarrow`\ Tools menu replace ``cmd.exe`` with\ [22]_ 772 773 ``"C:\Program Files\ConEmu\ConEmu64.exe" /WndW 180 /cmd %c`` 774 775 and then run an example *galgebra* program that used ``Eprint``. The default background and foreground colors make the output unreadable. To change these parameters to reasonable values:\ [23]_ 776 777 1. Right click on title bar of console. 778 779 2. Open *setting* window. 780 781 3. Open *colors* window. 782 783 4. Set the following parameters to the indicated values: 784 785 - Text: #0 786 - Back: #7 787 - Popup: #0 788 - Back: #7 789 - :math:`\rlap{ \checkmark }\square` Extend foreground colors with background #13 790 791 If ``Eprint`` is called in a program (linux) when multivectors are printed the basis blades or bases are printed in bold text, functions are printed in red, and derivative operators in green. 792 793 For formatting the multivector output there is the member function ``self.Fmt(fmt=1, title=None)`` which is documented in the multivector member functions. This member function works in the same way for LaTeX printing. 794 795 If ``A`` is a multivector then ``str(A)`` returns a string in which the scalar coefficients of the multivector bases have been simplified (grouped, factored, etc.). 796 797 Latex Printing 798 -------------- 799 800 For latex printing one uses one functions from the ``ga`` module and one function from the ``printer`` module. The functions are 801 802 .. autofunction:: galgebra.printer.Format 803 :noindex: 804 805 .. function:: galgebra.printer.Fmt(obj, fmt=1) 806 :noindex: 807 808 ``Fmt()`` can be used to set the global multivector printing format or to print a tuple, list, of dictionary\ [24]_. The modes and operation of ``Fmt()`` are as follows: 809 810 +---------------------+---------------------------------------------------------------------------------------------------------------------------------------------+ 811 | ``obj`` | Effect | 812 +=====================+=============================================================================================================================================+ 813 | ``obj=1,2,3`` | Global multivector format is set to 1, 2, or 3 depending on ``obj``. See multivector member function ``Fmt()`` for effect of ``obj`` value. | 814 +---------------------+---------------------------------------------------------------------------------------------------------------------------------------------+ 815 | obj=tuple/list/dict | The printing format of an object that is a tuple, list, or dict is controlled by the ``fmt`` argument in ``Fmt`` : | 816 +---------------------+---------------------------------------------------------------------------------------------------------------------------------------------+ 817 | | ``fmt=1``: Print complete ``obj`` on one line. | 818 +---------------------+---------------------------------------------------------------------------------------------------------------------------------------------+ 819 | | ``fmt=2``: Print one element of ``obj`` on each line. | 820 +---------------------+---------------------------------------------------------------------------------------------------------------------------------------------+ 821 822 .. function:: galgebra.printer.xpdf(filename=None, debug=False, paper=(14, 11), crop=False) 823 :noindex: 824 825 This function from the ``printer`` module post-processes the output captured from print statements, writes the resulting latex strings to the file ``filename``, processes the file with pdflatex, and displays the resulting pdf file. All latex files except the pdf file are deleted. If ``debug = True`` the file ``filename`` is printed to standard output for debugging purposes and ``filename`` (the tex file) is saved. If ``filename`` is not entered the default filename is the root name of the 826 python program being executed with ``.tex`` appended. The ``paper`` option defines the size of the paper sheet for latex. The format for the ``paper`` is 827 828 ===================== ============================================================= 829 ``paper=(w,h)`` ``w`` is paper width in inches and 830 \ ``h`` is paper height in inches 831 ``paper='letter'`` paper is standard letter size 8.5 in :math:`\times` 11 in 832 ``paper='landscape'`` paper is standard letter size but 11 in :math:`\times` 8.5 in 833 ===================== ============================================================= 834 835 The default of ``paper=(14,11)`` was chosen so that long multivector expressions would not be truncated on the display. 836 837 If the ``crop`` input is ``True`` the linux ``pdfcrop`` program is used to crop the pdf output (if output is one page). This only works for linux installations (where ``pdfcrop`` is installed). 838 839 The ``xpdf`` function requires that latex and a pdf viewer be installed on the computer. 840 841 ``xpdf`` *is not required when printing latex in IPython notebook.* 842 843 As an example of using the latex printing options when the following code is executed 844 845 .. code:: python 846 847 from printer import Format, xpdf 848 from ga import Ga 849 Format() 850 g3d = Ga('e*x|y|z') 851 A = g3d.mv('A', 'mv') 852 print(r'\bm{A} =',A) 853 print(A.Fmt(2,r'\bm{A}')) 854 print(A.Fmt(3,r'\bm{A}')) 855 xpdf() 856 857 The following is displayed 858 859 .. math:: 860 861 \begin{aligned} 862 {\boldsymbol{A}} = & A+A^{x}{\boldsymbol{e_{x}}}+A^{y}{\boldsymbol{e_{y}}}+A^{z}{\boldsymbol{e_{z}}}+A^{xy}{\boldsymbol{e_{x}{\wedge}e_{y}}}+A^{xz}{\boldsymbol{e_{x}{\wedge}e_{z}}}+A^{yz}{\boldsymbol{e_{y}{\wedge}e_{z}}}+A^{xyz}{\boldsymbol{e_{x}{\wedge}e_{y}{\wedge}e_{z}}} \\ 863 {\boldsymbol{A}} = & A \\ & +A^{x}{\boldsymbol{e_{x}}}+A^{y}{\boldsymbol{e_{y}}}+A^{z}{\boldsymbol{e_{z}}} \\ & +A^{xy}{\boldsymbol{e_{x}{\wedge}e_{y}}}+A^{xz}{\boldsymbol{e_{x}{\wedge}e_{z}}}+A^{yz}{\boldsymbol{e_{y}{\wedge}e_{z}}} \\ & +A^{xyz}{\boldsymbol{e_{x}{\wedge}e_{y}{\wedge}e_{z}}} \\ 864 {\boldsymbol{A}} = & A \\ & +A^{x}{\boldsymbol{e_{x}}} \\ & +A^{y}{\boldsymbol{e_{y}}} \\ & +A^{z}{\boldsymbol{e_{z}}} \\ & +A^{xy}{\boldsymbol{e_{x}{\wedge}e_{y}}} \\ & +A^{xz}{\boldsymbol{e_{x}{\wedge}e_{z}}} \\ & +A^{yz}{\boldsymbol{e_{y}{\wedge}e_{z}}} \\ & +A^{xyz}{\boldsymbol{e_{x}{\wedge}e_{y}{\wedge}e_{z}}}\end{aligned} 865 866 For the cases of derivatives the code is 867 868 .. code:: python 869 870 from printer import Format, xpdf 871 from ga import Ga 872 873 Format() 874 X = x, y, z = symbols('x y z') 875 o3d = Ga('e_x e_y e_z',g=[1,1,1],coords=X) 876 877 f = o3d.mv('f', 'scalar', f=True) 878 A = o3d.mv('A', 'vector', f=True) 879 B = o3d.mv('B', 'grade2', f=True) 880 881 print(r'\bm{A} =', A) 882 print(r'\bm{B} =', B) 883 884 print('grad*f =', o3d.grad*f) 885 print(r'grad|\bm{A} =', o3d.grad|A) 886 (o3d.grad*A).Fmt(2, r'grad*\bm{A}') 887 888 print(r'-I*(grad^\bm{A}) =', -o3g.mv_I*(o3d.grad^A)) 889 print((o3d.grad*B).Fmt(2, r'grad*\bm{B}')) 890 print(r'grad^\bm{B} =', o3d.grad^B) 891 print(r'grad|\bm{B} =', o3d.grad|B) 892 893 xpdf() 894 895 and the latex displayed output is (:math:`f` is a scalar function) 896 897 .. math:: \be {\boldsymbol{A}} = A^{x}{\boldsymbol{e_{x}}}+A^{y}{\boldsymbol{e_{y}}}+A^{z}{\boldsymbol{e_{z}}} \ee 898 899 .. math:: \be {\boldsymbol{B}} = B^{xy}{\boldsymbol{e_{x}{\wedge}e_{y}}}+B^{xz}{\boldsymbol{e_{x}{\wedge}e_{z}}}+B^{yz}{\boldsymbol{e_{y}{\wedge}e_{z}}} \ee 900 901 .. math:: \be {\boldsymbol{\nabla}} f = \partial_{x} f{\boldsymbol{e_{x}}}+\partial_{y} f{\boldsymbol{e_{y}}}+\partial_{z} f{\boldsymbol{e_{z}}} \ee 902 903 .. math:: \be {\boldsymbol{\nabla}} \cdot {\boldsymbol{A}} = \partial_{x} A^{x} + \partial_{y} A^{y} + \partial_{z} A^{z} \ee 904 905 .. math:: 906 907 \begin{aligned} 908 {\boldsymbol{\nabla}} {\boldsymbol{A}} = & \partial_{x} A^{x} + \partial_{y} A^{y} + \partial_{z} A^{z} \\ & +\lp - \partial_{y} A^{x} + \partial_{x} A^{y}\rp {\boldsymbol{e_{x}{\wedge}e_{y}}}+\lp - \partial_{z} A^{x} + \partial_{x} A^{z}\rp {\boldsymbol{e_{x}{\wedge}e_{z}}}+\lp - \partial_{z} A^{y} + \partial_{y} A^{z}\rp {\boldsymbol{e_{y}{\wedge}e_{z}}} \\ \end{aligned} 909 910 .. math:: \be -I ({\boldsymbol{\nabla}} {\wedge}{\boldsymbol{A}}) = \lp - \partial_{z} A^{y} + \partial_{y} A^{z}\rp {\boldsymbol{e_{x}}}+\lp \partial_{z} A^{x} - \partial_{x} A^{z}\rp {\boldsymbol{e_{y}}}+\lp - \partial_{y} A^{x} + \partial_{x} A^{y}\rp {\boldsymbol{e_{z}}} \ee 911 912 .. math:: 913 914 \begin{aligned} 915 {\boldsymbol{\nabla}} {\boldsymbol{B}} = & \lp - \partial_{y} B^{xy} - \partial_{z} B^{xz}\rp {\boldsymbol{e_{x}}}+\lp \partial_{x} B^{xy} - \partial_{z} B^{yz}\rp {\boldsymbol{e_{y}}}+\lp \partial_{x} B^{xz} + \partial_{y} B^{yz}\rp {\boldsymbol{e_{z}}} \\ & +\lp \partial_{z} B^{xy} - \partial_{y} B^{xz} + \partial_{x} B^{yz}\rp {\boldsymbol{e_{x}{\wedge}e_{y}{\wedge}e_{z}}} \\ \end{aligned} 916 917 .. math:: \be {\boldsymbol{\nabla}} {\wedge}{\boldsymbol{B}} = \lp \partial_{z} B^{xy} - \partial_{y} B^{xz} + \partial_{x} B^{yz}\rp {\boldsymbol{e_{x}{\wedge}e_{y}{\wedge}e_{z}}} \ee 918 919 .. math:: \be {\boldsymbol{\nabla}} \cdot {\boldsymbol{B}} = \lp - \partial_{y} B^{xy} - \partial_{z} B^{xz}\rp {\boldsymbol{e_{x}}}+\lp \partial_{x} B^{xy} - \partial_{z} B^{yz}\rp {\boldsymbol{e_{y}}}+\lp \partial_{x} B^{xz} + \partial_{y} B^{yz}\rp {\boldsymbol{e_{z}}} \ee 920 921 This example also demonstrates several other features of the latex printer. In the case that strings are input into the latex printer such as ``r'grad*\bm{A}'``, ``r'grad^\bm{A}'``, or ``r'grad*\bm{A}'``. The text symbols ``grad``, ``^``, ``|``, and ``*`` are mapped by the ``xpdf()`` post-processor as follows if the string contains an ``=``. 922 923 ========== =================== ============================== 924 original replacement displayed latex 925 ``grad*A`` ``\bm{\nabla}A`` :math:`{\boldsymbol{\nabla}}A` 926 ``A^B`` ``A\wedge B`` :math:`A\wedge B` 927 ``A|B`` ``A\cdot B`` :math:`A\cdot B` 928 ``A*B`` ``AB`` :math:`AB` 929 ``A<B`` ``A\rfloor B`` :math:`A\rfloor B` 930 ``A>B`` ``A\lfloor B`` :math:`A\lfloor B` 931 ``A>>B`` ``A\times B`` :math:`A\times B` 932 ``A<<B`` ``A\bar{\times} B`` :math:`A\bar{\times} B` 933 ========== =================== ============================== 934 935 If the first character in the string to be printed is a ``%`` none of the above substitutions are made before the latex processor is applied. In general for the latex printer strings are assumed to be in a math environment (equation or align) unless the first character in the string is a ``#``\ [25]_. 936 937 To get the latex string representation of a multivector ``A``, the :func:`printer.latex` function can be used as ``latex(A)``. 938 939 Printing Lists/Tuples of Multivectors/Differential Operators 940 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 941 942 Since the expressions for multivectors or differential operators can be very long printing lists or tuples of such items can easily exceed the page with when printing in LaTeX or in “ipython notebook.” I order to alleviate this problem the function ``Fmt`` can be used. 943 944 .. function:: galgebra.printer.Fmt(obj, fmt=0) 945 :noindex: 946 947 This function from the ``printer`` module allows the formatted printing of lists/tuples or multivectors/differential operators. 948 949 +-----------+---------------------------------------------------------------------------------+ 950 | ``obj`` | ``obj`` is a list or tuple of multivectors and/or differential operators. | 951 +-----------+---------------------------------------------------------------------------------+ 952 | ``fmt=0`` | ``fmt=0`` prints each element of the list/tuple on an individual lines\ [26]_. | 953 +-----------+---------------------------------------------------------------------------------+ 954 | | ``fmt=1`` prints all elements of the list/tuple on a single line\ [26]_. | 955 +-----------+---------------------------------------------------------------------------------+ 956 957 If l is a list or tuple to print in the LaTeX environment use the command 958 959 .. code:: python 960 961 print Fmt(l) # One element of l per line 962 963 or 964 965 .. code:: python 966 967 print Fmt(l, 1) # All elements of l on one line 968 969 If you are printing in “ipython notebook” then enter 970 971 .. code:: python 972 973 Fmt(l) # One element of l per line 974 975 or 976 977 .. code:: python 978 979 Fmt(l, 1) # All elements of l on one line 980 981 -------------- 982 983 984 .. [12] 985 Since ``X`` or the metric tensor can be functions of coordinates the vector space that the geometric algebra is constructed from is not necessarily flat so that the geometric algebra is actually constructed on the tangent space of the manifold which is a vector space. 986 987 .. [13] 988 The signature of the vector space, :math:`(p,q)`, is required to determine whether the square of the normalized pseudoscalar, :math:`I`, is :math:`+1` or :math:`-1`. In the future the metric tensor would be required to create a generalized spinor (:cite:`Hestenes`, pg106). 989 990 .. [14] 991 Using LaTeX output if a basis vector is denoted by :math:`{{\eb}}_{x}` then :math:`{{\eb}}` is the root symbol and :math:`x` is the subscript 992 993 .. [15] 994 There is a multivector class, ``Mv``, but in order the insure that every multivector is associated with the correct geometric algebra we always use the member function ``Ga.mv`` to instantiate the multivector. 995 996 .. [16] 997 Denoted in text output by ``A__x``, etc. so that for text output ``A`` would be printed as ``A__x*e_x+A__y*e_y+A__z*e_z``. 998 999 .. [18] 1000 In the future it should be possible to generate closed form expressions for :math:`e^{A}` if :math:`A^{r}` is a scalar for some integer :math:`r`. 1001 1002 .. [21] 1003 Remember that normalization is currently supported only for orthogonal systems (diagonal metric tensors). 1004 1005 .. [22] 1006 The 180 in the *ConEmu* command line is the width of the console you wish to display in characters. Change the number to suit you. 1007 1008 .. [23] 1009 I am not exactly sure what the different parameter setting do. I achieved the result I wished for by trial and error. I encourage the users to experiment and share their results. 1010 1011 .. [24] 1012 In *IPython notebook* tuples, or lists, or dictionaries of multivectors do print correctly. One mode of ``Fmt()`` corrects this deficiency. 1013 1014 .. [25] 1015 Preprocessing do not occur for the IPython notebook and the string post processing commands ``%`` and ``#`` are not used in this case. 1016 1017 .. [26] 1018 The formatting of each element is respected as applied by ``A.Fmt(fmt=1,2, or 3)`` where ``A`` is an element of ``obj`` so that if multivector/differential operation have been formatted to print on multiple lines it will printed on multiple lines. 1019 1020 .. |image0| image:: images/submanifold.svg 1021 .. |image1| image:: images/submanifold1.svg 1022 .. |image2| image:: images/LtransInst.svg 1023 .. |image3| image:: images/Ltrans.svg 1024 .. |image4| image:: images/Dop.svg