# galgebra.ga¶

Geometric Algebra (inherits Metric)

## Members¶

class galgebra.ga.Ga(bases, **kwargs)[source]

The vector space (basis, metric, derivatives of basis vectors) is defined by the base class ‘Metric’.

The instanciating the class ‘Ga’ constructs the geometric algebra of the vector space defined by the metric.

The construction includes the multivector bases, multiplication tables or functions for the geometric (*), inner (|), outer (^) products, plus the left (<) and right (>) contractions. The geometric derivative operator and any required connections for the derivative are also calculated.

Except for the geometric product in the case of a non-orthogonal set of basis vectors all products and connections (if needed) are calculated when needed and place in dictionaries (lists of tuples) to be used when needed. This greatly speeds up evaluations of multivector expressions over previous versions of this code since the products of multivector bases and connection are not calculated unless they are actually needed in the current calculation.

Only instantiate the Ga class via the Mv class or any use of enhanced printing (text or latex) will cause the bases and multiplication table entries to be incorrectly labeled .

Data Variables -

Inherited from Metric class -

g[,]: Metric tensor (sympy matrix) g_inv[,]: Inverse of metric tensor (sympy matirx) norm: Normalized diagonal metric tensor (list of sympy numbers) coords[]: Coordinate variables (list of sympy symbols) is_ortho: True if basis is orthogonal (bool) connect_flg: True if connection is non-zero (bool) basis[]: Basis vector symbols (list of non-commutative sympy variables) r_symbols[]: Reciprocal basis vector symbols (list of non-commutative sympy variables) n: Dimension of vector space/manifold (integer) n_range: List of basis indices de[][]: Derivatives of basis functions. Two dimensional list. First

entry is differentiating coordiate. Second entry is basis vector. Quantities are linear combinations of basis vector symbols.

Basis, basis bases, and basis blades data structures -

indexes[]: Index list for multivector bases and blades by grade (tuple of tuples). Tuple
so that indexes can be used to index dictionaries.
bases[]: List of bases (non-commutative sympy symbols). Only created for
non-orthogonal basis vectors.
orthogonal basis vectors the same as bases.
coord_vec: Linear combination of coordinates and basis vectors. For
example in orthogonal 3D x*e_x+y*e_y+z*e_z.

blades_to_indexes_dict{}: Map basis blades to index tuples (dictionary). indexes_to_blades_dict{}: Map index tuples to basis blades (dictionary). bases_to_indexes_dict{}: Map basis bases to index tuples (dictionary). indexes_to_bases_dict{}: Map index tuples to basis bases (dictionary). pseudoI: Symbol for pseudo scalar (non-commutative sympy symbol).

Multiplication tables data structures -

Keys in all multiplication tables (*,^,|,<,>) are always symbol1*symbol2. The correct operation is known by the context (name) of the relevant list or dictionary)

mul_table[]: Geometric products of basis blades as list of [(base1*base2, Expansion of base1*base2),…] mul_table_dict{}: Geometric products of basis blades as dicitionary {base1*base2: Expansion of base1*base2,…} wedge_table[]: Outer products of basis blades as list of [(base1*base2, Expansion of base1^base2),…] wedge_table_dict{}: Outer products of basis blades as dicitionary {base1*base2: Expansion of base1^base2,…}

Reciprocal basis data structures -

r_symbols[]: Reciprocal basis vector symbols (list of non-commutative sympy variables) r_basis[]: List of reciprocal basis vectors expanded as linear combination of basis vector symbols. r_basis_dict{}: Dictionary to map reciprocal basis symbols to reciprocal basis expanded in terms of basis symbols

{reciprocal basis symbol: linear combination of basis symbols,…}
r_basis_mv[]: List of reciprocal basis vectors in terms of basis multivectors (elements of list can be used in
multivector expressions.)

Derivative data structures -

de[][]: Derivatives of basis functions. Two dimensional list. First entry is differentiating coordinate index.
Second entry is basis vector index. Quantities are linear combinations of basis vector symbols.
dbases{}: Dictionary of derivatives of basis blades with respect to coordinate {(coordinate index, basis blade):
derivative of basis blade with respect to coordinate,…} (Note that values in dictionary are not multivectors, but linear combinations of basis blade symbols).

