Module Components
Warning
This page is converted from the original \(\LaTeX\) documentation, but may no longer reflect the current state of the library. See the API docs at galgebra (galgebra) for more up-to-date but less structured and in-depth descriptions.
If you would like to help with merging the descriptions on the API with a description on this page, please head over to #300 on GitHub, where there’s an explanation of how to do so. Even merging just one function explanation helps!
Any function or class below with a [source]
link to its right is
guaranteed to be up-to-date already, as its documentation is identical on
both pages.
The geometric algebra module consists of the following files and classes
File |
Classes |
Usage |
---|---|---|
|
Instantiates metric tensor and derivatives of basis vectors. Normalized basis if required. |
|
|
Instantiates geometric algebra (inherits |
|
Instantiates geometric algebra for submainfold (inherits |
||
|
Instantiates multivector. |
|
Instantiates linear multivector differential operator. |
||
|
Instantiates multivector linear transformation. |
|
|
Starts enhanced text printing on ANSI terminal (requires |
|
Text printer for all geometric algebra classes (inherits from |
||
\(\LaTeX\)printer for all geometric algebra classes (inherits from |
Instantiating a Geometric Algebra
The geometric algebra class is instantiated with
- class galgebra.ga.Ga(basis, g=None, coords=None, X=None, norm=False, sig='e', Isq='-', wedge=True, debug=False)
The
basis
andg
parameters were described in section Vector Basis and Metric. 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 haver, th, phi = coords = symbols('r,theta,phi', real=True) basis = 'e_r e_theta e_phi' g = [1, r**2, r**2*sin(th)**2] sp3d = Ga(basis, g=g, coords=coords, norm=True)
The input
X
allows the metric to be input as a vector manifold.X
is a list of functions ofcoords
of dimension, \(m\), equal to or greater than the number of coordinates. Ifg=None
it is assumed thatX
is a vector in an \(m\)-dimensional orthonormal Euclidean vector space. If it is wished the embedding vector space to be non-Euclidean that condition is specified withg
. For example if we wish the embedding space to be a 5-dimensional Minkowski space theng=[-1, 1, 1, 1, 1]
. Then the Ga class usesX
to calculate the manifold basis vectors as a function of the coordinates and from them the metric tensor[12].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 generalsympy* expression (one that has an unknown sign).*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.
sig
indicates the signature of the vector space in the following ways[13].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.
If the metric tensor is not purely numerical and orthogonal the following hints are used (dimension of vector space is \(n\))
sig='e'
the default hint assumes the signature is for a Euclidean space with signature \((n,0)\).sig='m+'
assumes the signature if for the Minkowski space \((n-1,1)\).sig='m-'
assumes the signature if for the Minkowski space \((1,n-1)\).sig=p
wherep
is an integer \(p\le n\) and the signature it \((p,n-p)\).
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.
Currently one need not be concerned about inputting
sig
unless one in using the Ga member functionGa.I()
or the functionsMv.dual()
orcross()
which also useGa.I()
.If \(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.If
wedge=True
the basis blades of a multivector are printed using the^
symbol between basis vectors. Ifwedge=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 \({{\eb}}_{x}\), \({{\eb}}_{y}\), and \({{\eb}}_{z}\) the grade 3 basis blade would be printed as \({{\eb}}_{xyz}\).If
debug=True
the data structures required to initialize the Ga class are printed out.To get the basis vectors for
sp3d
we would have to use the member functionGa.mv()
in the former, eth, ephi = sp3d.mv()
To access the reciprocal basis vectors of the geometric algebra use the member function mvr()
- galgebra.ga.Ga.mvr(norm='True')
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 bothmv()
andmvr()
)e_x, e_y, e_z = o3d.mv() e__x, e__y, e__z = o3d.mvr()
If
norm='True'
or the basis vectors are orthogonal the dot product of the basis vector and the corresponding reciprocal basis vector is one \({\lp {e_{i}\cdot e^{j}=\delta_{i}^{j}} \rp }\). Ifnorm='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, \(I^{2}\), of the geometric algebra \({\lp {e_{i}\cdot e^{j}=E^{2}\delta_{i}^{j}} \rp }\).
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()
.
- galgebra.ga.Ga.grads()
Ga.grads()
returns a tuple with the left and right geometric derivative operators. A typical usage would begrad, rgrad = sp3d.grads()
for the spherical 3-d geometric algebra. The left derivative \({\lp {{\texttt{grad}} ={\boldsymbol{\nabla}}} \rp }\) and the right derivative \({\lp {{\texttt{rgrad}} = {\boldsymbol{\bar{\nabla}}}} \rp }\) have been explained in section Linear Differential Operators. Again the names
grad
andrgrad
used in a program are whatever the user chooses them to be. In the previous examplegrad
andrgrad
are used.
an alternative instantiation method is
- galgebra.ga.Ga.build(basis, g=None, coords=None, X=None, norm=False, debug=False)
The input parameters for
Ga.build()
are the same as forGa()
. The difference is that in addition to returning the geometric algebraGa.build()
returns the basis vectors at the same time. UsingGa.build()
in the previous example givesr, th, phi = coords = symbols('r,theta,phi', real=True) basis = 'e_r e_theta e_phi' g = [1, r**2, r**2*sin(th)**2] sp3d, er, eth, ephi = Ga.build(basis, g=g, coord=coords, norm=True)
To access the pseudo scalar of the geometric algebra use the member function I()
.
- galgebra.ga.Ga.I()
Ga.I()
returns the normalized pseudo scalar \({\lp {{\left |{I^{2}}\right |}=1} \rp }\) for the geometric algebra. For example \(I = \mbox{{\texttt{o3d.I()}}}\) for theo3d
geometric algebra. This function requires the signature of the vector space (see instantiating a geometric algebra).
- galgebra.ga.Ga.E()
Ga.E()
returns the unnormalized pseudo scalar \(E_{n} = {\eb}_{1}{\wedge}\dots{\wedge}{\eb}_{n}\) for the geometric algebra.
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
Object |
Class |
|
---|---|---|
multivector |
||
submanifold |
||
linear transformation |
||
differential operator |
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.
Instantiating a Multivector
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:
- galgebra.ga.Ga.mv(name, mode, f=False)
As an example of both instantiating a geometric algebra and multivectors consider the following code fragment for a 3-d Euclidean geometric algebra.
from sympy import symbols from ga import Ga x, y, z = coords = symbols('x,y,z',real=True) o3d = Ga('e_x e_y e_z', g=[1, 1, 1], coords=coords) ex, ey, ez = o3d.mv() V = o3d.mv('V', 'vector', f=True) f = o3d.mv(x*y*z) B = o3d.mv('B', 2)
First consider the multivector instantiation in line 6,
V = o3d.mv('V','vector',f=True)
.Here a 3-dimensional multivector field that is a function of
x
,y
, andz
(f=True
) is being instantiated. If latex output were used (to be discussed later) the multivectorV
would be displayed as\[\be V^{x}\eb_{x} + V^{y}\eb_{y} + V^{z}\eb_{z} \ee\]Where the coefficients of the basis vectors are generalized sympy functions of the coordinates. If
f=(x,y)
then the coefficients would be functions ofx
andy
. In general isf
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 arename
mode
result
string s
scalar
symbolic scalar of value Symbol(s)
string s
vector
symbolic vector
string s
grade2
orbivector
symbolic bivector
string s
r
(integer)symbolic r-grade multivector
string s
pseudo
symbolic pseudoscalar
string s
spinor
symbolic even multivector
string s
mv
symbolic general multivector
scalar c
None
zero grade multivector with coefficient value c
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 algebrao3d
. 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 functionF = x**2*ex + z*ey + x*y*ez
or the bivector function
B = z*(ex^ey) + y*(ey^ez) + y*(ex^ez).
Line 7 is an example of instantiating a multivector scalar function (a multivector with only a scalar part). If we print
f
the result isx*y*z
. Line 8 is an example of instantiating a grade \(r\) (in the example a grade 2) multivector where\[\be B = B^{xy}{\eb}_{x}{\wedge}{\eb}_{y}+B^{yz}{\eb}_{y}{\wedge}{\eb}_{z}+B^{xz}{\eb}_{x}{\wedge}{\eb}_{z}. \ee\]
If one wished to calculate the left and right geometric derivatives of F
and B
the required code would be
grad, rgrad = o3d.grads()
dF = grad*F
dB = grad*B
dFr = F*rgrad
dBr = B*rgrad
dF
, dB
, dFr
, and dBr
are all multivector functions. For the code where the order of the operations are reversed
grad, rgrad = o3d.grads()
dFop = F*grad
dBop = B*grad
dFrop = rgrad*F
dBrop = rgrad*B
dFop
, dBop
, dFrop
, and dBrop
are all multivector differential operators (again see section Linear Differential Operators).
Backward Compatibility Class MV
In order to be backward compatible with older versions of galgebra we introduce the class MV
which is inherits it’s functions from then class Mv. To instantiate a geometric algebra using MV use the static function
- static MV.setup(basis, metric=None, coords=None, rframe=False, debug=False, curv=(None, None)) list [source]
This function allows a single geometric algebra to be created.
If the function is called more than once the old geometric algebra is overwritten by the new geometric algebra. The named input
metric
is the same as the named inputg
in the current version of galgebra. Likewise,basis
,coords
, anddebug
are the same in the old and current versions of galgebra [17]. Due to improvements in sympy the inputsrframe
andcurv[1]
are no longer required.curv[0]
is the vector function (list or tuple of scalar functions) of the coordinates required to define a vector manifold. For compatibility with the old version of galgebra ifcurv
is usedmetric
should be a orthonormal Euclidean metric of the same dimension ascurv[0]
.It is strongly suggested that one use the new methods of defining a geometric algebra on a manifold.
- class galgebra.deprecated.MV(base, mvtype, fct=False, blade_rep=True)
For the instantiation of multivector using
MV
thebase
andmvtype
arguments are the same as for new methods of multivector instantiation. Thefct
input is the same and theg
input in the new methods.blade_rep
is not used in the new methods so settingblade_rep=False
will do nothing. Effectivelyblade_rep=False
was not used in the old examples.
Basic Multivector Class Functions
If we can instantiate multivectors we can use all the multivector class functions as described as follows.
- galgebra.mv.Mv.blade_coefs(basis_lst)
Find coefficients (sympy expressions) of multivector basis blade expansion corresponding to basis blades in
basis_lst
. For example if \(V = V^{x}{{\eb}}_{x}+V^{y}{{\eb}}_{x}+V^{z}{{\eb}}_{x}\) Then \(V\text{.blade_coefs}([{{\eb}}_{z},{{\eb}}_{x}]) = [V^{z},V^{x}]\) or if \(B = B^{xy}{{\eb}}_{x}{\wedge}{{\eb}}_{y}+V^{yz}{{\eb}}_{y}{\wedge}{{\eb}}_{z}\) then \(B\text{.blade_coefs}([{{\eb}}_{x}{\wedge}{{\eb}}_{y}]) = [B^{xy}]\).
- galgebra.mv.Mv.convert_to_blades()
Convert multivector from the base representation to the blade representation. If multivector is already in blade representation nothing is done.
- galgebra.mv.Mv.convert_from_blades()
Convert multivector from the blade representation to the base representation. If multivector is already in base representation nothing is done.
- galgebra.mv.Mv.diff(var)
Calculate derivative of each multivector coefficient with respect to variable
var
and form new multivector from coefficients.
- galgebra.mv.Mv.dual()
The mode of the
dual()
function is set by theGa
class static member function,GA.dual_mode(mode='I+')
of theGA
geometric galgebra which sets the following return values (\(I\) is the pseudo-scalar for the geometric algebraGA
)mode
Return Value
'+I'
\(IA\)
'I+'
\(AI\)
'-I'
\(-IA\)
'I-'
\(-AI\)
'+Iinv'
\(I^{-1}A\)
'Iinv+'
\(AI^{-1}\)
'-Iinv'
\(-I^{-1}A\)
'Iinv-'
\(-AI^{-1}\)
For example if the geometric algebra is
o3d
,A
is a multivector ino3d
, and we wish to usemode='I-'
. We set the mode with the functiono3d.dual('I-')
and get the dual ofA
with the functionA.dual()
which returns \(-AI\).If
o3d.dual(mode)
is not called the default for the dual mode ismode='I+'
andA*I
is returned.Note that
Ga.dual(mode)
used the functionGa.I()
to calculate the normalized pseudoscalar. Thus if the metric tensor is not numerical and orthogonal the correct hint for thensig
input of the Ga constructor is required.
- galgebra.mv.Mv.even()
Return the even grade components of the multivector.
- galgebra.mv.Mv.exp(hint='-')
If \(A\) is a multivector then \(e^{A}\) is defined for any \(A\) via the series expansion for \(e\). However as a practical matter we only have a simple closed form formula for \(e^{A}\) if \(A^{2}\) is a scalar[18]. If \(A^{2}\) is a scalar and we know the sign of \(A^{2}\) we have the following formulas for \(e^{A}\).
\[\begin{split}$\begin{aligned} A^{2} > 0 : & & &\\ 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}}}} \\ A^{2} < 0 : & & &\\ 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}}}} \\ A^{2} = 0 : & & &\\ A &=0 ,& e^{A} &= 1 + A \end{aligned}\end{split}\]The hint is required for symbolic multivectors \(A\) since in general sympy cannot determine if \(A^{2}\) is positive or negative. If \(A\) is purely numeric the hint is ignored since the sign can be calculated.
- galgebra.mv.Mv.expand()
Return multivector in which each coefficient has been expanded using sympy
expand()
function.
- galgebra.mv.Mv.factor()
Apply the
sympy
factor
function to each coefficient of the multivector.
- galgebra.mv.Mv.Fmt(fmt=1, title=None)
Fuction to print multivectors in different formats where
fmt
1
Print entire multivector on one line.
2
Print each grade of multivector on one line.
3
Print each base of multivector on one line.
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 thatFmt
only overrides the the global multivector printing format for the particular instance being printed. To reset the global multivector printing format use the functionFmt()
in thegalgebra.printer
module.
- galgebra.mv.Mv.func(fct)
Apply the
sympy
scalar functionfct
to each coefficient of the multivector.
- galgebra.mv.Mv.grade(igrade=0)
Return a multivector that consists of the part of the multivector of grade equal to
igrade
. If the multivector has noigrade
part return a zero multivector.
- galgebra.mv.Mv.inv()
Return the inverse of the multivector \(M\) (
M.inv()
). If \(M\) is a non-zero scalar return \(1/M\). If \(M^{2}\) is a non-zero scalar return \(M/{\lp {M^{2}} \rp }\), If \(MM^{{\dagger}}\) is a non-zero scalar return \(M^{{\dagger}}/{\lp {MM^{{\dagger}}} \rp }\). Otherwise exit the program with an error message.All division operators (
/
,/=
) use right multiplication by the inverse.
- galgebra.mv.Mv.norm(hint='+')
Return the norm of the multivector \(M\) (
M.norm()
) defined by \(\sqrt{{\left |{MM^{{\dagger}}}\right |}}\). If \(MM^{{\dagger}}\) is a scalar (a sympy scalar is returned). If \(MM^{{\dagger}}\) is not a scalar the program exits with an error message. If \(MM^{{\dagger}}\) is a number sympy can determine if it is positive or negative and calculate the absolute value. If \(MM^{{\dagger}}\) is a sympy expression (function) sympy cannot determine the sign of the expression so thathint='+'
orhint='-'
is needed to determine if the program should calculate \(\sqrt{MM^{{\dagger}}}\) or \(\sqrt{-MM^{{\dagger}}}\). For example if we are in a Euclidean space andM
is a vector thenhint='+'
, ifM
is a bivector then lethint='-'
. Ifhint='0'
and \(MM^{{\dagger}}\) is a symbolic scalarsqrt(Abs(M*M.rev()))
is returned whereAbs()
is the sympy symbolic absolute value function.
- galgebra.mv.Mv.norm2()
Return the the scalar defined by \(MM^{{\dagger}}\) if \(MM^{{\dagger}}\) is a scalar. If \(MM^{{\dagger}}\) is not a scalar the program exits with an error message.
- galgebra.mv.Mv.proj(bases_lst)
Return the projection of the multivector \(M\) (
M.proj(bases_lst)
) onto the subspace defined by the list of bases (bases_lst
).
- galgebra.mv.Mv.proj(lst)
Return the projection of the mutivector \(A\) onto the list, \(lst\), of basis blades. For example if \(A = A^{x}{{\eb}}_{x}+A^{y}{{\eb}}_{y}+A^{z}{{\eb}}_{z}\) then \(A.proj{\lp {[{{\eb}}_{x},{{\eb}}_{y}]} \rp } = A^{x}{{\eb}}_{x}+A^{y}{{\eb}}_{y}\). Similarly if \(A = A^{xy}{{\eb}}_{x}{\wedge}{{\eb}}_{y}+A^{yz}{{\eb}}_{y}{\wedge}{{\eb}}_{z}\) then \(A.proj{\lp {[{{\eb}}_{x}{\wedge}{{\eb}}_{y}]} \rp } = A^{xy}{{\eb}}_{x}{\wedge}{{\eb}}_{y}\).
- galgebra.mv.Mv.project_in_blade(blade)
Return the projection of the mutivector \(A\) in subspace defined by the blade, \(B\), using the formula \({\lp {A\rfloor B} \rp }B^{-1}\) in [AlanMacdonald10], page 121.
- galgebra.mv.Mv.pure_grade()
If the multivector \(A\) is pure (only contains one grade) return, \(A.pure\_grade()\), the index (‘0’ for a scalar, ‘1’ for vector, ‘2’ for a bi-vector, etc.) of the non-zero grade. If \(A\) is not pure return the negative of the highest non-zero grade index.
- galgebra.mv.Mv.odd()
Return odd part of multivector.
- galgebra.mv.Mv.reflect_in_blade(blade)
Return the reflection of the mutivector \(A\) in the subspace defined by the \(r\)-grade blade, \(B_{r}\), using the formula (extended to multivectors) \(\sum_{i} {\lp {-1} \rp }^{r{\lp {i+1} \rp }}{B}_{r}{\left < {A} \right >}_{i}B_{r}^{-1}\) in [AlanMacdonald10], page 129.
- galgebra.mv.Mv.rev()
Return the reverse of the multivector.
- galgebra.mv.Mv.rotate_multivector(itheta, hint='-')
Rotate the multivector \(A\) via the operation \(e^{-\theta i/2}Ae^{\theta i/2}\) where itheta = \(\theta i\), \(\theta\) is a scalar, and \(i\) is a unit, \(i^{2} = \pm 1\), 2-blade. If \({\lp {\theta i} \rp }^{2}\) is not a number
hint
is required to determine the sign of the square ofitheta
. The default chosen,hint='-'
, is correct for any Euclidean space.
- galgebra.mv.Mv.scalar()
Return the coefficient (sympy scalar) of the scalar part of a multivector.
- galgebra.mv.Mv.simplify(mode=simplify)
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 appliedtrigsimp
andratsimp
sympy functions to the multivectorF
the code would beFsimp = F.simplify(mode=[trigsimp, ratsimp]).
Actually
simplify
could be used to apply any scalar sympy function to the coefficients of the multivector.
- galgebra.mv.Mv.set_coef(grade, base, value)
Set the multivector coefficient of index
(grade, base)
tovalue
.
- galgebra.mv.Mv.subs(x)
Return multivector where sympy subs function has been applied to each coefficient of multivector for argument dictionary/list
x
.
- galgebra.mv.Mv.trigsimp(**kwargs)
Apply the
sympy
trigonometric simplification functiontrigsimp
to each coefficient of the multivector.**kwargs
are the arguments of trigsimp. Seesympy
documentation ontrigsimp
for more information.
Basic Multivector Functions
- static Ga.com(A, B)[source]
Calculate commutator of multivectors \(A\) and \(B\). Returns \((AB-BA)/2\).
Additionally, commutator and anti-commutator operators are defined by
\[\begin{split}\begin{aligned} \texttt{A >> B} \equiv & {\displaystyle\frac{AB - BA}{2}} \\ \texttt{A << B} \equiv & {\displaystyle\frac{AB + BA}{2}}. \end{aligned}\end{split}\]
- galgebra.mv.cross(v1: Mv, v2: Mv) Mv [source]
If
v1
andv2
are 3-dimensional Euclidean vectors, compute the vector cross product \(v_{1}\times v_{2} = -I{\lp {v_{1}{\wedge}v_{2}} \rp }\).
- galgebra.printer.def_prec(gd: dict, op_ord: str = '<>|,^,*') None [source]
This is used with the
GAeval()
function to evaluate a string representing a multivector expression with a revised operator precedence.- Parameters:
gd – The
globals()
dictionary to lookup variable names in.op_ord – The order of operator precedence from high to low with groups of equal precedence separated by commas. The default precedence,
'<>|,^,*'
, is that used by Hestenes ([HS84], p7, [DL03], p38). This means that the<
,>
, and|
operations have equal precedence, followed by^
, and lastly*
.
- galgebra.mv.exp(A: Mv | Expr, hint: str = '-') Mv | Expr [source]
If
A
is a multivector thenA.exp(hint)
is returned. IfA
is a sympy expression the sympy expression \(e^{A}\) is returned (seesympy.exp()
).
- galgebra.printer.GAeval(s: str, pstr: bool = False)[source]
Evaluate a multivector expression string
s
.The operator precedence and variable values within the string are controlled by
def_prec()
. The documentation for that function describes the default precedence.The implementation works by adding parenthesis to the input string
s
according to the requested precedence, and then callingeval()
on the result.For example consider where
X
,Y
,Z
, andW
are multivectors:def_prec(globals()) V = GAeval('X|Y^Z*W')
The sympy variable
V
would evaluate to((X|Y)^Z)*W
.- Parameters:
s – The string to evaluate.
pstr – If
True
, the values ofs
ands
with parenthesis added to enforce operator precedence are printed.
- galgebra.mv.Nga(x, prec=5)[source]
Like
sympy.N()
, but also works on multivectorsFor multivectors with coefficients that contain floating point numbers, this rounds all these numbers to a precision of
prec
and returns the rounded multivector.
- Ga.ReciprocalFrame(basis: Sequence[Mv], mode: str = 'norm') Tuple[Mv, ...] [source]
Compute the reciprocal frame \(v^i\) of a set of vectors \(v_i\).
- Parameters:
basis – The sequence of vectors \(v_i\) defining the input frame.
mode –
"norm"
– indicates that the reciprocal vectors should be normalized such that their product with the input vectors is 1, \(v^i \cdot v_j = \delta_{ij}\)."append"
– indicates that instead of normalizing, the normalization coefficient \(E^2\) should be appended to the returned tuple. One can divide by this coefficient to normalize the vectors. The returned vectors are such that \(v^i \cdot v_j = E^2\delta_{ij}\).
Deprecated since version 0.5.0: Arbitrary strings are interpreted as
"append"
, but in future will be an error
Multivector Derivatives
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
X = x, y, z = symbols('x y z')
o3d = Ga('e*x|y|z', metric=[1, 1, 1], coords=X)
ex, ey, ez = o3d.mv()
grad, rgrad = o3d.grads()
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 (\(\T{grad} = \nabla\) and \(\T{rgrad} = \bar{\nabla}\)). Another option is to use the radiant operator members of the geometric algebra directly where we have \(\nabla = {\texttt{o3d.grad}}\) and
\(\bar{\nabla} = {\texttt{o3d.rgrad}}\).
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
all return multivector linear differential operators.
Submanifolds
In general the geometric algebra that the user defines exists on the tangent space of a manifold (see section Manifolds and Submanifolds). 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
instantiated with
- galgebra.ga.Ga.sm(map, coords, root='e', norm=False)
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
andcoords
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 base manifold. The length ofmap
is equal to the dimension of the base manifold and each function inmap
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 ofroot
ise
. The result of this is that if the sympy symbols for the coordinates areu
andv
(two dimensional manifold) the text symbols for the basis vectors aree_u
ande_v
or in LaTeX \(e_{u}\) and \(e_{v}\). As a concrete example consider the following code.from sympy import symbols, sin, pi, latex from galgebra.ga import Ga from galgebra.printer import Format, xpdf Format() coords = (r, th, phi) = symbols('r,theta,phi', real=True) sp3d = Ga('e_r e_th e_ph', g=[1, r**2, r**2 * sin(th)**2], coords=coords, norm=True) sph_uv = (u, v) = symbols('u,v', real=True) sph_map = [1, u, v] # Coordinate map for sphere of r = 1 sph2d = sp3d.sm(sph_map, sph_uv) print(r'(u,v)\rightarrow (r,\theta,\phi) = ', latex(sph_map)) # FIXME submanifold basis vectors are not normalized, g is incorrect print('g =', latex(sph2d.g)) F = sph2d.mv('F', 'vector', f=True) # scalar function f = sph2d.mv('f', 'scalar', f=True) # vector function print(r'\nabla f =', sph2d.grad * f) print('F =', F) print(r'\nabla F = ', sph2d.grad * F) cir_s = s = symbols('s', real=True) cir_map = [pi / 8, s] cir1d = sph2d.sm(cir_map, (cir_s,)) print('g =', latex(cir1d.g)) h = cir1d.mv('h', 'scalar', f=True) H = cir1d.mv('H', 'vector', f=True) print(r'(s)\rightarrow (u,v) = ', latex(cir_map)) print('H =', H) print(latex(H)) print(r'\nabla h =', cir1d.grad * h) print(r'\nabla H =', cir1d.grad * H) xpdf(filename='submanifold.tex', paper=(6, 5), crop=True)
The output of this program (using LaTeX) is
The base manifold,
sp3d
, is a 3-d Euclidean space using standard spherical coordinates. The submanifoldsph2d
ofsp3d
is a spherical surface of radius \(1\). To take the sumanifold operation one step further the submanifoldcir1d
ofsph2d
is a circle insph2d
where the latitude of the circle is \(\pi/8\).In each case, for demonstration purposes, a scalar and vector function on each manifold is defined (
f
andF
for the 2-d manifold andh
andH
for the 1-d manifold) and the geometric derivative of each function is taken. The manifold mapping and the metric tensor forcir1d
ofsph2d
are also shown. Note that if the submanifold basis vectors are not normalized[21] the program output is
Linear Transformations
The mathematical background for linear transformations is in section Linear Transformations/Outermorphisms. 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
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
- galgebra.ga.Ga.lt(M, f=False, mode='g')
M
is an expression that can define the coefficients of the linear transformation in various ways defined as follows.M
Result
string
M
Coefficients are symbolic constants with names \(\T{M}^{x_{i}x_{j}}\) where \(x_{i}\) and \(x_{j}\) are the names of the \(i^{th}\) and \(j^{th}\) coordinates (see output of
Ltrans.py
).char
mode
If
M
is a string thenmode
determines whether the linear transformation is general,mode='g'
, symmetric,mode='s'
, or antisymmetric,mode='a'
. The default ismode='g'
.list
M
If
M
is a list of vectors equal in length to the dimension of the vector space then the linear transformation is \(\f{L}{\ebf_{i}} = \T{M}\mat{i}\). IfM
is a list of lists of scalars where all lists are equal in length to the dimension of the vector space then the linear transformation is\(\f{L}{\ebf_{i}} = \T{M}\mat{i}\mat{j}\ebf_{j}\).dict
M
If
M
is a dictionary the linear transformation is defined by \(\f{L}{\ebf_{i}} = \T{M}\mat{\ebf_{i}}\). If \(\ebf_{i}\) is not in the dictionary then \(\f{L}{\ebf_{i}} =0\).rotor
M
If
M
is a rotor, \(\T{M}\T{M}^{\R}=1\), the linear transformation is defined by \(\f{L}{{\ebf}_{i}} = \T{M}{\ebf}_{i}\T{M}^{\R}\) .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 \(\f{L}{\ebf_{i}} = \f{\T{M}}{\ebf_{i}}\).f
isTrue
orFalse
. IfTrue
the symbolic coefficients of the general linear transformation are instantiated as functions of the coordinates.
The different methods of instantiation are demonstrated in the code LtransInst.py
from __future__ import division
from __future__ import print_function
from sympy import symbols, sin, cos, latex, Matrix
from galgebra.ga import Ga
from galgebra.printer import Format, xpdf
Format()
(x, y, z) = xyz = symbols('x,y,z', real=True)
(o3d, ex, ey, ez) = Ga.build('e_x e_y e_z', g=[1, 1, 1], coords=xyz)
A = o3d.lt('A')
print(r'\mbox{General Instantiation: }A =', A)
th = symbols('theta', real=True)
R = cos(th / 2) + (ex ^ ey) * sin(th / 2)
B = o3d.lt(R)
print(r'\mbox{Rotor: }R =', R)
print(r'\mbox{Rotor Instantiation: }B =', B)
dict1 = {ex: ey + ez, ez: ey + ez, ey: ex + ez}
C = o3d.lt(dict1)
print(r'\mbox{Dictionary} =', latex(dict1))
print(r'\mbox{Dictionary Instantiation: }C =', C)
lst1 = [[1, 0, 1], [0, 1, 0], [1, 0, 1]]
D = o3d.lt(lst1)
print(r'\mbox{List} =', latex(lst1))
print(r'\mbox{List Instantiation: }D =', D)
lst2 = [ey + ez, ex + ez, ex + ey]
E = o3d.lt(lst2)
print(r'\mbox{List} =', latex(lst2))
print(r'\mbox{List Instantiation: }E =', E)
xpdf(paper=(10, 12), crop=True)
with output
The member function of the Lt
class are
- Lt.__call__(A)[source]
Returns the image of the multivector \(A\) under the linear transformation \(L\).
\({{L}\lp {A} \rp }\) is defined by the linearity of \(L\), the vector values \({{L}\lp {{{\eb}}_{i}} \rp }\), and the definition \({{L}\lp {{{\eb}}_{i_{1}}{\wedge}\dots{\wedge}{{\eb}}_{i_{r}}} \rp } = {{L}\lp {{{\eb}}_{i_{1}}} \rp }{\wedge}\dots{\wedge}{{L}\lp {{{\eb}}_{i_{r}}} \rp }\).
- Lt.det() Expr [source]
Returns the determinant (a scalar) of the linear transformation, \(L\), defined by \({{\det}\lp {L} \rp }I = {{L}\lp {I} \rp }\).
- Lt.adj() Lt [source]
Returns the adjoint (a linear transformation) of the linear transformation, \(L\), defined by \(a\cdot{{L}\lp {b} \rp } = b\cdot{{\bar{L}}\lp {a} \rp }\) where \(a\) and \(b\) are any two vectors in the tangent space and \(\bar{L}\) is the adjoint of \(L\).
- Lt.tr() Expr [source]
Returns the trace (a scalar) of the linear transformation, \(L\), defined by \({{\operatorname{tr}}\lp {L} \rp }=\nabla_{a}\cdot{{L}\lp {a} \rp }\) where \(a\) is a vector in the tangent space.
- Lt.matrix() MutableDenseMatrix [source]
Returns the matrix representation of the linear transformation, \(L\), defined by \({{L}\lp {{{\eb}}_{i}} \rp } = L_{ij}{{\eb}}_{j}\) where \(L_{ij}\) is the matrix representation.
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 \(A\) and \(B\) are linear transformations, \(V\) a multivector, and \(\alpha\) a scalar then \({{{\lp {A\pm B} \rp }}\lp {V} \rp } = {{A}\lp {V} \rp }\pm{{B}\lp {V} \rp }\), \({{{\lp {AB} \rp }}\lp {V} \rp } = {{A}\lp {{{B}\lp {V} \rp }} \rp }\), and
\({{{\lp {\alpha A} \rp }}\lp {V} \rp } = \alpha{{A}\lp {V} \rp }\).
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()
.
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.
from sympy import symbols, sin, cos, latex
from galgebra.ga import Ga
from galgebra.printer import Format, xpdf
Format()
(x, y, z) = xyz = symbols('x,y,z', real=True)
(o3d, ex, ey, ez) = Ga.build('e_x e_y e_z', g=[1, 1, 1], coords=xyz)
grad = o3d.grad
(u, v) = uv = symbols('u,v', real=True)
(g2d, eu, ev) = Ga.build('e_u e_v', coords=uv)
grad_uv = g2d.grad
A = o3d.lt('A')
print('#3d orthogonal ($A,\\;B$ are linear transformations)')
print('A =', A)
print(r'\f{\operatorname{mat}}{A} =', latex(A.matrix()))
print('\\f{\\det}{A} =', A.det())
print('\\overline{A} =', A.adj())
print('\\f{\\Tr}{A} =', A.tr())
print('\\f{A}{e_x^e_y} =', A(ex ^ ey))
print('\\f{A}{e_x}^\\f{A}{e_y} =', A(ex) ^ A(ey))
B = o3d.lt('B')
print('A + B =', A + B)
print('AB =', A * B)
print('A - B =', A - B)
# FIXME linear transformations fail to simplify
# using dot products of bases
print('#2d general ($A,\\;B$ are linear transformations)')
A2d = g2d.lt('A')
print('A =', A2d)
print('\\f{\\det}{A} =', A2d.det())
# A2d.adj().Fmt(4,'\\overline{A}')
print('\\f{\\Tr}{A} =', A2d.tr())
print('\\f{A}{e_u^e_v} =', A2d(eu ^ ev))
print('\\f{A}{e_u}^\\f{A}{e_v} =', A2d(eu) ^ A2d(ev))
B2d = g2d.lt('B')
print('B =', B2d)
print('A + B =', A2d + B2d)
print('AB =', A2d * B2d)
print('A - B =', A2d - B2d)
a = g2d.mv('a', 'vector')
b = g2d.mv('b', 'vector')
print(r'a|\f{\overline{A}}{b}-b|\f{\underline{A}}{a} =',
((a | A2d.adj()(b)) - (b | A2d(a))).simplify())
print('#4d Minkowski spaqce (Space Time)')
m4d = Ga('e_t e_x e_y e_z', g=[1, -1, -1, -1],
coords=symbols('t,x,y,z', real=True))
T = m4d.lt('T')
print('g =', m4d.g)
# FIXME incorrect sign for T and T.adj()
print(r'\underline{T} =', T)
print(r'\overline{T} =', T.adj())
# m4d.mv(T.det()).Fmt(4,r'\f{\det}{\underline{T}}')
print(r'\f{\mbox{tr}}{\underline{T}} =', T.tr())
a = m4d.mv('a', 'vector')
b = m4d.mv('b', 'vector')
print(r'a|\f{\overline{T}}{b}-b|\f{\underline{T}}{a} =',
((a | T.adj()(b)) - (b | T(a))).simplify())
xpdf(paper=(10, 12), debug=True)
The output of this code is.
Differential Operators
For the mathematical treatment of linear multivector differential operators see section Linear Differential Operators. 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.
from sympy import symbols, sin
from galgebra.printer import Format, xpdf
from galgebra.ga import Ga
Format()
coords = (x, y, z) = symbols('x y z', real=True)
(o3d, ex, ey, ez) = Ga.build('e*x|y|z', g=[1, 1, 1], coords=coords)
X = x * ex + y * ey + z * ez
I = o3d.i
v = o3d.mv('v', 'vector')
f = o3d.mv('f', 'scalar', f=True)
A = o3d.mv('A', 'vector', f=True)
dd = v | o3d.grad
lap = o3d.grad * o3d.grad
print(r'\bm{X} =', X)
print(r'\bm{v} =', v)
print(r'\bm{A} =', A)
print(r'%\bm{v}\cdot\nabla =', dd)
print(r'%\nabla^{2} =', lap)
print(r'%\bm{v}\cdot\nabla f =', dd * f)
print(r'%\nabla^{2} f =', lap * f)
print(r'%\nabla^{2} \bm{A} =', lap * A)
print(r'%\bar{\nabla}\cdot v =', o3d.rgrad | v)
Xgrad = X | o3d.grad
rgradX = o3d.rgrad | X
print(r'%\bm{X}\cdot \nabla =', Xgrad)
# FIXME This outputs incorrectly, the scalar part 3 is missing
print(r'%\bar{\nabla}\cdot \bm{X} =', rgradX)
# FIXME The following code complains:
# ValueError: In Dop.Add complement flags have different values: False vs. True
# com = Xgrad - rgradX
# print(r'%\bm{X}\cdot \nabla - \bar{\nabla}\cdot \bm{X} =', com)
sph_coords = (r, th, phi) = symbols('r theta phi', real=True)
(sp3d, er, eth, ephi) = Ga.build('e', g=[1, r**2, r**2 * sin(th)**2],
coords=sph_coords, norm=True)
f = sp3d.mv('f', 'scalar', f=True)
lap = sp3d.grad * sp3d.grad
print(r'%\nabla^{2} = \nabla\cdot\nabla =', lap)
print(r'%\lp\nabla^{2}\rp f =', lap * f)
print(r'%\nabla\cdot\lp\nabla f\rp =', sp3d.grad | (sp3d.grad * f))
# FIXME crop didn't work, but pdf can be generated with TexLive 2017 installed
xpdf(paper='landscape', crop=True)
The output of this code is.
Note that for print an operator in the IPython notebook one must implement (yet to be done) a printing method similar to mv.Fmt()
.
Instantiating a Multi-linear Functions (Tensors)
The mathematical background for multi-linear functions is in section Multilinear Functions. To instantiate a multi-linear function use
- class galgebra.lt.Mlt(f, Ga, nargs=None, fct=False)
Where the arguments are
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 python function such as shown inTensorDef.py
.Ga
Geometric algebra that tensor is associated with.
nargs
If
f
is a string thennargs
is the number of vector arguments of the tensor. Iff
is anything other than a stringnargs
is not required sinceMlt
determines the number of vector arguments fromf
.fct
If
f
is a string thenfct=True
forces the tensor to be a tensor field (function of the coordinates. Iff
anything other than a stringfct
is not required sinceMlt
determines whether the tensor is a tensor field fromf
.
import sys
from sympy import symbols, sin, cos
from galgebra.printer import Format, xpdf, Print_Function
from galgebra.ga import Ga
from galgebra.lt import Mlt
coords = symbols('t x y z', real=True)
(st4d, g0, g1, g2, g3) = Ga.build('gamma*t|x|y|z', g=[1, -1, -1, -1],
coords=coords)
A = st4d.mv('T', 'bivector')
def TA(a1, a2):
return A | (a1 ^ a2)
T = Mlt(TA, st4d) # Define multi-linear function
Basic Multilinear Function Class Functions
If we can instantiate multilinear functions we can use all the multilinear function class functions as described as follows. See section Multilinear Functions for the mathematical description of each operation.
- Mlt.__call__(*args)[source]
Evaluate the multilinear function for the given vector arguments. Note that a sympy scalar is returned, not a multilinear function.
- Mlt.contract(slot1: int, slot2: int)[source]
Returns contraction of tensor between
slot1
andslot2
whereslot1
is the index of the first vector argument andslot2
is the index of the second vector argument of the tensor.For example if we have a rank two tensor,
T(a1, a2)
, thenT.contract(1, 2)
is the contraction ofT
. For this case since there are only two slots, there can only be one contraction.
- Mlt.pdiff(slot: int)[source]
Returns gradient of tensor,
T
, with respect to slot vector.For example if the tensor is \({{T}\lp {a_{1},a_{2}} \rp }\) then
T.pdiff(2)
is \(\nabla_{a_{2}}T\). SinceT
is a scalar function,T.pdiff(2)
is a vector function.
- Mlt.cderiv()[source]
Returns covariant derivative of tensor field.
If
T
is a tensor of rank \(k\) thenT.cderiv()
is a tensor of rank \(k+1\). The operation performed is defined in section Multilinear Functions.
Standard Printing
Printing of multivectors is handled by the module 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 printer.Eprint
class that enhances the console output of sympy to make the printed output multivectors, functions, and derivatives more readable. printer.Eprint
requires an ansi console such as is supplied in linux or the program ConEmu replaces cmd.exe
.
For a windows user the simplest way to implement ConEmu is to use the geany editor and in the Edit\(\rightarrow\)Preferences\(\rightarrow\)Tools menu replace cmd.exe
with[22]
"C:\Program Files\ConEmu\ConEmu64.exe" /WndW 180 /cmd %c
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]
Right click on title bar of console.
Open setting window.
Open colors window.
Set the following parameters to the indicated values:
Text: #0
Back: #7
Popup: #0
Back: #7
\(\rlap{ \checkmark }\square\) Extend foreground colors with background #13
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.
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.
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.).
Latex Printing
For latex printing one uses one functions from the ga
module and one function from the printer
module. The functions are
- galgebra.printer.Format(Fmode: bool = True, Dmode: bool = True, inverse='full')[source]
Turns on latex printing with configurable options.
This redirects printer output so that latex compiler can capture it.
Format()
is also required for printing from ipython notebook (note thatxpdf()
is not needed to print from ipython notebook).- Parameters:
Fmode – Value for the
omit_function_args
setting ofGaLatexPrinter
.Dmode – Value for the
omit_partial_derivative_fraction
setting ofGaLatexPrinter
.
- galgebra.printer.Fmt(obj, fmt=1)
Fmt()
can be used to set the global multivector printing format or to print a tuple, list, of dictionary[24]. The modes and operation ofFmt()
are as follows:obj
Effect
obj=1,2,3
Global multivector format is set to 1, 2, or 3 depending on
obj
. See multivector member functionFmt()
for effect ofobj
value.obj=tuple/list/dict
The printing format of an object that is a tuple, list, or dict is controlled by the
fmt
argument inFmt
:fmt=1
: Print completeobj
on one line.fmt=2
: Print one element ofobj
on each line.
- galgebra.printer.xpdf(filename=None, debug=False, paper=(14, 11), crop=False)
This function from the
printer
module post-processes the output captured from print statements, writes the resulting latex strings to the filefilename
, processes the file with pdflatex, and displays the resulting pdf file. All latex files except the pdf file are deleted. Ifdebug = True
the filefilename
is printed to standard output for debugging purposes andfilename
(the tex file) is saved. Iffilename
is not entered the default filename is the root name of the python program being executed with.tex
appended. Thepaper
option defines the size of the paper sheet for latex. The format for thepaper
ispaper=(w,h)
w
is paper width in inches andh
is paper height in inchespaper='letter'
paper is standard letter size 8.5 in \(\times\) 11 in
paper='landscape'
paper is standard letter size but 11 in \(\times\) 8.5 in
The default of
paper=(14,11)
was chosen so that long multivector expressions would not be truncated on the display.If the
crop
input isTrue
the linuxpdfcrop
program is used to crop the pdf output (if output is one page). This only works for linux installations (wherepdfcrop
is installed).The
xpdf
function requires that latex and a pdf viewer be installed on the computer.xpdf
is not required when printing latex in IPython notebook.
As an example of using the latex printing options when the following code is executed
from printer import Format, xpdf
from ga import Ga
Format()
g3d = Ga('e*x|y|z')
A = g3d.mv('A', 'mv')
print(r'\bm{A} =',A)
print(A.Fmt(2,r'\bm{A}'))
print(A.Fmt(3,r'\bm{A}'))
xpdf()
The following is displayed
For the cases of derivatives the code is
from printer import Format, xpdf
from ga import Ga
Format()
X = x, y, z = symbols('x y z')
o3d = Ga('e_x e_y e_z',g=[1,1,1],coords=X)
f = o3d.mv('f', 'scalar', f=True)
A = o3d.mv('A', 'vector', f=True)
B = o3d.mv('B', 'grade2', f=True)
print(r'\bm{A} =', A)
print(r'\bm{B} =', B)
print('grad*f =', o3d.grad*f)
print(r'grad|\bm{A} =', o3d.grad|A)
(o3d.grad*A).Fmt(2, r'grad*\bm{A}')
print(r'-I*(grad^\bm{A}) =', -o3g.mv_I*(o3d.grad^A))
print((o3d.grad*B).Fmt(2, r'grad*\bm{B}'))
print(r'grad^\bm{B} =', o3d.grad^B)
print(r'grad|\bm{B} =', o3d.grad|B)
xpdf()
and the latex displayed output is (\(f\) is a scalar function)
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 =
.
original |
replacement |
displayed latex |
|
|
\({\boldsymbol{\nabla}}A\) |
|
|
\(A\wedge B\) |
|
|
\(A\cdot B\) |
|
|
\(AB\) |
|
|
\(A\rfloor B\) |
|
|
\(A\lfloor B\) |
|
|
\(A\times B\) |
|
|
\(A\bar{\times} B\) |
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].
To get the latex string representation of a multivector A
, the printer.latex()
function can be used as latex(A)
.
Printing Lists/Tuples of Multivectors/Differential Operators
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.
- galgebra.printer.Fmt(obj, fmt=0)
This function from the
printer
module allows the formatted printing of lists/tuples or multivectors/differential operators.obj
obj
is a list or tuple of multivectors and/or differential operators.fmt=0
fmt=0
prints each element of the list/tuple on an individual lines[26].fmt=1
prints all elements of the list/tuple on a single line[26].If l is a list or tuple to print in the LaTeX environment use the command
print Fmt(l) # One element of l per line
or
print Fmt(l, 1) # All elements of l on one line
If you are printing in “ipython notebook” then enter
Fmt(l) # One element of l per line
or
Fmt(l, 1) # All elements of l on one line
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.
The signature of the vector space, \((p,q)\), is required to determine whether the square of the normalized pseudoscalar, \(I\), is \(+1\) or \(-1\). In the future the metric tensor would be required to create a generalized spinor ([HS84], pg106).
Using LaTeX output if a basis vector is denoted by \({{\eb}}_{x}\) then \({{\eb}}\) is the root symbol and \(x\) is the subscript
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.
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
.
In the future it should be possible to generate closed form expressions for \(e^{A}\) if \(A^{r}\) is a scalar for some integer \(r\).
Remember that normalization is currently supported only for orthogonal systems (diagonal metric tensors).
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.
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.
In IPython notebook tuples, or lists, or dictionaries of multivectors do print correctly. One mode of Fmt()
corrects this deficiency.
Preprocessing do not occur for the IPython notebook and the string post processing commands %
and #
are not used in this case.
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.