Pdop_identity: Partial differential operator identity (operates on multivector function to return function). Pdiffs{}: Dictionary of partial differential operators (operates on multivector functions) for each coordinate

{x: partial_{x}, …}
sPds{}: Dictionary of scalar partial differential operators (operates on scalar functions) for each coordinate
{x: partial_{x}, …}
operator.
derivative.
Christoffel_symbols(mode=1)

mode = 1 Christoffel symbols of the first kind mode = 2 Christoffel symbols of the second kind

bases_dict(prefix=None)[source]

returns a dictionary mapping basis element names to their MultiVector instances, optionally for specific grades

if you are lazy, you might do this to populate your namespace with the variables of a given layout.

>>> locals().update(ga.bases())

basis_product_tables()[source]

For the different products of geometric algebra bases/blade initialize auto-updating of bases/blades product lists. For orthogonal bases all basis product lists are generated on the fly using functions and the base and blade representations are identical. For a non-orthogonal basis the multiplication table for the geometric product is pre-calcuated for base pairs. The tables for all other products (including the geometric product) are calulated on the fly and updated and are for blade pairs.

All tables are of the form

blade_derivation(blade, ib)[source]

Calculate derivatives of basis blade ‘blade’ using derivative of basis vectors calculated by metric. ‘ib’ is the index of the coordinate the derivation is with respect to or the coordinate symbol. These are requried for the calculation of the geometric derivatives in curvilinear coordinates or for more general manifolds.

‘blade_derivation’ saves the results in a dictionary, ‘self.dbases’, so that the derivation for a given blade and coordinate is never calculated more that once.

static build(*kargs, **kwargs)[source]

Static method to instantiate geometric algebra and return geometric algebra, basis vectors, and grad operator as a tuple.

build_bases()[source]

The bases for the multivector (geometric) algebra are formed from all combinations of the bases of the vector space and the scalars.

Each base is represented as a non-commutative symbol of the form -

e_{i_{1}}e_{i_{2}}…e_{i_{r}}

where 0 < i_{1} < i_{2} < … < i_{r} and 0 < r <= n the dimension of the vector space and 0 < i_{j} <= n. The total number of all symbols of this form plus the scalars is 2^{n}. Any multivector can be represented as a linear combination of these bases and the scalars.

If the basis vectors are not orthogonal a second set of symbols is required given by -

e_{i_{1}}^e_{i_{2}}^…^e_{i_{r}}.

These are called the blade basis for the geometric algebra and and multivector can also be represented by a linears combination of these blades and the scalars. The number of basis vectors that are in the symbol for the blade is call the grade of the blade.

Representing the multivector as a linear combination of blades gives a blade decomposition of the multivector.

There is a linear mapping from bases to blades and blades to bases so that one can easily convert from one representation to another. For the case of an orthogonal set of basis vectors the bases and blades are identical.

build_reciprocal_basis(gsym)[source]
Calculate reciprocal basis vectors e^{j} where
e^{j}cdot e_{k} = delta_{k}^{j}

and delta_{k}^{j} is the kronecker delta. We use the formula from Doran and Lasenby 4.94 -

e^{j} = (-1)**{j-1}e_{1}^…e_{j-1}^e_{j+1}^…^e_{n}*E_{n}**{-1}

where E_{n} = e_{1}^…^e_{n}.

For non-orthogonal basis e^{j} is not normalized and must be divided by E_{n}**2 (self.e_sq) in any relevant calculations.

If gsym = True then (E_{n})**2 is not evaluated, but is represented as (E_{n})**2 = (-1)**(n*(n-1)/2)*det(g) where det(g) the determinant of the metric tensor can be general scalar function of the coordinates.

connection(rbase, key_base, mode, left)[source]

Compute required multivector connections of the form (Einstein summation convention) e^{j}*(D_{j}e_{i_{1}…i_{r}}) and (D_{j}e_{i_{1}…i_{r}})*e^{j} where * could be *, ^, |, <, or > depending upon the mode and e^{j} are reciprocal basis vectors

dop(*kargs, **kwargs)[source]

Instanciate and return a multivector differential operator for this, ‘self’, geometric algebra.

dot(A, B)[source]

Let A = a + A’ and B = b + B’ where a and b are the scalar parts of A and B and A’ and B’ are the remaining parts of A and B. Then we have:

(a+A’)<(b+B’) = a(b+B’) + A’<B’ (a+A’)>(b+B’) = b(a+A’) + A’>B’

We use these relations to reduce A<B and A>B.

static dot_orthogonal(V1, V2, g=None)

Returns the dot product of two vectors in an orthogonal coordinate system. V1 and V2 are lists of sympy expressions. g is a list of constants that gives the signature of the vector space to allow for non-euclidian vector spaces.

This function is only used to form the dot product of vectors in the embedding space of a vector manifold or in the case where the basis vectors are explicitly defined by vector fields in the embedding space.

A g of None is for a Euclidian embedding space.

static dual_mode(mode='I+')[source]

Sets mode of multivector dual function for all geometric algebras in users program.

If Ga.dual_mode(mode) not called the default mode is ‘I+’.

mode return value +I I*self -I -I*self I+ self*I I- -self*I +Iinv Iinv*self -Iinv -Iinv*self Iinv+ self*Iinv Iinv- -self*Iinv

er_blade(er, blade, mode='*', left=True)[source]

Product (*,^,|,<,>) of reciprocal basis vector ‘er’ and basis blade ‘blade’ needed for application of derivatives to multivectors. left is ‘True’ means ‘er’ is multiplying ‘blade’ on the left, ‘False’ is for ‘er’ multiplying ‘blade’ on the right. Symbolically for left geometric product -

e^{j}*(e_{i_{1}}^…^e_{i_{r}})
grad_sqr(A, grad_sqr_mode, mode, left)[source]

Caclulate ‘(grad *_{1} grad) *_{2} A’ or ‘A *_{2} (grad *_{1} grad)’ where grad_sqr_mode = *_{1} = *, ^, or | and mode = *_{2} = *, ^, or |.

grade_decomposition(A)[source]

Returns dictionary with grades as keys of grades of A. For example if A is a rotor the dictionary keys would be 0 and 2. For a vector the single key would be 1. Note A can be input as a multivector or an multivector object (sympy expression). If A is a multivector the dictionary entries are multivectors. If A is a sympy expression (in this case a linear combination of non-commutative symbols) the dictionary entries are sympy expressions.

lt(*kargs, **kwargs)[source]

Instanciate and return a linear transformation for this, ‘self’, geometric algebra.

metric_symbols_list(s=None)

rows of metric tensor are separated by “,” and elements of each row separated by ” “. If the input is a single row it is assummed that the metric tensor is diagonal.

Output is a square matrix.

mv(root=None, *kargs, **kwargs)[source]

Instanciate and return a multivector for this, ‘self’, geometric algebra.

mvr(norm=True)[source]

Returns tumple of reciprocal basis vectors. If norm=True or basis vectors are orthogonal the reciprocal basis is normalized in the sense that

e_{i}cdot e^{j} = delta_{i}^{j}.

If the basis is not orthogonal and norm=False then e_{i}cdot e^{j} = I^{2}delta_{i}^{j}.

pDiff(A, coord)[source]

Compute partial derivative of multivector function ‘A’ with respect to coordinate ‘coord’.

reduce_basis(blst)[source]

Repetitively applies reduce_basis_loop to blst product representation until normal form is realized for non-orthogonal basis

static reduce_basis_loop(g, blst)[source]

blst is a list of integers [i_{1},…,i_{r}] representing the geometric product of r basis vectors a_{{i_1}}*…*a_{{i_r}}. reduce_basis_loop searches along the list [i_{1},…,i_{r}] untill it finds i_{j} == i_{j+1} and in this case contracts the list, or if i_{j} > i_{j+1} it revises the list (~i_{j} means remove i_{j} from the list)

Case 1: If i_{j} == i_{j+1}, return a_{i_{j}}**2 and
[i_{1},..,~i_{j},~i_{j+1},…,i_{r}]
Case 2: If i_{j} > i_{j+1}, return a_{i_{j}}.a_{i_{j+1}},
[i_{1},..,~i_{j},~i_{j+1},…,i_{r}], and [i_{1},..,i_{j+1},i_{j},…,i_{r}]
remove_scalar_part(A)[source]

Return non-commutative part (sympy object) of A.obj.

sm(*kargs, **kwargs)[source]

Instanciate and return a submanifold for this, ‘self’, geometric algebra. See ‘Sm’ class for instantiation inputs.

split_multivector(A)[source]

Split multivector A into commutative part a and non-commutative part A’ so that A = a+A’

class galgebra.ga.Sm(*kargs, **kwargs)[source]

Submanifold is a geometric algebra defined on a submanifold of a base geometric algebra defined on a manifold. The submanifold is defined by a mapping from the coordinates of the base manifold to the coordinates of the submanifold. The inputs required to define the submanifold are:

u {kargs} The coordinate map defining the submanifold

which is a list of functions of coordinates of the base manifold in terms of the coordinates of the submanifold. for example if the manifold is a unit sphere then - ‘u = [sin(u)*cos(v),sin(u)*sin(v),cos(u)]’.

Alternatively {kargs} is a parametric vector function of the basis vectors of the base manifold. The coefficients of the bases are functions of the coordinates {kargs}. In this case we would call the submanifold a “vector” manifold and additional characteristics of the manifold can be calculated since we have given an explicit embedding of the manifold in the base manifold.

coords {kargs} The coordinate list for the submanifold, for
example ‘[u,v]’.

See ‘init_slots’ for possible other inputs. The ‘Ga’ member function ‘sm’ can be used to instantiate the submanifold via (o3d is the base manifold)

coords = (u,v) = symbols(‘,v’,real=True) sm_example = o3d.sm([sin(u)*cos(v),sin(u)*sin(v),cos(u)],coords)

Christoffel_symbols(mode=1)

mode = 1 Christoffel symbols of the first kind mode = 2 Christoffel symbols of the second kind

bases_dict(prefix=None)

returns a dictionary mapping basis element names to their MultiVector instances, optionally for specific grades

if you are lazy, you might do this to populate your namespace with the variables of a given layout.

>>> locals().update(ga.bases())

basis_product_tables()

For the different products of geometric algebra bases/blade initialize auto-updating of bases/blades product lists. For orthogonal bases all basis product lists are generated on the fly using functions and the base and blade representations are identical. For a non-orthogonal basis the multiplication table for the geometric product is pre-calcuated for base pairs. The tables for all other products (including the geometric product) are calulated on the fly and updated and are for blade pairs.

All tables are of the form

blade_derivation(blade, ib)

Calculate derivatives of basis blade ‘blade’ using derivative of basis vectors calculated by metric. ‘ib’ is the index of the coordinate the derivation is with respect to or the coordinate symbol. These are requried for the calculation of the geometric derivatives in curvilinear coordinates or for more general manifolds.

‘blade_derivation’ saves the results in a dictionary, ‘self.dbases’, so that the derivation for a given blade and coordinate is never calculated more that once.

static build(*kargs, **kwargs)

Static method to instantiate geometric algebra and return geometric algebra, basis vectors, and grad operator as a tuple.

build_bases()

The bases for the multivector (geometric) algebra are formed from all combinations of the bases of the vector space and the scalars.

Each base is represented as a non-commutative symbol of the form -

e_{i_{1}}e_{i_{2}}…e_{i_{r}}

where 0 < i_{1} < i_{2} < … < i_{r} and 0 < r <= n the dimension of the vector space and 0 < i_{j} <= n. The total number of all symbols of this form plus the scalars is 2^{n}. Any multivector can be represented as a linear combination of these bases and the scalars.

If the basis vectors are not orthogonal a second set of symbols is required given by -

e_{i_{1}}^e_{i_{2}}^…^e_{i_{r}}.

These are called the blade basis for the geometric algebra and and multivector can also be represented by a linears combination of these blades and the scalars. The number of basis vectors that are in the symbol for the blade is call the grade of the blade.

Representing the multivector as a linear combination of blades gives a blade decomposition of the multivector.

There is a linear mapping from bases to blades and blades to bases so that one can easily convert from one representation to another. For the case of an orthogonal set of basis vectors the bases and blades are identical.

build_reciprocal_basis(gsym)
Calculate reciprocal basis vectors e^{j} where
e^{j}cdot e_{k} = delta_{k}^{j}

and delta_{k}^{j} is the kronecker delta. We use the formula from Doran and Lasenby 4.94 -

e^{j} = (-1)**{j-1}e_{1}^…e_{j-1}^e_{j+1}^…^e_{n}*E_{n}**{-1}

where E_{n} = e_{1}^…^e_{n}.

For non-orthogonal basis e^{j} is not normalized and must be divided by E_{n}**2 (self.e_sq) in any relevant calculations.

If gsym = True then (E_{n})**2 is not evaluated, but is represented as (E_{n})**2 = (-1)**(n*(n-1)/2)*det(g) where det(g) the determinant of the metric tensor can be general scalar function of the coordinates.

connection(rbase, key_base, mode, left)

Compute required multivector connections of the form (Einstein summation convention) e^{j}*(D_{j}e_{i_{1}…i_{r}}) and (D_{j}e_{i_{1}…i_{r}})*e^{j} where * could be *, ^, |, <, or > depending upon the mode and e^{j} are reciprocal basis vectors

dop(*kargs, **kwargs)

Instanciate and return a multivector differential operator for this, ‘self’, geometric algebra.

dot(A, B)

Let A = a + A’ and B = b + B’ where a and b are the scalar parts of A and B and A’ and B’ are the remaining parts of A and B. Then we have:

(a+A’)<(b+B’) = a(b+B’) + A’<B’ (a+A’)>(b+B’) = b(a+A’) + A’>B’

We use these relations to reduce A<B and A>B.

static dot_orthogonal(V1, V2, g=None)

Returns the dot product of two vectors in an orthogonal coordinate system. V1 and V2 are lists of sympy expressions. g is a list of constants that gives the signature of the vector space to allow for non-euclidian vector spaces.

This function is only used to form the dot product of vectors in the embedding space of a vector manifold or in the case where the basis vectors are explicitly defined by vector fields in the embedding space.

A g of None is for a Euclidian embedding space.

static dual_mode(mode='I+')

Sets mode of multivector dual function for all geometric algebras in users program.

If Ga.dual_mode(mode) not called the default mode is ‘I+’.

mode return value +I I*self -I -I*self I+ self*I I- -self*I +Iinv Iinv*self -Iinv -Iinv*self Iinv+ self*Iinv Iinv- -self*Iinv

er_blade(er, blade, mode='*', left=True)

Product (*,^,|,<,>) of reciprocal basis vector ‘er’ and basis blade ‘blade’ needed for application of derivatives to multivectors. left is ‘True’ means ‘er’ is multiplying ‘blade’ on the left, ‘False’ is for ‘er’ multiplying ‘blade’ on the right. Symbolically for left geometric product -

e^{j}*(e_{i_{1}}^…^e_{i_{r}})
grad_sqr(A, grad_sqr_mode, mode, left)

Caclulate ‘(grad *_{1} grad) *_{2} A’ or ‘A *_{2} (grad *_{1} grad)’ where grad_sqr_mode = *_{1} = *, ^, or | and mode = *_{2} = *, ^, or |.

grade_decomposition(A)

Returns dictionary with grades as keys of grades of A. For example if A is a rotor the dictionary keys would be 0 and 2. For a vector the single key would be 1. Note A can be input as a multivector or an multivector object (sympy expression). If A is a multivector the dictionary entries are multivectors. If A is a sympy expression (in this case a linear combination of non-commutative symbols) the dictionary entries are sympy expressions.

lt(*kargs, **kwargs)

Instanciate and return a linear transformation for this, ‘self’, geometric algebra.

metric_symbols_list(s=None)

rows of metric tensor are separated by “,” and elements of each row separated by ” “. If the input is a single row it is assummed that the metric tensor is diagonal.

Output is a square matrix.

mv(root=None, *kargs, **kwargs)

Instanciate and return a multivector for this, ‘self’, geometric algebra.

mvr(norm=True)

Returns tumple of reciprocal basis vectors. If norm=True or basis vectors are orthogonal the reciprocal basis is normalized in the sense that

e_{i}cdot e^{j} = delta_{i}^{j}.

If the basis is not orthogonal and norm=False then e_{i}cdot e^{j} = I^{2}delta_{i}^{j}.

pDiff(A, coord)

Compute partial derivative of multivector function ‘A’ with respect to coordinate ‘coord’.

reduce_basis(blst)

Repetitively applies reduce_basis_loop to blst product representation until normal form is realized for non-orthogonal basis

static reduce_basis_loop(g, blst)

blst is a list of integers [i_{1},…,i_{r}] representing the geometric product of r basis vectors a_{{i_1}}*…*a_{{i_r}}. reduce_basis_loop searches along the list [i_{1},…,i_{r}] untill it finds i_{j} == i_{j+1} and in this case contracts the list, or if i_{j} > i_{j+1} it revises the list (~i_{j} means remove i_{j} from the list)

Case 1: If i_{j} == i_{j+1}, return a_{i_{j}}**2 and
[i_{1},..,~i_{j},~i_{j+1},…,i_{r}]
Case 2: If i_{j} > i_{j+1}, return a_{i_{j}}.a_{i_{j+1}},
[i_{1},..,~i_{j},~i_{j+1},…,i_{r}], and [i_{1},..,i_{j+1},i_{j},…,i_{r}]
remove_scalar_part(A)

Return non-commutative part (sympy object) of A.obj.

sm(*kargs, **kwargs)

Instanciate and return a submanifold for this, ‘self’, geometric algebra. See ‘Sm’ class for instantiation inputs.

split_multivector(A)

Split multivector A into commutative part a and non-commutative part A’ so that A = a+A’

class galgebra.ga.auto_update_dict(f_update, instance=None)[source]

auto_update_dict creats entries to a dictionary on the fly. When the dictionary is called and the key used is not one of the existing keys The function self.f_update(key) is called to evaluate the key. The result is then added to the dictionary so that self.f_update is not used to evaluate the same key again.

The __init__ is used to input self.f_update for a given dictionary.

clear() → None. Remove all items from D.
copy() → a shallow copy of D
fromkeys()

Create a new dictionary with keys from iterable and values set to value.

get()

Return the value for key if key is in the dictionary, else default.

items() → a set-like object providing a view on D's items
keys() → a set-like object providing a view on D's keys
pop(k[, d]) → v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised

popitem() → (k, v), remove and return some (key, value) pair as a

2-tuple; but raise KeyError if D is empty.

setdefault()

Insert key with a value of default if key is not in the dictionary.

Return the value for key if key is in the dictionary, else default.

update([E, ]**F) → None. Update D from dict/iterable E and F.

If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

values() → an object providing a view on D's values
galgebra.ga.nc_subs(expr, base_keys, base_values=None)[source]

See if expr contains nc keys in base_keys and substitute corresponding value in base_values for nc key. This was written since standard sympy subs was very slow in performing this operation for non-commutative keys for long lists of keys.

galgebra.ga.update_and_substitute(expr1, expr2, func, mul_dict)[source]
Linear expand expr1 and expr2 to get (summation convention)
expr1 = coefs1[i]*bases1[i] expr2 = coefs2[j]*bases2[j]

where coefs1 and coefs2 are lists of are commutative expressions and bases1 and bases2 are lists of bases for the geometric algebra. Then evaluate

expr = coefs1[i]*coefs2[j]*F(bases1[i],bases2[j])

where F(bases1[i],bases2[j]) is a function that returns the appropriate product of bases1[i]*bases2[j] as a linear combination of scalars and bases of the geometric algebra.