AVF Doc

Exterior calculus with algebra valued forms

Hugo D. Wahlquist © 2003-2012

Now mantained by Frank B. Estabrook and José M. Martín-García after Hugo passed away in 2008.

AVF is a Mathematica package for
	- exterior calculus with indexed (or algebra-valued) sets of basis forms,
	- Cartan moving frame theory in n-dimensional Riemannian geometry with arbitrary signature,
	- the exterior differential systems of Cartan-Kähler theory and calculation of Cartan characters, and
	- embedding of Riemannian manifolds.
There are specific programs for generation and use of Clifford algebra valued forms with moving frames, and generalizations.  This package is a small modification of a suite of programs written by Hugo D. Wahlquist in 2003.

Frank Estabrook, long-time collaborator of Hugo Wahlquist and first user of AVF, has kindly authorized these programs to be included in the xAct suite of tensor computer algebra packages for Mathematica. The original programs, as Hugo wrote them for him, can be downloaded from

	http://www.emis.de/journals/SIGMA/2008/063/

The original programs were not structured as a single Mathematica package. There were actually two main codes, AVF (Algebra Valued Forms) and CAV (Clifford Algebra Valued forms), plus additional smaller utility programs. They have been merged and documented as a single Mathematica package, called AVF, and adapted to the xAct hierarchy.

The AVF package is independent of the rest of the xAct packages except for xCore, needed to access directory information. AVF is included in the xAct framework because it covers a complementary area. It does not yet talk to the other mathematical packages as it uses a different, mostly index-free, approach.

This is the doc file AVFDoc.nb of version 1.0 of the AVF package. Last update on 17 December 2011.

This AVFDoc.nb file has been built by joining and editing nine different documentation files that Hugo wrote. At the beginning of each section we indicate the respective file used. It is divided in four parts:
	- Introduction: a general discussion of the capabilities of AVF, with no executable code.
	- Basic computations
	- Examples: not so basic computations
	- Advanced computations

Two relevant references:

F. B. Estabrook and H. D. Wahlquist, “Classical Geometries Defined by Exterior Differential Systems on Higher Frame Bundles”, Classical and Quantum Gravity, 6, 263-74 (1989) (for Clifford-algebra-valued forms, Cartan-Kähler theory and Cartan characters)

H.D. Wahlquist “Monte Carlo calculation of Cartan characters”, in Proc. International Conference on Aspects of General Relativity  and Mathematical Physics, ed. N. Breton, R. Capovilla and T. Matos, Mexico City, CINVESTAV, 1993.

I. Introduction

This is taken from the file AVF_Introduction.nb.

I.a. General comments

This section contains a general description of the structure and capabilities of AVF. It covers the basic information and operations needed to understand the package, but will not serve as a detailed manual. All the operations described here, and many additional ones, are introduced, explained and used in the demonstration sections below.
  
Section I.g contains a summary of the complete set of variable and function names together with a brief description for each entry.

I.b. Basic structures

An  algebra-valued-form (AVF) is a multinomial, each term of which is a product of three types of factors:

	( scalar coefficient ) ( exterior product of basis forms ) ( a single algebra element )

For example,

sampleterm=(2(z^3) Sin[x])((Subscript[θ, 1])⋀(Subscript[θ, 4])⋀(Subscript[θ, 2]))((Subscript[e, 3]))         (parentheses optional)                  [1]

Any of these factors may be omitted in any term of an AVF expression.

I.b.1. Fundamental lists

The algebraic categories of the variables involved are established by their membership in one of three fundamental lists of arbitrarily chosen symbols with the reserved names: scalars, forms and elements.

After calling up the AVF package with  <<xAct`AVF` and before starting a calculation, these lists may be defined (and can be changed at any later time) by the commands :

makescalars[{list of scalar symbols}]

makeforms[{list of 1-form symbols}]                                                          [2]

makeelements[{list of algebra-element symbols}]

For instance, the following start-up commands (which can be executed in any order) would establish the properties of the symbols in the sampleterm used in [1] :

makeforms[{(Subscript[θ, 1]),(Subscript[θ, 2]),(Subscript[θ, 3]),(Subscript[θ, 4])}]
{(Subscript[θ, 1]),(Subscript[θ, 2]),(Subscript[θ, 3]),(Subscript[θ, 4])}

makescalars[{x,y,z}]                                                                                        [3]
{x,y,z}

makeelements[{(Subscript[e, 0]),(Subscript[e, 1]),(Subscript[e, 2]),(Subscript[e, 3])}]
{(Subscript[e, 0]),(Subscript[e, 1]),(Subscript[e, 2]),(Subscript[e, 3])}

Since their names are protected, the lists cannot be defined by simple assignments; such as for example, scalars={x, y, z}, although their values may always be viewed by typing their names.
  		
If the make commands are not executed, the lists will have the default values: scalars={}, forms={}, and elements={identity}.

The make commands are needed to perform  several essential chores in addition to defining the values of the respective lists. For instance, the make commands for scalars (0-forms) and  forms (1-forms) automatically  generate lists of symbols for their exterior derivatives with reserved names, dscalars, dforms; e.g.,

dscalars
{dx,dy,dz}
                                                                                                                                         [4]
dforms
{(Subscript[dθ, 1]),(Subscript[dθ, 2]),(Subscript[dθ, 3]),(Subscript[dθ, 4])}

Furthermore, the dscalars list is automatically joined to the forms list,

forms                                                                                                                              [5]
{(Subscript[θ, 1]),(Subscript[θ, 2]),(Subscript[θ, 3]),(Subscript[θ, 4]),dx,dy,dz}

and all members of forms are treated as independent 1-forms generating the Grassmann algebra based on them.

The algebra elements are assumed to be constant.
  		
A make command creates a new list each time it is used; it does not extend the existing list. So, for example, makescalars[{}]  deletes all scalars, and makeforms[{}] deletes all 1-forms, except for the members of dscalars (if any), which can be removed only by deleting the scalars.
  		 
Extending a list can be accomplished by; e.g., :

makescalars[Join[scalars,{list of additional scalars}]]               [6]

Many other lists (described below) are also generated automatically by these commands, or else created by their own make commands.

I.b.2. Symbols

There is nothing special about the particular symbols used for the members of scalars, forms, and elements  in the examples displayed here. The symbols in these lists may be any variable names acceptable to Mathematica, and may include multiple subscripts, overscripts, underscripts, etc., but not superscripts, which are always interpreted as exponents.

These symbols are the "atoms" out of which expressions will be built. They themselves must be elementary objects --simple names--, neither expressions nor functions, and must never have assigned values. For example, neither -x  nor f[x] is an acceptable candidate for membership in scalars, and (y dz - z dy) is not a valid member of forms.

Any relations between the independent members of scalars or forms such as y->y[x] or (Subscript[θ, 1])->(y dz - z dy)can (and must) be handled by using replacement rules, not by assignments. Of course, nothing forbits defining a 1-form (Subscript[σ, 1])=y dz-z dy by assignment; it simply becomes an AVF. But (Subscript[σ, 1]) is not then an independent generator, or “basis-form”, and so is not eligible for membership in the forms list.

The make functions perform a screening test of their argument lists. The test will  cause an Interrupt if it finds a problem and indicate where it is, but it will not detect all possible errors. Most often, errors occur because a name has had a prior assignment. The Interrupt can be handled by selecting Abort in the window, modifying the input argument (e.g., clearing any assigned values), and re-executing the make command. Sometimes the easiest fix may be to Quit and re-start the Kernel.

The different lists must have no members in common except for the automatic inclusion of dscalars in forms. Any simple variable in an AVF expression which is not a member of any of these lists will be treated as a constant scalar parameter.

I.b.3. Algebras

The algebras of scalars and differential forms are fixed, but the algebra of elements must be specified in a multiplication table defining the desired algebra. This is accomplished by inputting a matrix with the appropriate products. For example, for an algebra with four generators (say, elements={(Subscript[e, 0]),(Subscript[e, 1]),(Subscript[e, 2]),(Subscript[e, 3])}), the matrix (here called producttable), would have the following structure:

producttable={{(Subscript[e, 0])(Subscript[e, 0]),(Subscript[e, 0])(Subscript[e, 1]),(Subscript[e, 0])(Subscript[e, 2]),(Subscript[e, 0])(Subscript[e, 3])},
		                {(Subscript[e, 1])(Subscript[e, 0]),(Subscript[e, 1])(Subscript[e, 1]),(Subscript[e, 1])(Subscript[e, 2]),(Subscript[e, 1])(Subscript[e, 3])},                                                [7]
		                {(Subscript[e, 2])(Subscript[e, 0]),(Subscript[e, 2])(Subscript[e, 1]),(Subscript[e, 2])(Subscript[e, 2]),(Subscript[e, 2])(Subscript[e, 3])},
		                {(Subscript[e, 3])(Subscript[e, 0]),(Subscript[e, 3])(Subscript[e, 1]),(Subscript[e, 3])(Subscript[e, 2]),(Subscript[e, 3])(Subscript[e, 3])}}

where the indicated products are to be replaced by their linear values for a specific algebra. Note that the first member of elements is always taken as the identity element of the algebra regardless of the symbol used for it. So in the above example, (Subscript[e, 0])(Subscript[e, i]) = (Subscript[e, i])(Subscript[e, 0]) = (Subscript[e, i]) , and the top row and left column of the matrix will equal elements.

The algebra is then established by the command

makealgebra[producttable]                                                                                  [8]

which sets the reserved variable algebra to producttable. The variable algebra constitutes the actual look-up table for products of elements during calculations. It can be displayed in MatrixForm by typing the the command : mtx[]. The algebra can be changed at any time by executing [8] with a different argument.

The AVF package requires an "identity" element, acting as a unital operator to serve as a  placeholder in many calculations. If the algebra defined by producttable does not include an identity element, one must be supplied by executing the command makealgebra[] with two arguments, makealgebra[producttable, symbol], where the second (optional) argument, symbol, will be used as a new first member of elements, to function as the essential placeholder. This will have no effect on the products defined by producttable, nor on calculations with AVFs not involving the spurious identity.

Note that the initial values: elements={identity}, algebra={{identity}} are set when the package AVF.m is  called. These values are appropriate for doing ordinary differential form analysis, and so for this purpose it is not necessary to input any algebra table.

The particular case of Clifford algebras is implemented through special routines collectively referred to as “the CAV program”, described below. Using CAV, setting up a Clifford algebra can be easily accomplished by defining a list containing the signature of the metric in an orthonormal basis. Many problems in metric spaces, for example, can be conveniently treated with the CAV orthonormal frame form (OverHat[θ]) and associated CAV connection form (OverHat[ω]), which are constructed by the CAV program.

I.c. AVF expressions

An AVF expression is just a sum of terms similar to the sample term in [1]; e.g.,

avf=2 (x^2) y (Subscript[e, 2])+λ z (Subscript[θ, 2])⋀dx (Subscript[e, 0])- (y^(-3))(Subscript[θ, 1])⋀(Subscript[θ, 4])⋀(Subscript[θ, 2]) (Subscript[e, 1])+(Subscript[θ, 3])⋀(Subscript[dθ, 2])                                          
                                                                                                                                                   [9]
2 (x^2) y (Subscript[e, 2])+z λ (Subscript[e, 0]) (Subscript[θ, 2])⋀dx+(Subscript[θ, 3])⋀(Subscript[dθ, 2])-(((Subscript[e, 1]) (Subscript[θ, 1])⋀(Subscript[θ, 4])⋀(Subscript[θ, 2]))/(y^3))

Any symbol in a wedge product must be a member of forms (which automatically includes dscalars), or of dforms (which is also automatically constructed). Improper inputs would include e.g., (Subscript[θ, 1])⋀(-(Subscript[θ, 4])) , (z (Subscript[θ, 2]))⋀ dx , (Subscript[θ, 3])⋀ d (Subscript[θ, 2]) , y (Subscript[e, 2])(Subscript[e, 3]). Note that AVF expressions can be of inhomogeneous degree as differential forms.

Since the symbol λ is not a member of any list, it would be treated as a constant scalar. The missing algebra-element of the last input term defaults to the identity element of the algebra (the first member of elements). Thus, the algebra-element could also have been omitted in the second term. If the algebra-element were omitted from all terms, avf would become an ordinary differential form expression.

I.c.1. Input

The expression avf could be typed in from the keyboard just as it appears in [9]. For longer expressions, or more complicated symbols, this can become sufficiently tedious that defining a symbol palette my be useful, although the BasicInput palette is usually sufficient. In the case of expressions with uniform structure, Mathematica’s Sum function can be used, either with indexed symbols or with part specifications in the lists of variables; e.g.,

avf1=Sum[(Subscript[θ, i])(Subscript[e, i]),{i,3}]
(Subscript[e, 1]) (Subscript[θ, 1])+(Subscript[e, 2]) (Subscript[θ, 2])+(Subscript[e, 3]) (Subscript[θ, 3])
                                                                                                                                                   [10]
avf1=Sum[forms[[i]] elements[[i+1]],{i,3}]
(Subscript[e, 1]) (Subscript[θ, 1])+(Subscript[e, 2]) (Subscript[θ, 2])+(Subscript[e, 3]) (Subscript[θ, 3])

Whenever an AVF expression is used as an argument in an AVF function (such a multiplication), it is converted to an equivalent List expression adapted to the simplified structure of AVFs. The purpose is to allow writing efficient AVF procedures and to accomplish certain operations that are quite difficult to implement with the standard commands provided by Mathematica.

These conversions happen “behind the scenes” and are generally invisible. The function in[avf] creates the equivalent List expression for the argument avf whenever it is required in a calculation. The List expression can be displayed by executing that command with any AVF argument. Caution: only a properly input avf will be converted correctly.

I.c.2. Output

Upon completion of an AVF procedure, the final List expression is converted back to standard algebraic format by the function out[final], essentially the inverse of in, except that all monomial wedge products are re-arranged into canonical Mathematica order and the identity element of the algebra is suppressed. Any of the usual Mathematica commands can then be used on the output expression.

I.d. Algebraic operations

There are three special algebraic functions on AVFs implemented in the program; multiplication, factoring out a basis form, and contraction with vectors.

I.d.1. Multiplication

The function, mult[avf1, avf2], gives the expanded product of two AVFs. For each term in the result, it simultaneously performs the usual product of the scalar coefficients, the exterior product of the basis forms, and the algebraic product of the elements as determined by the algebra table.
  		
The same product results from using the NonCommutativeMultiply infix operator, ** . In this form, any number of AVFs can be multiplied together at once; e.g.,

avf1**avf2**avf3**(etc.)                                                                       [11]

If the algebra table defines a non-associative algebra, it may be necessary to use the appropriate parentheses to define the order of multiplications. Without parentheses, multiplication proceeds from right to left, as for composite functions.

The infix wedge symbol ⋀ appearing  between basis forms in input and output expressions has the usual significance of exterior product. It is important to note, however, that it is neither recognized nor used by the program as an operator. It is used purely symbolically to denote products of basis forms, and also serves to prevent Mathematica from incorrectly permuting the order of such products.

Any wedge symbol in a properly input AVF can be replaced by the ** operator. This has little effect when the wedge is between basis forms, but in the case of non-basis-form factors (which must themselves be properly input AVFs in  parentheses), it will cause the product to be expanded out.

The AVF function, expand[avf], is included for just this purpose. It substitutes ** for all wedge symbols in the argument avf, and returns the expanded result. Its primary use is to facilitate replacements within wedge products.

I.d.2. Factoring

The function factor[basisform, avf] returns the factor of basisform in avf, where basisform is any member of forms or dforms, and avf is an AVF expression. The factor function does not require basisform to factor all of avf; it treats the terms separately and returns the factor of basisform in whatever subset of terms  contains it. For the sample avf given in [9], for instance,

factor[(Subscript[θ, 2]),avf]                                                                                          [12]

returns

dx z λ-(((Subscript[e, 1]) (Subscript[θ, 1])⋀(Subscript[θ, 4]))/(y^3))                                                                                         [13]

where in standard AVF output the element (Subscript[e, 0]) has been suppressed. (The basisform is always factored to the left of avf). While this function may not be used very often, it is provided because it is not easily accomplished using standard Mathematica operations on wedge products.

I.d.3. Vector contraction

In AVF a vector is a list of components, each component representing its contraction on the corresponding member of forms (which includes dscalars). In effect, the vector is expressed in the dual basis to forms. For convenience, the procedure makevectors[] (no arguments) will generate four such vectors, {vec1, vec2, vec3, vec4}. Each of these is a list of the same length as forms, having indexed components, {(Subscript[v1, i]),(Subscript[v2, i]),(Subscript[v3, i]),(Subscript[v4, i])}, to represent its contraction on the  ith  member of forms. If needed  more vectors are easily constructed.

Neither the names of the vectors nor the component symbols are reserved, so they can be given any variable names at will. A vector component should be defined for each member of forms, however, unless care is taken to avoid potential errors. Whenever makeforms is executed, it calls the makevectors routine automatically to create four new vectors agreeing in length and order with the new forms list.

Additional structures are necessary to implement the contraction of vectors on the 2-forms included in dforms. This is accomplished by defining a list of replacements named drules to express dforms in terms of forms. The reserved variable drules can be established in the standard way by makedrules[replacement_list]. For instance, a typical set of drules might be:

makedrules[{(Subscript[dθ, 1])->(Subscript[θ, 2])⋀(Subscript[θ, 3]),(Subscript[dθ, 2])->(Subscript[θ, 3])⋀(Subscript[θ, 1]),(Subscript[dθ, 3])->(Subscript[θ, 1])⋀(Subscript[θ, 2])}]
                                                                                                                                           [14]
{(Subscript[dθ, 1])->(Subscript[θ, 2])⋀(Subscript[θ, 3]),(Subscript[dθ, 2])->(Subscript[θ, 3])⋀(Subscript[θ, 1]),(Subscript[dθ, 3])->(Subscript[θ, 1])⋀(Subscript[θ, 2])}

The initial default value for drules is natural, {(Subscript[dθ, 1])->0, etc}, i.e. specifying that all members of forms are closed. The drules are invoked automatically for contractions where they are essential, but only then. The drules are an extremely important and useful feature of AVF for many other purposes in addition to contraction. How the drules are applied is illustrated in detail further down.

Note that the vector components, ((Subscript[v1, i]),(Subscript[v2, i]),(Subscript[v3, i]),(Subscript[v4, i])), are not automatically introduced into the scalars list, and so will not be differentiated. They can be added in by e.g.,

makescalars[Join[scalars,vec1]]                                                                  [15]

so that the (Subscript[v1, i]) become independent scalars with their own exterior derivatives (Subscript[dv1, i]). Alternatively, the components could be given assigned values either as explicit, or unspecified, functions of the existing scalars. This should not be done, if they have been introduced as independent scalars by the makescalars command.

The function contract[vector,expression] returns the contraction of vector on expression, where expression can be either a single AVF or a list of AVFs. This operation also has an infix form using the “small-circle" symbol, which is input by typing the sequence esc-sc-esc. And in this form multiple contractions can be performed; e.g.,

vec1∘vec2∘vec3∘avf1                                                                                             [16]

or for a list of AVFs,

vec4∘vec1∘{avf1,avf2,avf3}                                                                           [17]

I.e. Exterior differentiation and Lie derivation

The operator d[expr] returns the exterior derivative of expr which may be either a single AVF, or a list of AVFs. The symbols used for the derivatives of all the fundamental variables are in dscalars and dforms. Their make commands also establish two additional replacement lists, sderiv and fderiv, to accomplish the derivations.

A very simple example, for an ordinary 1-form f is shown here:

f=x (Subscript[θ, 1])+y (Subscript[θ, 2])+z (Subscript[θ, 3])
x (Subscript[θ, 1])+y (Subscript[θ, 2])+z (Subscript[θ, 3])
                                                                                                                              [18]
d[f]
x (Subscript[dθ, 1])+y (Subscript[dθ, 2])+z (Subscript[dθ, 3])+dx⋀(Subscript[θ, 1])+dy⋀(Subscript[θ, 2])+ dz⋀(Subscript[θ, 3])

The Lie derivative of AVFs is defined by the expansion:

lie[vec,avf]:=vec∘d[avf]+d[vec∘avf]                                        [19]

and since both d[] and ∘ work with AVF lists, the avf argument here can be a list of AVFs. As explained in section I.d.3 on contractions, to execute this function on general objects, a set of drules must be defined, and in order to be differentiated, the vector components must either be members of scalars themselves, or expressed in terms of scalars.

I.f. Clifford algebras

We now describe how to set up Clifford-Algebra-Valued forms within AVF. This is done by executing the command makeclifford[{signature_list}]. The argument specifies the signatures of the diagonal metric, (Subscript[g, ij]), for a Clifford algebra defined with respect to an orthonormal basis, (Subscript[γ, i]); i.e.,

(Subscript[γ, i])(Subscript[γ, j])+(Subscript[γ, j])(Subscript[γ, i])=2 (Subscript[g, ij])(Subscript[γ, 0])        ( (Subscript[g, ij])=0 {i≠j},(Subscript[g, ii])=±1)      (1≤{i,j}≤cadim)         [20]

where (Subscript[γ, 0]) is the identity element and cadim is the number of generators. For example, a 4-dim Clifford algebra with Lorentzian metric would be obtained by:

makeclifford[{1,1,1,-1}]                                                              [21]

Another option would be:

makeclifford[{-1,-1,-1,1}]                                                         [22]

but the two options actually give different Clifford algebras. The input

makeclifford[{-1,-1}]                                                                       [23]

gives a Clifford algebra which is isomorphic to the algebra of quaternions.

I.f.1. Fundamental lists

The makeclifford[] command defines all the fundamental AVF lists for the chosen Clifford algebra, with the exception of scalars which remains the null list {}.

The program first checks the variable clifflist to see if this algebra has been encountered previously; if so, it will input the appropriate data file from the “CliffordAlgebras” folder. If not, it will proceed to construct the necessary quantities, save them in a file in that folder, and add the respective filename to clifflist, so it won't be necessary to repeat the calculation. Since the algebra matrix contains 2^(2 cadim) entries, it is expensive in both time and memory to calculate for cadim > 6 although the program is capable of cadim <= 11.

If the command in [21] or [22] above were executed, the elements list for either one would appear as :

{(Subscript[γ, 0]),(Subscript[γ, 1]),(Subscript[γ, 2]),(Subscript[γ, 3]),(Subscript[γ, 4]),(Subscript[γ, 12]),(Subscript[γ, 13]),(Subscript[γ, 14]),(Subscript[γ, 23]),(Subscript[γ, 24]),(Subscript[γ, 34]),(Subscript[γ, 15]),(Subscript[γ, 25]),(Subscript[γ, 35]),(Subscript[γ, 45]),(Subscript[γ, 5])}            [24]

although the algebra tables would differ. Multiple indices indicate the corresponding products; e.g. (Subscript[γ, 23])=(Subscript[γ, 2])(Subscript[γ, 3]). The element (Subscript[γ, 1 + cadim]) is always used to represent the complete product element; in this case (Subscript[γ, 5])=(Subscript[γ, 1])(Subscript[γ, 2])(Subscript[γ, 3])(Subscript[γ, 4]). And in order to minimize the amount of indices, a “dual” representation for higher products is employed; i.e., (Subscript[γ, 15])=(Subscript[γ, 1])(Subscript[γ, 5])=sig[1](Subscript[γ, 234]), etc.

I.f.2. Variables and algebra-valued-forms

Two lists of graded symbols are generated by makeclifford[]: omegas and thetas. Both are established as basis 1-forms by makeforms; e.g., (in the cadim==4 case)

forms={(Overscript[θ, 0]),(Subscript[(Overscript[θ, 1]), 1]),(Subscript[(Overscript[θ, 1]), 2]),(Subscript[(Overscript[θ, 1]), 3]),(Subscript[(Overscript[θ, 1]), 4]),(Subscript[(Overscript[θ, 2]), 12]),(Subscript[(Overscript[θ, 2]), 13]),(Subscript[(Overscript[θ, 2]), 14]),(Subscript[(Overscript[θ, 2]), 23]),(Subscript[(Overscript[θ, 2]), 24]),(Subscript[(Overscript[θ, 2]), 34]),(Subscript[(Overscript[θ, 3]), 1]),(Subscript[(Overscript[θ, 3]), 2]),(Subscript[(Overscript[θ, 3]), 3]),(Subscript[(Overscript[θ, 3]), 4]),(Overscript[θ, 4]),
	           (Overscript[ω, 0]),(Subscript[(Overscript[ω, 1]), 1]),(Subscript[(Overscript[ω, 1]), 2]),(Subscript[(Overscript[ω, 1]), 3]),(Subscript[(Overscript[ω, 1]), 4]),(Subscript[(Overscript[ω, 2]), 12]),(Subscript[(Overscript[ω, 2]), 13]),(Subscript[(Overscript[ω, 2]), 14]),(Subscript[(Overscript[ω, 2]), 23]),(Subscript[(Overscript[ω, 2]), 24]),(Subscript[(Overscript[ω, 2]), 34]),(Subscript[(Overscript[ω, 3]), 1]),(Subscript[(Overscript[ω, 3]), 2]),(Subscript[(Overscript[ω, 3]), 3]),(Subscript[(Overscript[ω, 3]), 4]),(Overscript[ω, 4])  }      [25]

where the grades of the basis 1-forms are indicated by overscripts. These are used to create two graded CAV 1-forms, (OverHat[θ]) and (OverHat[ω]).

(OverHat[θ]) =  (Overscript[θ, 0]) (Subscript[γ, 0])+
	       (Subscript[γ, 1]) (Subscript[(Overscript[θ, 1]), 1])+(Subscript[γ, 2]) (Subscript[(Overscript[θ, 1]), 2])+(Subscript[γ, 3]) (Subscript[(Overscript[θ, 1]), 3])+(Subscript[γ, 4]) (Subscript[(Overscript[θ, 1]), 4])+
	       (Subscript[γ, 12]) (Subscript[(Overscript[θ, 2]), 12])+(Subscript[γ, 13]) (Subscript[(Overscript[θ, 2]), 13])+(Subscript[γ, 14]) (Subscript[(Overscript[θ, 2]), 14])+(Subscript[γ, 23]) (Subscript[(Overscript[θ, 2]), 23])+(Subscript[γ, 24]) (Subscript[(Overscript[θ, 2]), 24])+(Subscript[γ, 34]) (Subscript[(Overscript[θ, 2]), 34])+                                         [26]
	       (Subscript[γ, 15]) (Subscript[(Overscript[θ, 3]), 1])+(Subscript[γ, 25]) (Subscript[(Overscript[θ, 3]), 2])+(Subscript[γ, 35]) (Subscript[(Overscript[θ, 3]), 3])+(Subscript[γ, 45]) (Subscript[(Overscript[θ, 3]), 4])+
	       (Overscript[θ, 4]) (Subscript[γ, 5])

(OverHat[ω]) =  (Overscript[ω, 0]) (Subscript[γ, 0])+
	      (Subscript[γ, 1]) (Subscript[(Overscript[ω, 1]), 1])+(Subscript[γ, 2]) (Subscript[(Overscript[ω, 1]), 2])+(Subscript[γ, 3]) (Subscript[(Overscript[ω, 1]), 3])+(Subscript[γ, 4]) (Subscript[(Overscript[ω, 1]), 4])+
	      (Subscript[γ, 12]) (Subscript[(Overscript[ω, 2]), 12])+(Subscript[γ, 13]) (Subscript[(Overscript[ω, 2]), 13])+(Subscript[γ, 14]) (Subscript[(Overscript[ω, 2]), 14])+(Subscript[γ, 23]) (Subscript[(Overscript[ω, 2]), 23])+(Subscript[γ, 24]) (Subscript[(Overscript[ω, 2]), 24])+(Subscript[γ, 34]) (Subscript[(Overscript[ω, 2]), 34])+                                         [27]
	      (Subscript[γ, 15]) (Subscript[(Overscript[ω, 3]), 1])+(Subscript[γ, 25]) (Subscript[(Overscript[ω, 3]), 2])+(Subscript[γ, 35]) (Subscript[(Overscript[ω, 3]), 3])+(Subscript[γ, 45]) (Subscript[(Overscript[ω, 3]), 4]) +
                (Overscript[ω, 4]) (Subscript[γ, 5			])

where the grades have been put on separate lines for clarity. Other CAV expressions with higher degree p-forms (not necessarily homogeneous) can also be defined. Examples are the homogeneous torsion and curvature 2-forms discussed next.

In the particular case of metric geometry, the grade[1] part of (OverHat[θ]) could represent an orthonormal co-frame with signature given by the Clifford algebra, and the grade[2] part of (OverHat[ω]) would represent Cartan’s skew-symmetric connection matrix. The commands grade[1,(OverHat[θ])] and and grade[2,(OverHat[ω])] will pick out these parts:

(OverHat[θ])= grade[1,(OverHat[θ])]=(Subscript[γ, 1]) (Subscript[(Overscript[θ, 1]), 1])+(Subscript[γ, 2]) (Subscript[(Overscript[θ, 1]), 2])+(Subscript[γ, 3]) (Subscript[(Overscript[θ, 1]), 3])+(Subscript[γ, 4]) (Subscript[(Overscript[θ, 1]), 4])  
						                                                                                                     [28]
(OverHat[ω])= grade[2,(OverHat[ω])]=(Subscript[γ, 12]) (Subscript[(Overscript[ω, 2]), 12])+(Subscript[γ, 13]) (Subscript[(Overscript[ω, 2]), 13])+(Subscript[γ, 14]) (Subscript[(Overscript[ω, 2]), 14])+(Subscript[γ, 23]) (Subscript[(Overscript[ω, 2]), 23])+(Subscript[γ, 24]) (Subscript[(Overscript[ω, 2]), 24])+(Subscript[γ, 34]) (Subscript[(Overscript[ω, 2]), 34])

In this geometric situation, the components of the torsion 2-form, Θ, and the curvature 2-form, Ω, are defined by the Cartan structure equations:

(Subscript[Θ, i])=(Subscript[(Overscript[dθ, 1]), i])+(∑_(k=1)^cadim)(Subscript[g, kk])(Subscript[(Overscript[ω, 2]), ik])⋀(Subscript[(Overscript[θ, 1]), k])
											                                    		[29]
(Subscript[Ω, ij])= (Subscript[(Overscript[dω, 2]), ij])+(∑_(k=1)^cadim)(Subscript[g, kk])(Subscript[(Overscript[ω, 2]), ik])⋀(Subscript[(Overscript[ω, 2]), kj])

These can be combined into the CAV torsion 2-form(OverHat[ Θ]) =(∑_i^cadim)(Subscript[Θ, i])(Subscript[γ, i]), and the CAV curvature 2-form (OverHat[Ω]) =(∑_(i,j>i)^cadim) (Subscript[Ω, ij])(Subscript[γ, ij]), which are then given by the AVF expressions

(OverHat[Θ]) = d[(OverHat[θ])]+(1/2)((OverHat[ω])**(OverHat[θ])+(OverHat[θ])**(OverHat[ω]))
									                          					[30]
(OverHat[Ω]) = d[(OverHat[ω])]+(1/2)((OverHat[ω])**(OverHat[ω]))

and these CAVs comprise all the Cartan structure equations for the manifold --which would be Riemannian for vanishing torsion, (OverHat[Θ])=0. The CAV commands maketorsion[] and makecurvature[] will use these definitions to evaluate them explicitly for any assigned (OverHat[θ]) and (OverHat[ω]) .

The definitions [30] can also be used in the general case when (OverHat[θ]) and (OverHat[ω]) incorporate all possible grades for the algebra. In this situation (OverHat[ω]) can be interpreted as a non-Abelian CAV gauge potential and (OverHat[Ω]) as the corresponding CAV field 2-form. Note that the field (OverHat[Ω]) will contain a mixture of the different grades of the CAV gauge potential (OverHat[ω]). In the cadim=4 case, for instance, interactions are generated among the

grade[1] : ( vector - valued),
grade[2] : ( tensor - valued),
grade[3] : ( pseudovector - valued), and   
grade[4] : ( pseudoscalar - valued) parts.

The exception is the grade[0] : (scalar-valued, or Abelian) part, which never mixes.

Both the torsion and curvature 2-forms satisfy differential identities by virtue of their definitions,

torsionidentity[]:=(d[(OverHat[Θ])]+(1/2)((OverHat[ω])**(OverHat[Θ])-(OverHat[Θ])**(OverHat[ω]))+(1/2)((OverHat[θ])**(OverHat[Ω])-(OverHat[Ω])**(OverHat[θ])))==0
														       		[31]
curvatureidentity[]:=(d[(OverHat[Ω])]+(1/2)((OverHat[ω])**(OverHat[Ω])-(OverHat[Ω])**(OverHat[ω])))==0

and are known to the program by these names. They can be verified by explicit calculation, although in the completely general case with arbitrary basis forms and all grades included, it requires some time for a 4-dim, or higher, algebra.

In the 4-dim Riemannian case with (OverHat[Θ])=0, only the last commutator in torsionidentity survives. It is a grade[1] 3-form which expresses the usual cyclic identity for the curvature components. The corresponding anticommutator, (OverHat[G])=((OverHat[θ])**(OverHat[Ω])+(OverHat[Ω])**(OverHat[θ]))/2 is a grade[3] 3-form which incorporates all four Ricci 3-forms expressing the Ricci, or actually Einstein, curvature tensor. It satisfais a contracted identity with the general form

contractedidentity[]:=(d[(OverHat[G])]+(1/2)((OverHat[ω])**(OverHat[G])+(OverHat[G])**(OverHat[ω]))-(1/2)((OverHat[Θ])**(OverHat[Ω])+(OverHat[Ω])**(OverHat[Θ])))==0            [32]

I.g. AVF names of variables and functions

All AVF names are lower case to distinguish them from Mathematica names. Most of the names on these lists are protected and so will refuse assignment. A large number of unlisted temporary variables and subroutines have names beginning with av$.  To avoid interference, this pattern should not be used when defining new names or symbols.

I.g.1.Variables

1.  adjlist - arbitrary permutation of the list in "elements"  
  2.  algebra - multiplication table for the "elements" of an  algebra
  3.  brackets - Lie brackets,[ (Subscript[V, forms[[i]]]),(Subscript[V, forms[[j]]]) ],for non-exact dual vectors
  4.  cadim - number of generators( (Subscript[γ, i])),in the orthonormal basis of a Clifford algebra
  5.  clifflist -list of the filenames in the"CliffordAlgebras" folder
  6.  coords- list of scalars designated as independent variables
  7.  coordsdim - number of independent variables; = Length[coords]
  8.  cosub - the list of basis 1-forms to be annulled in a subspace;"subspace[cosub]"
  9.  depend - "coords" as a Sequence; used for function arguments
10.  dforms -list of symbols for the exterior derivatives of the members of "forms"
11. drules - list of replacement rules for the exterior derivatives of "forms"
12. dscalars - list of symbols for the exterior derivatives of "scalars"
13. eldim - number of algebra elements; = Length[elements]
14. elements - list of generators of the algebra specified by "algebra"
15. fderiv - basic rules to give exterior derivatives of "forms" and "dforms"
16. fmdim - number of independent basis 1-forms; = Length[forms]
17. forms - list of basis 1-forms generating the exterior algebra -includes "dscalars"
18. frame - list of orthonormal basis forms
19. frdim - number of orthonormal basis 1-forms; = Length[frame]
20. gammas -all  Clifford "elements",retrieved from a file in  "CliffordAlgebras"
21. identity - elements={identity} is the initial default assignment for "elements"
22. names - list of all AVF and CAV variables and functions
23. natural - the"drules"specifying "closed"  basis 1-forms( default value) 
24. omegas - first list of graded symbols for a complete set of CAV  1-forms
25. scalars - list of 0-forms which will have exterior derivatives given by "dscalars"
26. scdim - number of scalars; =Length[scalars]
27. sderiv -  basic rules to  give exterior derivatives of "scalars" 
28. sig[i] - ((((Subscript[γ, i])))^2)=±1,the ith eigenvalue,(Subscript[g, ii]),of the diagonal Clifford metric
29. signature -list of all sig[i]; the argument for  "makeclifford[signature]"
30. skew - list of skew-symmetric structure constants:  (Subscript[sk, i,j,k])+(Subscript[sk, i,k,j])=0	
31. sub - list of basis 1-forms spanning a subspace; = Complement[forms,cosub]
32. symm - list of symmetric structure constants:  (Subscript[sy, i,j,k])-(Subscript[sy, i,k,j])=0	
33. thetas - second list of graded symbols for a complete set of CAV  1-forms
34. topartials - replacements to express exterior derivatives by  partials(subscripts)
35. tosub - replacements to annul "cosub" and  d[cosub] in a subspace
36. trivial - the initial default value of "algebra"  having "identity" in most positions
37. vec1,vec2,vec3,vec4 - four independent vectors created by "makevectors"
38. (Subscript[v1, i]),(Subscript[v2, i]),(Subscript[v3, i]),(Subscript[v4, i]) - the components of the above vectors in the dual basis to "forms"

I.g.2. Functions

The  argument avf means a single  algebra-valued-form; avf or {avfs} means either a single avf, or a list of them. Functions with CAV arguments are defined only for those expressions. Empty brackets mean no arguments.

1. adjmat[list_of_elements] - returns matrix:adjmat.adjlist = argument_list
  2.adL[element,list_of_elements] - returns (element)**{any list of the elements}
  3. adR[list_of_elements,element] - returns {any list of the elements}**(element)
  4. applydrules[avf or {avfs}] - implements "drules";= expand[{avfs}/.drules]
  5. associators[n] - returns up to "n"  associators for "algebra";prints number found
  6. coeffs[avf] - returns a list of the non-zero coefficients of "elements" in "avf"
  7. collect[avf or {avfs}] - collects the factors of "elements";displays"identity"
  8. contract[vector,avf or {avfs}] - contracts "vector" on {avfs};∘ is the infix form
  9. contractedidentity[] - differential identity for the Einstein 3-form  (Overscript[(OverHat[G]),  ])
10. curvatureidentity[] - aka Bianchi identity;general identity for CAV field  (OverHat[Ω])
11. d[avf or {avfs}] - returns exterior derivatives of arguments
12. da[avf or {avfs}]- shortcut for:   applydrules[d[arguments]]
13. δ[avf or {avfs}] -coderivative for arguments expressed in "frame"=hs[da[hs[arg]]]
14. (Subscript[D, sub])[avf or {avfs}] - coordinate derivative defined by "makecoords[]" command
15. dot[p-form1,p-form2] - scalar product of arguments expressed in "frame"
16. expand[avf or {avfs}] - substitutes infix  multiplication operator ** for ⋀ 
17. factor[basisform,avf] - returns the righthand factor of "basisform" in "avf"
18. generic[] -constructs a general "algebra" for "elements"using "skew" and  "symm"
19. grade[integer,CAV] - returns the specified grade of a CAV form
20. grades[CAV] - returns a list of all grades of a CAV form
21. hs[avf or {avfs}] - returns the Hodge dual for arguments expressed in "frame" 
22. in[avf] - converts "avf" to equivalent List expression for AVF operations
23. involute[CAV] - changes sign of all odd grades in CAV
24. lie[vector,avf or {avfs}] - returns  Lie derivatives of "avfs"  wrt "vector"
25. liealgebra[] - returns the Lie brackets of the dual vectors to non- exact forms
26. makealgebra[product_matrix]- establishes the multiplication table for "elements"
27. makeall[] - in CAV does(makethetahat;makeomegahat;maketorsion;makecurvature)
28. makeclifford[signature-list] - makes Clifford algebra with specified signature
29. makecoords[symbol_list] - defines a set of independent scalars and "partials"
30. makecurvature[]- calculates the CAV  2-form  (OverHat[Ω])  from the connection  1-form  (OverHat[ω])
31. makedrules[replacement_list]- establishes "drules" for "dforms" (+ optional Rules)
32. makeeinstein[] - makes a CAV  3-form  (OverHat[G])=((OverHat[θ]) **(OverHat[Ω])+(OverHat[Ω])**(OverHat[θ]) )/2  (4dim Einstein tensor)
33. makeelements[symbol_list] - establishes the list of generators for an algebra
34. makeforms[symbol_list] - establishes the list of fundamental non-exact 1-forms
35. makeframe[symbol_list] - defines a set of orthonormal basis forms = "frame" 
36. makematrices[] - constructs a matrix representation of the chosen  Clifford algebra 
37. makeomegahat[] - makes the generalized CAV connection  1- form, (Overscript[(OverHat[ω]),  ])
38. makescalars[symbol_list] - establishes the list of fundamental scalars(0-forms)
39. makethetahat[] - makes the generalized CAV "co-frame" 1-form, (OverHat[θ])
40. maketorsion[] -  calculates the CAV  2-form  (OverHat[Θ])  from the CAV  1-forms  (OverHat[θ])  and  (OverHat[ω])
41. makevectors[] - makes a set of four lists named:(vec1,vec2,vec3,vec4)
42. matmult[m1,m2] -  multiplication of AVF  matrices;infix operator, m1⊗ m2
43. mtx[avf_ array] - outputs the argument in MatrixForm;"algebra" is default argument
44. mult[avf1,avf2] - returns the product, avf1**avf2, where ** is the infix form
45. out[List_form_of_avf] - left inverse of in[avf];i.e.,avf==out[in[avf]]
46. prune[list,exp] - keeps only those members of "list"that  appear in "exp"
47. pullback[avf or {avfs}] - pulls back {avfs} into subspace"sub";={avfs}/.tosub
48. reset[]- set "timer" to zero
49. reverse[CAV] - returns the "reversion" of CAV; equiv.to reversing all (Subscript[γ, i]) products
50. setzero[list_of_expressions] - turns the  arg list into a list of equations;==0
51. subspace[list_of_basis_1-forms] - make replacement list "tosub" for "pullback"
52. timer[] - returns elapsed time from most recent "reset"
53. torsionidentity[] -  general identity for CAV field,(OverHat[Θ]) ;aka Cartan identity  
54.zerocurvature[] - constructs a list of "drules" giving vanishing CAV curvature  (OverHat[Ω])
55.zerotorsion[] - constructs a list of "drules" giving vanishing CAV torsion  (Overscript[(OverHat[Θ]),  ])

I.g.3. Jose: Additional comments on the choice of names

We have kept the original choices by Hugo Wahlquist on the naming conventions, though they are not standard in Mathematica. It is hence important to be aware of them:

	1. Commands of the package start with lowercase letters
	2. The many global variables of the package also have names starting with lowercase, instead of the standard capitalized names starting with $.
	3. The AVF package already uses some frequent 1-character symbols, namely d, δ, ω, Ω, θ, Θ, Γ, L, V, R. Also some 2- or 3- characters symbols: da, hs, dot, in, out, lie, mtx, sig, sk, sy, v1, v2, v3, v4, dω, dθ, dΩ, dΘ. Those symbols can be used for computations, but only as long as values are not assigned to them.

II. Basic computations

Sections II.a,b,c are taken from the file AVF_Demo.nb. Section II.d is taken from the file LieDerivative_Demo.nb.

Load the AVF package:

<<xAct`AVF`

II.a. First examples

II.a.1. Introducing the fundamental lists of variables

1) Declare a list of symbols to be scalars:

makescalars[{x,y,z}]

The information is stored in global variables:

scalars

scdim

The differentials of those scalars are automatically created:

dscalars

These exact 1-forms are also included in forms:

forms

2) To add in some non-exact basis 1-forms with derivative symbols in dforms we can use makeforms. The non-exact forms always appear before the exact forms:

makeforms[{ξ,η,ζ}]

The global variable dforms contains respective exact 2-forms which can be given additional properties using drules. The sub-section on drules appears below.

dforms

drules

3) AVF initializes the elements list and the algebra matrix as follows:

elements

algebra

so it is ready to accomplish ordinary differential form analysis without further input. Since that case is treated simply as a special (trivial) algebra, all the commands for it are identical to the more general case with a non-trivial algebra to be used here.

makeelements[{(Subscript[m, 0]),(Subscript[m, 1]),(Subscript[m, 2]),(Subscript[m, 3])}]

elements

eldim

The three lists scalars, forms and elements may be introduced in any order and be changed at any time by executing new make commands. Note that AVF needs to be told that something is a variable (not constant) by being included in scalars or forms, but not what it depends on. In fact, the members of these fundamental lists are always treated as independent variables, and can neither be functions nor have assigned values. Interdependence among them may be imposed by using replacement rules, however. See below.

II.a.2. Establishing the Algebra Table

The next statement defines the multiplication table of a 2-dimensional Clifford algebra which is isomorphic to the algebra of real 2×2 orthogonal matrices. Flipping a few of the signs would turn it into the quaternion algebra H.

(Subscript[M, 2])[R]={elements,{(Subscript[m, 1]),(Subscript[m, 0]),(Subscript[m, 3]),(Subscript[m, 2])},{(Subscript[m, 2]),-(Subscript[m, 3]),(Subscript[m, 0]),-(Subscript[m, 1])},{(Subscript[m, 3]),-(Subscript[m, 2]),(Subscript[m, 1]),-(Subscript[m, 0])}}

The makealgebra command sets the global variable algebra to its argument, (Subscript[M, 2])[R],

makealgebra[(Subscript[M, 2])[R]]

algebra

and this outputs the active algebra table as a matrix.

mtx[]

The command mtx[] is just an abbreviation for Mathematica's MatrixForm[] and will accept the same arguments. algebra is the default argument.

II.a.3. Matrix Representations

Calculations in AVF are accomplished using the algebra table for products of elements. Sometimes it is useful to have a matrix representation of the elements, even though the program never requires it. For example, a matrix representation of the (Subscript[M, 2])[R] generators is given by :

(Subscript[mat, 0])={{1,0},{0,1}};
(Subscript[mat, 1])={{1,0},{0,-1}};
(Subscript[mat, 2])={{0,-1},{-1,0}};
(Subscript[mat, 3])={{0,-1},{1,0}};

and their matrix products agree with the (Subscript[M, 2])[R] algebra table; e.g. ,

((Subscript[mat, 1])).(Subscript[mat, 2])==(Subscript[mat, 3])

Since the indices of mat and m agree,  any AVF expression or list can be converted to matrix form by the kernel replacement rule,  /. m -> mat ; i.e. ,

elements

elements/.m->mat

Another example is shown below, and the use of matrices is also developed further down .

II.a.4. Sample input expressions

Here are two sample AVF expressions. The first, avf1, is an AVF 1-form; the second, avf2, has a different kind of factor omitted from each term and is a differential form of inhomogeneous degree. The scalars and forms lists are output for reference.

avf1=2λ y ζ (Subscript[m, 2]) +(Subscript[m, 3]) (x^3) dz

avf2=z (Subscript[m, 2])+3 η y+(Subscript[m, 1]) dx⋀ξ

scalars
forms

The missing algebra element in the second input term of avf2 defaults to the identity, (Subscript[m, 0]). It never needs to be typed in input, and is generally suppressed in output. Note that, except inside a wedge product, the order of factors within a term is immaterial.

II.b. Algebraic operations

II.b.1. Multiplication

The multiplication operator ** simultaneously implements the Grassmann algebra of differential forms and the specified element algebra. Operator ** has high precedence; its multiplicands will need parentheses if they're not single names, and also in multiple products if the algebra is non-associative.

A first example using ordinary differential forms, where (Subscript[m, 0]) is the implicit algebra element:

(x dy-y dx)**(ξ-η)

Though avf1 is a 1-form, its algebra-valued self product is non-zero:

avf1**avf1

avf3=avf1**avf2

For this matrix algebra, AVF multiplication is associative, but generally non-commutative.

avf1**avf3**avf2==(avf1**avf1)**(avf2**avf2)

avf1**avf2===avf2**avf1

II.b.2. Formatting commands

The non-zero coefficients of the algebra elements in an AVF expression are given as a list of differential forms by:

coeffs[avf3]

and the expression is displayed in collected form by:

collect[avf3]

This is the only AVF command that always outputs the identity element (Subscript[m, 0]) explicitly. It is required in the next statement to give the correct matrix representation of avf3:

matavf3=collect[avf3]/.m->mat

mtx[matavf3]

The collect[] command can be applied to arrays of AVFs, but coeffs[] must be Mapped onto them,

collect[{avf1,avf2}]

Map[coeffs,{avf1,avf2}]

II.b.3. Vector contraction

The infix contraction operator is the small open circle, typed by the sequence esc-sc-esc. It is used to contract a vector either on a single AVF, or on a list of them. Whenever new 1-forms are defined, the makeforms command automatically generates four independent vectors {vec1, vec2, vec3, vec4} just for convenience. Each vector is a symbol list of the same length as the forms list. The first two vectors:

vec1

vec2

Since they are expressed in the dual basis to forms, each component of a vector is its contraction on the corresponding member of forms; i.e. ,

forms

vec1∘(η+dz)

avf2

vec1∘avf2

vec1∘%

A number of sequential contractions,

vec2∘vec1∘avf3

and contraction on a list,

vec2∘vec3∘{avf1,avf2,avf3}

collect[%]

vec3∘%

It is not necessary to use these convenience vectors. Any list of scalar variables, including specified or unspecified functions of the elements of scalars may be used, so long as the list agrees in length with the forms list. Any such list will be interpreted as a vector expressed in the dual basis to forms. Components not in scalars (or functions thereof) will be constant parameters, as are the convenience-vector components.

A quick way to get a new vector of the correct length is by using a replacement,

pvec=vec1/.v1->p

or by the Mathematica command,

pvec=Array[p,fmdim]

where the global variable fmdim = Length[forms].

II.b.4. Factoring an AVF

avf3

Any basis form in forms or dforms will be factored out (to the left) of an AVF by:

fac=factor[ζ,avf3]

All terms containing ζ are factored, so the following expression represents the part of avf3 that is actually independent of ζ:

avf3-ζ⋀fac

This will simplify using the expand operator (lower case "e"), which is similar to Mathematica's upper case Expand, except that it operates on wedge products .

expand[%]

Jose: The function factor actually does the equivalent of Coefficient in Mathematica, not the equivalent of Factor.

An iterative subroutine to factor out any monomial product of basis forms from an AVF would be:

monomialfactor[mono_,avf_]:=Block[{fac},
fac=avf;
If[Head[mono]=!=Wedge,
fac=factor[mono,fac],
Do[fac=factor[mono[[i]],fac],{i,Length[mono]}]
];
fac
];

For example,

monomialfactor[ξ⋀dx,avf3]

II.b.5. The expand function

The AVF function expand[expr] replaces all wedge products in expr with the actual multiplication operator **, and so re-calculates the entire expression. Any expression containing wedge products of AVF expressions can be expanded in this way. For instance,

avf1⋀avf2

Only the substitutions occurred because wedge is not recognized as an operator, and with the factors being algebra-valued-forms, it is a slight abuse of notation. Nevertheless, this re-derives avf3,

expand[%]

Note that an expression containing wedge products of factors which are not simple basis forms, such as avf1⋀avf2, is not an acceptable input for any AVF operations other than expand. The operator expand must be used to convert such expressions to correct input form for other AVF functions.

Since every wedge product at all levels in the expressions will be calculated anew, using expand allows arbitrary replacements to be made within wedge products, and this is its primary function. For example, the ζ-independent part of avf3 could also be obtained by

avf3/.ζ->0

expand[%]

Clearly, any wedge product in an input expression (even between basis forms) could just as well be typed using **. This has little real effect when used between basis forms (except perhaps to simplify and re-order a product into Mathematica's canonical order), but it constitutes a much larger abuse of standard nomenclature.

ξ⋀dz+η⋀ζ⋀η

expand[%]

ξ**dz+η**ζ**η

II.c. Exterior calculus operations

II.c.1. Exterior differentiation

The exterior derivative of an AVF is given by d[expr]; e.g. ,

avf1

d[avf1]

Note that scalars and forms are differentiated, but the algebra elements and parameter λ are not. A more complicated example is:

d[avf3]

The operator d[] also works on a list of AVF's,

d[{avf1,avf2}]

as well as on a matrix of them,

d[matavf3]

d[%]

The non-commutativity coming from both the Grassmann and the element algebras generally forbids any simple application of the Leibnitz rule for derivations, unless the leading factors are of homogeneous degree as differential forms and the algebraic order of the factors is preserved. The following expansion works because avf1 is a 1-form (note the minus sign).

d[avf1**avf2]==d[avf1]**avf2-avf1**d[avf2]

For simplicity, the input samples, avf1 and avf2, involved only algebraic functions of the scalars. Any functions known to Mathematica can be used in an AVF, but any arguments not appearing in the scalars list will be treated as constant parameters;

avf4= Cos[k y]ξ (Subscript[m, 1])+Sin[k y]η (Subscript[m, 2])

d[avf4]

Simplify[avf4**avf4]

d[%]

and an unspecified function including a parameter gives,

d[f[x,y,z,k]]

II.c.2. Defining drules

An important feature of AVF involves the list of replacement rules for exterior derivatives called drules. Their primary purpose is to establish properties for the derivatives of the non-exact basis forms (the members of dforms) which can then be easily implemented in AVF expressions. They are not restricted to such replacements, however, and may include any other appropriate replacement rules.
                             
Additional structure for the derivatives in dforms is prescribed by defining a set of replacement rules which are given by expansions of the members of dforms in terms of the members of forms. If all the non-exact 1-forms are closed, for example, the appropriate value for drules is the global variable natural,

natural

and this is the default value of drules established initially for all the non-exact members of forms introduced by the makeforms command; i.e., currently,

drules

A different set of replacements can be defined; e.g.,

newdrules={dξ->η⋀ζ,dη->ζ⋀ξ,dζ->ξ⋀η}

and this becomes the reserved variable drules using the makedrules command;

makedrules[newdrules]

The current drules can be implemented in any AVF expression with the command applydrules, which is defined by: applydrules[arg_]:=expand[arg/.drules]; e.g.,

d[avf2]

applydrules[%]

The drules can be changed at any time to a different set. As with other make commands, makedrules won't accumulate replacements, but different sets of rules may be combined using Join in the argument. The following command simply resets drules to natural,

makedrules[{}]

so that now,

applydrules[d[avf2]]

Re-establish newdrules.

makedrules[newdrules]

The nested command just above, applydrules[d[arg]], is actually used more often than d[arg] alone. An abbreviated differentiation operator da[arg] is defined for it; i.e.,

d[ξ+η]

applydrules[%]

da[ξ+η]

Note that in using da[], differentiation occurs before the drules are applied, so they have no effect on the derivative of any exact form, which necessarily vanishes; e.g.,

dforms

d[dforms]

da[dforms]

but,

forms

d[forms]

da[forms]

Generally, it is important to ensure consistency (closure) of the drules, which is not verified automatically by the program; e.g.,

da[ξ]

and differentiating without applying the drules gives,

d[%]

but as required for consistency of the double derivative,

applydrules[%]

Checking all of them

da[da[ξ]]==da[da[η]]==da[da[ζ]]==0

but again, this could be done in one step on the whole list;

da[da[forms]]

This ensures that both double derivatives will vanish identically for all AVF expressions; e.g.,

d[d[avf2]]

da[da[avf2]]

Generally, the use of drules is optional, but there is one situation in which they are mandatory, and is the reason for establishing a default value for them. The one place drules are required is for vector contractions, which are defined on all members of forms, but not on their exterior derivative 2-forms. In the case of vector contraction, they are invoked automatically before doing the contraction; e.g.,

vec1∘dforms

Note that all the replacements that have been established as drules are applied in a contraction, not just those involving dforms.

In summary, establishing a set of drules is essential for most operations involving contractions, such as the Lie derivative of AVFs. In addition: they can be used to define anholonomic basis forms; to express derivatives of functions of coordinates in terms of an anholonomic basis; and to impose a group structure on the basis 1-forms using a set of Maurer-Cartan equations (as in newdrules).

II.c.3. Transformations of coordinates

Call the current scalars cartesian and add in a new set, spherical

cartesian=scalars

spherical={r,θ,φ}

makescalars[Join[cartesian,spherical]]

dscalars

The transformation from cartesian to spherical coordinates is expressed by a list of replacement rules, not assignments. Mathematica's Thread command is convenient for distributing the Rule symbol,

trans=Thread[cartesian->{r Sin[θ] Cos[φ],r Sin[θ]Sin[φ],r Cos[θ]}]

and the transformation can be accomplished by ReplaceAll (/.).

cartesian/.trans

The operator d[] works on a list of AVFs --not on a list of Rules-- but the transformation of derivatives can be constructed quickly by;

dtrans=Thread[d[cartesian]->d[(cartesian/.trans)]]

and all of these can be joined into a single list of transformation rules;

tospherical=Join[trans,dtrans]

Simplify[(x^2)+(y^2)/.tospherical]

For the volume form,

vol=dx⋀dy⋀dz

vol/.tospherical

The substitutions were made, but the expression needs to be simplified. Mathematica's Expand has no effect on wedge products,

Expand[%]

but the analogous AVF command does the required expansion of the wedge products,

expand[%]

after which Mathematica will simplify the coefficients,

Simplify[%]

This could also be done with drules.

makedrules[dtrans]

Simplify[applydrules[vol]]

II.c.4. Clean up

To avoid confusion among the variables of different problems, it is important to have a way of undeclaring the variables we have registered in the various fundamental lists. There are two sets of variables: the private global variables of the AVF package (in the xAct`AVF` or xAct`AVF`Private` contexts) and the user variables (in the Global` contex).

a) Global variables of the AVF package.

Jose: To help keeping track of which variables are modified, I have added these:

ModifiedGlobalVariables

%/. AVFinitialstate

%%/.AVFstate

To restore the original state of the AVF variables we can do the following, in this order:

makeelements[{identity}]

makealgebra[{{identity}}]

makeforms[{}]

makescalars[{}]

Now:

ModifiedGlobalVariables

Jose: Those four commands (plus some others of the same type) have beeng grouped in the single action makeclear[], which will be used from now on in this file for clearing the AVF state.

b) Then we also have our own variables, declared in the Global` context of Mathematica :

?Global`*

We can remove them individually, or can remove all of them using

Remove["Global`*"]

Now the Global` context is empty:

?Global`*

II.d. Lie differentiation

II.d.1. Setting up some scalar variables

makescalars[{x,y,z}]

Introducing non-exact 1-forms will be delayed to a later section.

Since the algebra elements are constants, they are not actively involved in Lie differentiation. All the operations below can be applied to general AVF's, but for illustration we use ordinary differential forms; i.e., the trivial default algebra.

mtx[]

II.d.2. Lie derivative of AVFs, using a coordinate basis

The current forms list and the first convenience vector,

forms

vec1

The function lie[vec, avf] calculates the Lie derivative of avf with respect to a vector vec using the expansion lie[vec_,avf_]:=vec∘d[avf]+da[vec∘avf]. On a function of the scalars, lie just gives the directional derivative,

lie[vec1,F[x,y,z]]

But the convenience vector components are constants,

d[vec1]

and usually one wants a vector field. There are two ways to turn the components of V into field variables: either write them explicitly as specified or unspecified functions of scalars; or add the components into scalars as new independent variables. The problem with the first approach arises from Mathematica's output notation for derivatives of unspecified multi-variable functions, which is lengthy and not very readable.

Consider the vector V having unspecified functional components dual to {dx,dy,dz}, operating on a general 2-form T,

V={v1[x,y,z],v2[x,y,z],v3[x,y,z]}

T=X[x,y,z]dy⋀dz+Y[x,y,z]dz⋀dx+Z[x,y,z]dx⋀dy

lie[V,T]

II.d.3. Introducing coordinates with makecoords

Better output is provided in AVF by establishing a subset of scalars as coords, using the makecoords[] command. More details about makecoords[] are given at the end of this section. Any pre-existing members of scalars which are not designated as coords will have subscript partial derivative expansions defined for them using Format output, and these are added into the drules, which are invoked automatically for Lie derivatives.

Using this approach, the scalar field variables in V and T are written without functional dependence, and are added into scalars before defining coords,

V={v1,v2,v3}
T=X dy⋀dz+Y dz⋀dx+Z dx⋀dy

makescalars[Join[scalars,V,{X,Y,Z}]]

and then coords is established,

makecoords[{x,y,z}]

scalars

drules

Now the same Lie derivative performed above is output in a more readable form:

lie[V,T]

To sort that into independent bases, the canonical order of the basis 2-forms (as they appear there) must be used. This gives about the simplest possible output for general vectors and forms.

Collect[%,{dy⋀dz,dx⋀dz,dx⋀dy}]

Note that the current drules are never invoked automatically in exterior differentiation; e.g.,

d[{v1,Y,T}]

but they will be applied using da[],

da[{v1,Y,T}]

and are automatic for all vector contractions,

V∘d[{v1,Y,T}]

Any variable not in scalars can have the same formatting of partial derivatives by writing it as a function of the reserved variable depend, which inserts the dependence on coords,

f=F[depend]

d[f]

lie[V,f]

The operators d and lie must commute identically for an arbitrary vector field,

d[lie[V,f]]-lie[V,d[f]]

but the initial d[] derivative in that statement does not invoke the drules required to give the correct result; i.e.,

applydrules[%]

and the identity should be written using da[] rather than d[]; for example, on the 2-form T,

da[lie[V,T]]-lie[V,da[T]]

Clearly, this technique may not be helpful when some vector components and some scalars are independent of some coords. In such cases, it may be better to use the standard functional notation, although it might also be feasible to edit out any unwanted terms from the automatically constructed drules, to use makedrules[] with the edited drules, and so preserve the brevity given by the Format notation.

II.d.4. Lie product of vectors

Since both d[] and ∘ extend to arrays of AVFs, so does the lie[] function. And since a vector is represented as a list of scalar components, lie[] can be applied to vectors as well. Introduce a new vector W,

W={w1,w2,w3}

makescalars[Join[scalars,W]]

To avoid duplication of drules,

makedrules[{}]

and now again make coords,

makecoords[{x,y,z}]

drules

lie[V,W]

but for the Lie product this must be anti-symmetrized,

VW=lie[V,W]-lie[W,V]

The identity for Lie differentiation reads

Expand[lie[VW,T]-(lie[V,lie[W,T]]-lie[W,lie[V,T]])]

II.d.5. Anholonomic forms

Coordinate and anholonomic basis forms can perfectly well be mixed together, but for the moment the scalar variables will be dropped,

makescalars[{}]

makeforms[{(Subscript[ω, 1]),(Subscript[ω, 2]),(Subscript[ω, 3])}]

The first convenience vector is given a shorter name,

V=vec1

By default, the drules specify closed 1-forms, and lie invokes drules automatically to perform the vector contractions involved. Furthermore, the vector V is constant,

drules

d[V]

so the resulting Lie derivative of the 2-form, Q , vanishes.

Q=(Subscript[ω, 1])⋀(Subscript[ω, 2])

lie[V,Q]

The anholonomic basis can be given the Maurer-Cartan structure relations:

mcdrules={(Subscript[dω, 1])->(Subscript[ω, 2])⋀(Subscript[ω, 3]),(Subscript[dω, 2])->-((Subscript[ω, 1])⋀(Subscript[ω, 3])),(Subscript[dω, 3])->(Subscript[ω, 1])⋀(Subscript[ω, 2])}

makedrules[mcdrules]

and checking closure,

da[da[forms]]

The vector V becomes a field by making its components into independent scalars,

makescalars[V]

forms

and now the Lie derivative and commutation property are non-trivial.

lie[V,Q]

da[lie[V,Q]]-lie[V,da[Q]]

When new basis forms appear, as the (Subscript[dv1, i]) above, the convenience vectors will automatically expand to accommodate them,

vec1

but these 3 new components, representing contractions on the derivatives of the original vector components, are not in scalars and so are constant.

d[vec1]

Taking higher Lie derivatives following this approach would require expanding the vectors and scalars at each new level. That is possible, but it gets out of hand rather quickly. However, the makecoords command can be used here to prevent the expansion; e.g.,

If higher derivatives are to be calculated, it will be necessary to expand V just once to cover contractions on the coordinate basis used to expand all scalar variables, say {x,y,z}

makescalars[{x,y,z}]

forms

Since all other scalars will be expanded on the coordinate basis, only these first 6 members of forms need to have vector components, and these components must appear in the final scalars list,

V=vec1

makescalars[V]

and now use makecoords to get a complete set of drules.

makecoords[{x,y,z}]

The final lists:

scalars

forms

drules

Repeating the same Lie derivative as calculated above,

VQ=lie[V,Q]

da[VQ]-lie[V,da[Q]]

and a second derivative can now be evaluated,

lie[V,VQ]

The coordinates can mix in with the anholonomic forms;

S=dx⋀(Subscript[ω, 1])+dy⋀(Subscript[ω, 2])+dz⋀(Subscript[ω, 3])

VS=lie[V,S]

da[VS]-lie[V,da[S]]

lie[] will operate on any array of AVFs

M={{(Subscript[ω, 1]),(Subscript[ω, 2])},{(Subscript[dω, 1]),(Subscript[dω, 2])}}

lie[V,M]

da[lie[V,M]]-lie[V,da[M]]

II.d.6. Lie products and the Lie algebra of non-exact forms

The "dual" basis vectors are given by the rows of the identity matrix, where fmdim is the length of the forms list. The duals to the exact 1-forms in dscalars must commute, so can be eliminated,

makescalars[{}]

forms

duals=IdentityMatrix[fmdim];

mtx[%]

A list of the Lie derivatives of the forms list with respect to each of their 3 dual vectors:

lf=Table[lie[duals[[m]],forms],{m,fmdim}]

And next, a list of the anti-symmetrized derivatives of each of these with respect to the dual vectors; equivalent to the Lie derivative of forms with respect to the Lie brackets of the duals.

Table[lie[duals[[m]],lf[[n]]]-lie[duals[[n]],lf[[m]]],{m,fmdim-1},{n,m+1,fmdim}]

Comparing the two lists, which contain the same results up to signs and order, reveals the Lie algebra of drules.

The function liealgebra[] will return a list of the Lie brackets, L[ (Overscript[V, m]),(Overscript[V, n])] , for the full set of vectors dual to the current forms list (excluding any exact basis forms in dscalars), using the current drules which must be defined for all the non-exact forms.

liealgebra[]

The variable brackets contains the same thing, but with the numerical overscripts replaced by the corresponding dual 1-forms, which need not be indexed or ordered in the same way.

brackets

Clear[brackets]

II.d.7. makecoords: Format command for coordinates and partial derivatives

Making a new scalars list:

makescalars[{u,v,w}]

A special new set of scalars (or a subset of the existing scalars) can be designated as coords by the command:

makecoords[{x,y}]

Any new symbols introduced will be included automatically in scalars and dscalars, with coords moving to the front.

scalars

dscalars

Any pre-existing scalars which are not designated as coords will have subscript partial derivative symbols defined for them using Format output. A set of replacement rules, topartials, is automatically generated to expand the exterior derivatives of these scalars in any AVF as follows:

topartials

and the set topartials is automatically included in drules, so that,

dscalars/.topartials

can also be accomplished by,

da[scalars]

with appropriate closure of the second derivative.

da[%]

These partial derivative expansions provide a more concise and readable notation for the output of some AVF expressions. Note that topartials is defined only for scalars introduced before the makecoords command is executed, and the transformations are implemented only for second partials. Furthermore, the subscript symbols are not recognized as derivatives by Mathematica for input.

By using contraction with the vectors dual to the coords basis forms, a particular partial derivative of an AVF (expressed in terms of coords) is selected by the operator (Subscript[D, sub]), where sub can be either the coordinate symbol, or an integer giving the position of the coordinate in the coords list. This operator extends to arrays of AVFs as well. For instance,

(Subscript[D, x])[{u^3, Sin[v]}]

(Subscript[D, 1])[%]

(Subscript[D, y])[%]

Because the D operator is generated by first taking an exterior derivative, it may not give the expected result on a differential form, especially an exact one,

(Subscript[D, x])[u dv+v du]

The selection of independent coordinates and dependent scalars can be changed at any time. For example, interchanging roles,

makecoords[{u,v,w}]

scalars

dscalars

dscalars/.topartials

The variable depend can be used to make any other variable into a function of coords with a similar output representation for its first and second derivatives; e.g.,

G[depend]

d[%]

which is a bit easier to scan than standard Mathematica output;

makecoords[{}]

d[G[u,v,w]]

and considerably improves the looks of the spherical Laplacian derived above

Lsph=(((Subscript[ω, 1])⋀(Subscript[ω, 2]) (((Csc[θ])^2) Derivative[0,2][ψ][θ,ϕ]+Cot[θ] Derivative[1,0][ψ][θ,ϕ]+Derivative[2,0][ψ][θ,ϕ]))/(R^2))

makecoords[{θ,ϕ}]

Lsph

This format is especially useful for Lie differentiation when the vector components are expressed as functions of coords.

Recalling the curvature on the spheroid from section ?? above,

(Subscript[Ω, θϕ])=-(((-1+k) Sin[θ] dθ⋀dϕ)/(((1-k ((Sin[θ])^2)))^(3/2)))

we want its Lie derivative in the coordinate basis, with respect to a vector vec

vec={(Overscript[v, θ]),(Overscript[v, ϕ])}

makeforms[{}]

SetSystemOptions["DifferentiationOptions"->{"DifferentiateHeads"->False}];

makescalars[{θ,ϕ,(Overscript[v, θ]),(Overscript[v, ϕ])}]

makecoords[{θ,ϕ}]

drules

lie[vec,(Subscript[Ω, θϕ])]

Simplify[%,Trig->False]

sph=%/.k->0

A vector  ( (Overscript[v, θ])(∂_(θ ))+ (Overscript[v, ϕ])(∂_ϕ))  making these expressions vanish would leave (Subscript[Ω, θϕ]) unchanged.
An obvious solution from symmetry in both cases is the Killing vector: (Overscript[v, θ])= 0 , (Overscript[v, ϕ])= 1.

The makecoords facility  can be useful also for Hamiltonian mechanics. For a simple example using canonical coordinates in two dimensions:

canonical={p1,p2,q1,q2}

makescalars[canonical]

dscalars

Jose: Variable ω changed to om to avoid loading values into the AVF variable ω.

om=p1 dq1+p2 dq2

dom=d[om]

A convenience vector,

vec1

can be edited to adapt it,

vec={(Subscript[vp, 1]),(Subscript[vp, 2]),(Subscript[vq, 1]),(Subscript[vq, 2])}

vec∘dscalars

Adding in the vector components and an arbitrary Hamiltonian function to "scalars",

makescalars[Join[scalars,vec,{H}]]

To avoid including previous drules,

makedrules[{}]

and now introduce coords,

makecoords[canonical]

drules

The Hamiltonian flow equations read,

vec∘dom+da[H]

and taking the independent components,

eqns=setzero[Coefficient[%,dscalars]]

The Hamiltonian for a pair of coupled oscillators could be,

explicit={H->Function[{p1,p2,q1,q2},( (p1^2)+(p2^2))/(2 m)+k (((q1-L))^2)/2+k (((q2+L))^2)/2+ϵ/2(((q1-q2))^2)]}

eqns=eqns/.explicit

equilibrium=eqns/.Thread[vec->{0,0,0,0}]

Flatten[Solve[%,canonical]]

II.d.8. Clean up

makeclear[]

Remove["Global`*"]

ModifiedGlobalVariables

III. Examples

III.a. A toy geometry problem -- Almost trivial, but not quite

This is taken from the file AVF_Demo.nb.

This problem shows how AVF and Mathematica commands work together, and further illustrates the use of drules.

In cylindrical coordinates {r,ϕ,z}, put r = R sin(θ) and z = (Sqrt[(1 - k)]) R cos(θ), so that (1 - k) (r^2)+(z^2)= (1 - k) (R^2),  a spheroid with equatorial radius R and polar radius (Sqrt[(1 - k)])R ; i.e., prolate for k < 0 , spherical for k=0, oblate for 0 < k < 1 , a disk of radius R for k = 1.

The independent coordinates will be θ and ϕ, and we also introduce three non-exact basis forms for later use .

makescalars[{θ,ϕ}]

makeforms[{(Subscript[ω, 1]),(Subscript[ω, 2]),(Subscript[ω, 3])}]

Previously, the variables r and z were in scalars, but are not there now, so can be assigned values;

r=R Sin[θ]
z=(Sqrt[(1-k)])R Cos[θ]

Since k and R are not members of any fundamental list, they are treated as constant parameters.

dr=d[r]
dz=d[z]

AVF knows that dθ and dϕ are 1-forms, but Mathematica doesn't, so the Euclidean line element in cylindrical coordinates can be input as:

Simplify[(dr^2)+(dz^2)+(r^2)((dϕ)^2)/.((Cos[θ])^2)->1-((Sin[θ])^2)]

Using Mathematica's Collect[] command,

Collect[%,{((dθ)^2),((dϕ)^2)}]

showing the induced metric on the spheroid has orthonormal basis forms,  R(Sqrt[1-k (sin^2)(θ)])dθ  and  R sin(θ) dϕ, which can be identified with the non-exact basis forms, (Subscript[ω, 1]) and  (Subscript[ω, 2]) . Here again we use replacement rules, not assignments, which are forbidden for the members of forms. It's actually much more useful to express the relations this way, so that transformations between the orthonormal and coordinate bases are easily made in both directions.

tocoords={(Subscript[ω, 1])->R(Sqrt[1-k Sin[θ]^2])dθ,(Subscript[ω, 2 ])->R Sin[θ]dϕ}

The rules can be turned into equations to solve for the inverse transformation. Writing equations does not involve assignments, nor does their solution.

eqns=tocoords/.Rule->Equal

toortho=Flatten[Solve[eqns,dscalars]]

In a 2-dim space, the only independent connection form is (Subscript[ω, 12]). Since (Subscript[ω, 3 ])is already in the forms list, that symbol will be used for it temporarily. The Cartan structure equations,  (Subscript[dω, i]) + (Subscript[ω, ij])⋀(Subscript[ω, j]) = 0 , then can be expressed by the replacement rules:

structure={(Subscript[dω, 1])->(Subscript[ω, 2])⋀(Subscript[ω, 3]),(Subscript[dω, 2])->(Subscript[ω, 3])⋀(Subscript[ω, 1])}

The transformations toortho can also be entered as drules, so that everything, including derivatives of functions, will be converted automatically to the orthobasis.

makedrules[Join[structure,toortho]]

Because no drule has been established for (Subscript[ω, 3]), these drules are not properly closed. Imposing closure can be used to determine (Subscript[ω, 3]); i.e., for consistency the following conditions must vanish,

conditions=da[da[scalars]]

Vanishing of the first condition requires (Subscript[ω, 3 ])proportional to (Subscript[ω, 2])with no component on (Subscript[ω, 1]). So we can safely factor (Subscript[ω, 1]) out of the second condition, and equate the result to zero.

factor[(Subscript[ω, 1]),conditions[[2]]]==0

soln=Flatten[Solve[%,(Subscript[ω, 3])]]

Put this into drules:

newdrules=expand[drules/.soln]

and the obvious fact that  (Subscript[ω, 1]) is closed appears explicitly. Now establish these as the drules,

makedrules[newdrules]

Note: the last two statements could be combined into one (without defining newdrules), but drules is Protected, so it can't be accomplished just by assignment without using makedrules[].

Checking for consistency:

da[da[scalars]]

da[da[forms]]

Set the connection form equal to the solution for (Subscript[ω, 3]), and find the curvature 2-form expressed in orthobasis:

(Subscript[ω, 12])=(Subscript[ω, 3])/.soln

(Subscript[Ω, 12])=da[(Subscript[ω, 12])]

(Subscript[Ω, 12])=Simplify[%]

The same quantity in the coordinate basis:

(Subscript[Ω, θϕ])=Simplify[expand[(Subscript[Ω, 12])/.tocoords],Trig->False]

Interpretation of the following special values (as products of the Gaussian curvatures) is much simpler in the orthonormal basis than in the coordinate basis.

At the poles:

(Subscript[Ω, 12])/.θ->0

At the equator:

(Subscript[Ω, 12])/.θ->Pi/2

And for a sphere:

(Subscript[Ω, 12])/.k->0

In 2-dim the Bianchi identity is trivial:

da[(Subscript[Ω, 12])]

The surface element in the orthonormal basis is  (Subscript[ω, 1])⋀(Subscript[ω, 2]), while in the coordinate basis:

expand[(Subscript[ω, 1])⋀(Subscript[ω, 2])/.tocoords]

The area of a polar cap, where pa is the polar angle or colatitude, is (Jose: The following few definitions have been deactivated because they take a long time and demonstrate nothing of AVF):

Timing[polarcap=Integrate[(R^2) Sin[θ] (Sqrt[1-k ((Sin[θ])^2)]),{θ,0,pa},{ϕ,0,2 Pi}]]

and this gives the familiar result for a sphere;

FullSimplify[Limit[First@polarcap,k->0]]

The total surface area for any spheroid is,

area=Simplify[polarcap/.pa->Pi]

For the sphere:

Limit[area,k->0]

For the flat disk:

Limit[area,k->1]

In this simple 2-dim. case, the Hodge star operation is easily defined in the orthonormal basis.

toduals={(Subscript[ω, 1])->(Subscript[ω, 2]),(Subscript[ω, 2])->-(Subscript[ω, 1])}

For a function, ψ[θ,ϕ] , with exterior derivative in the coordinate basis,

d[ψ[θ,ϕ]]

the  *d[ψ]  operation is given by

da[ψ[θ,ϕ]]/.toduals

and the Laplacian on the spheroid, d*d[ψ], is the factor of (Subscript[ω, 1])⋀(Subscript[ω, 2 ])in the next expression,

Simplify[da[%]]

which becomes the usual expression for a sphere,

%/.k->0

Clean up:

makeclear[]

Remove["Global`*"]

ModifiedGlobalVariables

III.b. The quaternion algebra

This is taken from the file AVF_Commands.nb.

III.b.1. Establishing the quaternion algebra H

Introduce a list of four elements, where the initial element (Subscript[σ, 0]) is the identity.

makeelements[{(Subscript[σ, 0]),(Subscript[σ, 1]),(Subscript[σ, 2]),(Subscript[σ, 3])}]

The multiplication table defining H is entered,

H={{(Subscript[σ, 0]),(Subscript[σ, 1]),(Subscript[σ, 2]),(Subscript[σ, 3])},{(Subscript[σ, 1]),-(Subscript[σ, 0]),(Subscript[σ, 3]),-(Subscript[σ, 2])},{(Subscript[σ, 2]),-(Subscript[σ, 3]),-(Subscript[σ, 0]),(Subscript[σ, 1])},{(Subscript[σ, 3]),(Subscript[σ, 2]),-(Subscript[σ, 1]),-(Subscript[σ, 0])}};

and this becomes the established algebra by,

makealgebra[H]

algebra

With no argument, mtx[] outputs its default argument algebra as a matrix

mtx[]

Input a general quaternion,

q=Sum[(Subscript[x, i])(Subscript[σ, i]),{i,0,3}]

and construct its conjugate,

(OverBar[q])=-q/.(Subscript[x, 0])->-(Subscript[x, 0])

III.b.2. Multiplication

AVF multiplication uses **, the NonCommutativeMultiply infix operator,

q**(OverBar[q])

The identity element generally is suppressed in output from AVF operations. An independent quaternion,

Q=q/.x->ω

with the non-commutative quaternion product,

qQ=q**Q

q**Q-Q**q

Any number of AVFs can be multiplied together,

q**Q**(OverBar[q])

and if the algebra table specifies a non-associative algebra, the order of performing triple products may be important. But for H it's not,

(q**Q)**(OverBar[q])-q**(Q**(OverBar[q]))

All the commands used herein can be applied to non-associative cases, such as octonions and Lie algebras, with due regard for the ordering of triple products.

III.b.3. Format commands

The non-zero coefficients of the algebra elements in an AVF, such as qQ , are returned in a list by

coeffs[qQ]

and the AVF expression is output in collected form by,

collect[qQ]

This is the only AVF command that always outputs the identity element explicitly. The result contains the usual scalar and vector products for 3-vectors,

%/.{(Subscript[x, 0])->0,(Subscript[ω, 0])->0}

III.b.4. Differentiation

Exterior differentiation is accomplished with the operator d[] , but since no scalars or forms lists have been established yet, all quantities are treated as constants,

d[qQ]

The coefficients in q

q

can be made into independent scalar fields by,

makescalars[coeffs[q]]

and the makescalars command also generates their 1-form derivative symbols, dscalars,

dscalars

The algebra elements themselves are always constants, but q has become a quaternion field,

d[q]

d[q**(OverBar[q])]

The coefficients in Q can be established as non-exact basis 1-forms by

makeforms[coeffs[Q]]

where the independent basis 1-forms will include dscalars automatically, and the non-exact forms have derivative symbols in dforms,

dforms

The quantity Q is now a quaternion-valued 1-form field with the 2-form derivative,

d[Q]

and the AVF self-product,

QQ=Q**Q

The derivative of the previously defined variable qQ now gives the quaternion 2-form,

collect[d[qQ]]

In field theories, the AVF 2-form field F is important,

F=collect[d[Q]+QQ/2]

where the coefficients have the structure of Maurer-Cartan forms for the quaternion algebra,

coeffs[%]

and the quaternion-valued “curvature” 2-form satisfies the 3-form Bianchi identity,

d[F]+Q**(F/2)-(F/2)**Q

Similar AVF structures can be defined for other associative algebras (such as the geometric Clifford algebras, which include H), and for non-associative algebras (e.g., Lie or supersymmetric graded Lie algebras).

The derivative operator can also be applied to a list of AVFs.

d[{q**(OverBar[q]),QQ}]

III.b.5. Ordinary differential forms

Any ordinary differential form expression can be input simply by omitting the algebra elements. Absent elements default to the identity element of the algebra, which only appears with collect; e.g.,

f=((Subscript[x, 1])(Subscript[ω, 2])⋀(Subscript[dx, 2])+(Subscript[x, 0])(Subscript[dω, 3]))**((Subscript[ω, 3])+(Subscript[ω, 2]))

collect[f]

df=d[f]

Since ordinary differential forms are treated as a trivial algebra, all AVF commands will work equally well in either case.

III.b.6. factor and expand

Any member of forms or dforms can be factored out to the left of an AVF by the following command, where all terms containing the basis form will be factored.

fac=factor[(Subscript[dω, 3]),df]

and so the original df can be recovered by using expand on the next expression,

(df/.(Subscript[dω, 3])->0)+(Subscript[dω, 3])⋀fac

expand[%]

The AVF command expand is analogous to Mathematica's Expand, except that it also expands wedge products, and so allows arbitrary replacements within them at all levels of an AVF expression. Note that the wedge symbol has the usual meaning of exterior product between basis forms, but is neither recognized nor used as an operator.

Q⋀QQ

%/.(Subscript[ω, 2])->((Subscript[dx, 1])+(Subscript[dx, 3]))

expand[%]

III.b.7. Vector contraction

A vector in AVF is a list of scalar variables with the same length as the forms list. The list represents the components of the vector in the dual basis to forms. The components will be constants, unless they are chosen from the scalars list, or are input as specified or unspecified functions of scalars. Define two independent vectors, V1 and V2,  with symbols adapted to the forms list:

forms

V1={(Subscript[W1, 0]),(Subscript[W1, 1]),(Subscript[W1, 2]),(Subscript[W1, 3]),(Subscript[X1, 0]),(Subscript[X1, 1]),(Subscript[X1, 2]),(Subscript[X1, 3])};
V2={(Subscript[W2, 0]),(Subscript[W2, 1]),(Subscript[W2, 2]),(Subscript[W2, 3]),(Subscript[X2, 0]),(Subscript[X2, 1]),(Subscript[X2, 2]),(Subscript[X2, 3])};

Vector contractions are given by the SmallCircle infix operator, typed as esc-sc-esc; i.e., vector ∘ AVF . Contraction can also be applied to a list of AVFs, and multiple contractions can be performed together. On the list of basis 1-forms, it simply returns the vector itself;

V1∘forms

V1∘{QQ,d[q]}

V1∘V2∘QQ

collect[%]

These vectors are constant,

d[V1]

but the components can be input as functions of scalars,

V1={(Subscript[W1, 0])[(Subscript[x, 0])],(Subscript[W1, 1])[(Subscript[x, 1])],(Subscript[W1, 2])[(Subscript[x, 2])],(Subscript[W1, 3])[(Subscript[x, 3])],(Subscript[X1, 0]),(Subscript[X1, 1]),(Subscript[X1, 2]),(Subscript[X1, 3])}

d[V1]

V1∘QQ

collect[d[%]]

or even be entered into scalars themselves to make them independent fields with their own derivatives,

makescalars[Join[scalars,V2]]

forms

V2∘QQ

collect[d[%]]

Contraction on this last expression would require a longer vector to encompass the additional independent basis 1-forms created by extending the scalars list. It would also require defining contractions on the members of dforms.

The makescalars command just above illustrates a general feature of AVF; i.e., that the fundamental lists scalars, forms, elements and algebra can be changed at any time by executing the respective make command. For instance, the vector components can be deleted from scalars by

makescalars[Complement[scalars,V2]]

forms

This doesn't delete them from memory,

V2

but they do revert to being constant parameters in AVF.

d[V2]

III.b.8. Matrix representations and operations

Sometimes it is useful to have a matrix representation of the algebra elements, even though the program never requires it. For example, the quaternion elements can be represented by Pauli-type matrices, which have the same multiplication table as H,

mtx[]

for instance,

(Subscript[Σ, 0])={{1,0},{0,1}};
(Subscript[Σ, 1])={{0,I},{I,0}};
(Subscript[Σ, 2])={{0,-1},{1,0}};(Subscript[Σ, 3])={{I,0},{0,-I}};

((Subscript[Σ, 1])).(Subscript[Σ, 1])==-(Subscript[Σ, 0])
((Subscript[Σ, 1])).(Subscript[Σ, 2])==(Subscript[Σ, 3])

and since the indices of these matrices agree with the (Subscript[σ, i]), any quaternion expression or list can be converted to a matrix by replacement of the symbol kernel; i.e.,

elements

elements/.σ->Σ

q

mq=q/.σ->Σ

mtx[%]

QQ

mQQ=QQ/.σ->Σ

mtx[%]

When the AVF includes a suppressed identity element, it is necessary to make it explicit by using collect before conversion; e.g.,

q**q

collect[q**q]/.σ->Σ

Since the matrix mq has only scalar components, Mathematica's matrix product gives the same result,

Expand[mq.mq]

III.b.9. AVF matrices

The AVF program includes an infix operator, denoted CircleTimes and typed by esc-c*-esc}, that can be used when the matrix elements are complete AVFs, such as quaternion-valued p-forms. For instance, the above matrix mQQ can be calculated using the matrix form of Q having 1-form elements,

mQ=Q/.σ->Σ

mtx[mQ⊗mQ]

Using Mathematica's BlockMatrix[] command, the matrices mq and mQ can be combined to give a graded matrix, GM, with diagonal blocks of even grade (0-forms) and off-diagonal blocks of odd grade (1-forms). Such matrices generate supergroups and their commutators generate the associated Lie superalgebras.

<< LinearAlgebra`MatrixManipulation`;

For brevity, the identity elements are deleted in this example,

GM=BlockMatrix[{{mq,mQ},{mQ,-mq}}]/.{(Subscript[x, 0])->0,(Subscript[ω, 0])->0};
mtx[GM]

The product is a graded matrix of the same general type; i.e., diagonal blocks of even grades in the Grassmann algebra and off-diagonal blocks of odd grade:

mtx[GM⊗GM]

A graded matrix equivalent to GM can be expressed more concisely with a 2×2 matrix of the quaternion-valued AVFs,

QM={{q,Q},{Q,-q}}/.{(Subscript[x, 0])->0,(Subscript[ω, 0])->0};mtx[QM]

mtx[BlockMatrix[QM/.σ->Σ]]

and it can be multiplied directly with the CircleTimes operator, giving essentially the same result for the matrix product, but in a representation-independent and slightly more compact form,

QM2=collect[QM⊗QM];
mtx[QM2]

Note that as a matrix QM is symmetric, but its expanded form GM is unsymmetric (anti-Hermitian), so matrix operations involving transposes and conjugates must be defined and handled differently.

Since d[] maps recursively onto AVF lists, it also extends to AVF matrices,

collect[d[QM2]]

d[%]

and the same is true for contractions,

collect[V2∘QM2]

For a quaternion-valued, even-odd, column vector,

QV={{(OverBar[q])},{Q}}/.{(Subscript[x, 0])->0,(Subscript[ω, 0])->0}

the QM⊗QV product returns an even-odd column vector

QM⊗QV

and finally, a single, quaternion-valued, even-grade, p-form,

collect[Transpose[QV]⊗%]

d[%]

d[%]

III.b.10. Clean up

makeclear[]

Remove["Global`*"]

ModifiedGlobalVariables

III.c. More general algebras

This is taken from the file Miscellany_Demo.nb

III.c.1. General comments

This section contains a miscellaneous collection of AVF calculations. Most of the operations used are introduced and explained in other sections. The first example treats the Dirac equation with quaternion matrices. The rest involve a variety of non-associative algebras.  Some of these exercises were suggested by the fine review book on non-associative algebras by Susumu Okubo:

Introduction to Octonion and Other Non-Associative Algebras in Physics, S. Okubo, Montroll Memorial Lecture Series in Mathematical Physics: 2, Cambridge University Press, 1995

III.c.2. Quaternions

Setting up the quaternion algebra, H

makeelements[{(Subscript[σ, 0]),(Subscript[σ, 1]),(Subscript[σ, 2]),(Subscript[σ, 3])}]

H={{(Subscript[σ, 0]),(Subscript[σ, 1]),(Subscript[σ, 2]),(Subscript[σ, 3])},{(Subscript[σ, 1]),-(Subscript[σ, 0]),(Subscript[σ, 3]),-(Subscript[σ, 2])},{(Subscript[σ, 2]),-(Subscript[σ, 3]),-(Subscript[σ, 0]),(Subscript[σ, 1])},{(Subscript[σ, 3]),(Subscript[σ, 2]),-(Subscript[σ, 1]),-(Subscript[σ, 0])}};

makealgebra[H]

mtx[]

with three independent quaternions,

q1=Sum[(Subscript[X, i])(Subscript[σ, i]),{i,0,3}]

q2=q1/.X->Y

q3=q1/.X->Z

III.c.3. The Dirac equation using quaternions

A familiar 2×2 representation of Dirac matrices can be expressed by the quaternion elements, σ ;

(Subscript[Γ, 0])={{0, (Subscript[σ, 2])},{ (Subscript[σ, 2]),0}};
(Subscript[Γ, 1])=I{{0,(Subscript[σ, 1])},{(Subscript[σ, 1]),0}};
(Subscript[Γ, 2])={{(Subscript[σ, 0]),0},{0,-(Subscript[σ, 0])}};
(Subscript[Γ, 3])=I{{0,(Subscript[σ, 3])},{(Subscript[σ, 3]),0}};

The operator CircleTimes multiplies matrices of AVF expressions, and for the squares of the Γ's gives the Lorentz signature, {-1,1,1,1}; i.e.,

-(Subscript[Γ, 0])⊗(Subscript[Γ, 0])==(Subscript[Γ, 1])⊗(Subscript[Γ, 1])==(Subscript[Γ, 2])⊗(Subscript[Γ, 2])==(Subscript[Γ, 3])⊗(Subscript[Γ, 3])=={{1,0},{0,1}}

where, as usual, the identity element (Subscript[σ, 0 ])is suppressed in AVF results, but can be recovered using collect. They all anti-commute among themselves, and also with (Subscript[Γ, 5]),

(Subscript[Γ, 5])=(Subscript[Γ, 0])⊗(Subscript[Γ, 1])⊗(Subscript[Γ, 2])⊗(Subscript[Γ, 3])

collect[%]

(Subscript[Γ, 5])⊗(Subscript[Γ, 5])

Make the coefficients of q1 and q2 into scalar variables,

makescalars[Join[coeffs[q1],coeffs[q2]]]

and define a quaternion-valued 2-vector qV to represent the Dirac field,

qV={{q1},{q2}};
mtx[qV]

Introducing a new set of scalars called coords will automatically construct partial derivative expansions for the exterior derivatives of q1 and q2, and these expressions are incorporated in drules by the makecoords command, as is described more fully in the sectioin on LieDerivative below.

makecoords[{t,x,y,z}]

scalars

Thus,

d[q1]

collect[applydrules[%]]

or equivalently, using the compound operator, da[arg] = applydrules[d[arg]],

collect[da[q1]]

A particular partial derivative of an AVF expression, or list, is given either by the coordinate name appearing as a subscript on D,

(Subscript[D, x])[qV]

or by the position of the coordinate variable in the coords list,

(Subscript[D, 1])[qV]

The Dirac equation can then be written as the quaternion-valued 2-vector equation,

dirac=collect[(∑_(i=0)^3)I (Subscript[Γ, i])⊗(Subscript[D, i+1])[qV]+I m (Subscript[Γ, 5])⊗qV]

and applying the same operator a second time returns the Klein-Gordon equation for each quaternion component,

KG=collect[(∑_(i=0)^3)I (Subscript[Γ, i])⊗(Subscript[D, i+1])[dirac]+I m (Subscript[Γ, 5])⊗ dirac]

III.c.4. General algebras

The algebra table may contain unspecified parameters in the products. For example, the procedure generic[] constructs a completely general algebra for elements using structure parameters (Subscript[sy, i,j,k]) which are symmetric in the {j,k} indices and (Subscript[sk, i,j,k])which are skew-symmetric in {j,k}. The indices {i,j,k} start at (0,1,1) with 0 denoting the "identity" element. Only the independent parameters with j ≤ k are defined. The algebra can be established by:

makealgebra[generic[]]

and so with the present elements constructs the lists symm and skew and the generic algebra

(Subscript[σ, j])(Subscript[σ, k]) = (Underscript[Σ, i])  ( (Subscript[sy, i,j,k])+(Subscript[sk, i,j,k]))(Subscript[σ, i])

symm

skew

mtx[]

Either Expand or collect can be used to obtain appropriate cancellations here;

commutator=Expand[(Subscript[σ, 1])**(Subscript[σ, 2])-(Subscript[σ, 2])**(Subscript[σ, 1])]

anticommutator=Expand[(Subscript[σ, 1])**(Subscript[σ, 2])+(Subscript[σ, 2])**(Subscript[σ, 1])]

The arbitrary algebra is non-associative,

collect[((Subscript[σ, 1])**(Subscript[σ, 2]))**(Subscript[σ, 1])-(Subscript[σ, 1])**((Subscript[σ, 2])**(Subscript[σ, 1]))]

The generic[] product of q1 and q2,

collect[q1**q2]

One application of generic[] is simply to solve for the structure constants of a given algebra table. The subroutine, structure[], gives the solution:

structure[arg_]:=Block[{diff,eqns},
makealgebra[generic[]];
diff=collect[arg-algebra];
eqns=setzero[Flatten[Map[coeffs,Flatten[diff]]]];Flatten[Solve[eqns,Join[skew,symm]]]
];

For H,

constants=structure[H]

The quaternion product can be recovered by,

collect[q1**q2/.constants]

and H is restored as the active algebra by replacing the constants in the current generic algebra,

makealgebra[algebra/.constants]

mtx[]

The generic algebra may not be of much use beyond demonstrating generality; i.e., one can use p-form AVFs defined over: Clifford, Lie, and Jordan algebras, other non-associative(e.g., octonion) algebras, gauge group algebras, and superalgebras.

Clear[symm,skew]

III.c.5. Derived algebras

The non-associative derived algebras, (SuperMinus[A])  and  (SuperPlus[A]), for AVFs may also be defined: (see Okubo, p.19). In Mathematica, they can be easily input using the following two infix operators:

The commutator function for AVFs, typed by esc- c- -esc;

CircleMinus[arg1_,arg2_]:=arg1**(arg2/2)-(arg2/2)**arg1

d[q1]⊖d[q2]

The anti-commutator function for AVFs, typed by esc- c+ -esc;

CirclePlus[arg1_,arg2_]:=arg1**(arg2/2)+(arg2/2)**arg1

d[q1]⊕d[q2]

For an associative underlying algebra, such as H , operator ⊖ defines a Lie-algebra, (SuperMinus[A]), over AVFs with the Jacobi identity,

d[q1]⊖(d[q2]⊖q3)+d[q2]⊖(q3⊖d[q1])+q3⊖(d[q1]⊖d[q2])

and the ⊕ operator gives a special Jordan algebra, (SuperPlus[A]), satisfying the Jordan identity,

((d[q1]**d[q1])⊕q3)⊕d[q1]-(d[q1]**d[q1])⊕(q3⊕d[q1])

The following joint identity also holds in the underlying associative case, as well as in some special non-associative cases,

d[q1]⊖(d[q2]⊕q3)-(d[q1]⊖d[q2])⊕q3-d[q2]⊕(d[q1]⊖q3)

and that expression implies the cyclic super-Jacobi identity,

d[q1]⊖(d[q2]⊕q3)+d[q2]⊖(q3⊕d[q1])+q3⊖(d[q1]⊕d[q2])

These operations are not supplied in AVF as reserved functions, but can be introduced as above.

III.c.6. Generating a Lie algebra

We start with the associative Clifford algebra, signature={-1,1,1,1}, but with the algebra table truncated to grade(2) products;

makeclifford[{-1,1,1,1},2]

elements

The full elements list must be retained, since they all appear in algebra, though products of grades higher than grade(2) cannot be performed.

mtx[]

The table of commutator products for the truncated elements is given by

liealg=(algebra-Transpose[algebra])/2;
mtx[liealg]

and this closed 10-dimensional Lie algebra, isomorphic to so(3,2), can be the established algebra.

Some remarks are necessary here:

The Lie algebras are among those that do not include an identity element. However, identity serves as an essential placeholder in many AVF calculations, so the fundamental list elements must always include an initial member to act as the identity element. If the algebra does not include an identity, it must be supplied as the first member of elements and to preserve its "unital" action, the top row and left column of algebra must equal elements (or a truncated portion thereof).

Since this is essential for correct operation of the program, the makealgebra[] command will always modify any multiplication table (supplied as its argument) so that this requirement is met; i.e., the top row and left column will be changed to elements before being assigned to algebra. If the algebra includes the identity in the first member of elements, this actually leaves it unchanged. If there is no identity element, a symbol for it may be entered as the second (optional) argument of makealgebra to become a new element in the first position of elements. The multiplication table entered in the mandatory first argument will appear unchanged, except for having the new elements list prepended as the first row and column of algebra. Products with the spurious identity will not conform to the algebra, but products of all other elements (which do belong to the algebra) will be unchanged. The new row and column can be considered just as convenient headers for the others.

For example,

makealgebra[liealg,e]

mtx[]

and the full list of elements is still retained,

elements

Basic AVF multiplication, ** , now gives the non-associative Lie product for all Lie-algebra-valued forms, which in standard notation is written as a bracket. The CAV defined 1-form, (OverHat[ω]) , becomes a Lie-algebra-valued gauge potential,

(OverHat[ω])

where the expansion of the Lie bracket [(OverHat[ω]) , (OverHat[ω])] is given directly by,

collect[(OverHat[ω])**(OverHat[ω])]

All the Jacobi identities of the structure constants of this Lie algebra are involved in the triple self-product of (OverHat[ω]) , regardless of parentheses;

((OverHat[ω])**(OverHat[ω]))**(OverHat[ω])==(OverHat[ω])**((OverHat[ω])**(OverHat[ω]))==(OverHat[ω])**(OverHat[ω])**(OverHat[ω])==0

The AVF form of the Yang-Mills equation includes the grades(0,1,2) curvature fields, F, for the gauge potential, (OverHat[ω]) ,

F=collect[d[(OverHat[ω])]+(OverHat[ω])**(OverHat[ω])/2]

In the Clifford algebra, the curvature identity is expressed by,

d[F]+(OverHat[ω])**(F/2)-(F/2)**(OverHat[ω])

but in the Lie algebra, AVF 1-forms and 2-forms anti-commute and the Jacobi identities annul the triple (OverHat[ω]) product, so the curvature identity simplifies to,

d[F]+(OverHat[ω])**F==d[F]-F**(OverHat[ω])==0

III.c.7. The non-associative octonions algebra

Introduce a new elements list,

octonionbasis={(Subscript[e, 0]),(Subscript[e, 1]),(Subscript[e, 2]),(Subscript[e, 3]),(Subscript[e, 4]),(Subscript[e, 5]),(Subscript[e, 6]),(Subscript[e, 7])};

makeelements[octonionbasis]

A particular representation, (SuperPlus[C]), of the octonion multiplication table is:

octoniontable={
{(Subscript[e, 0]),(Subscript[e, 1]),(Subscript[e, 2]),(Subscript[e, 3]),(Subscript[e, 4]),(Subscript[e, 5]),(Subscript[e, 6]),(Subscript[e, 7])},
{(Subscript[e, 1]),-(Subscript[e, 0]),(Subscript[e, 4]),(Subscript[e, 7]),-(Subscript[e, 2]),(Subscript[e, 6]),-(Subscript[e, 5]),-(Subscript[e, 3])},
{(Subscript[e, 2]),-(Subscript[e, 4]),-(Subscript[e, 0]),(Subscript[e, 5]),(Subscript[e, 1]),-(Subscript[e, 3]),(Subscript[e, 7]),-(Subscript[e, 6])},
{(Subscript[e, 3]),-(Subscript[e, 7]),-(Subscript[e, 5]),-(Subscript[e, 0]),(Subscript[e, 6]),(Subscript[e, 2]),-(Subscript[e, 4]),(Subscript[e, 1])},
{(Subscript[e, 4]),(Subscript[e, 2]),-(Subscript[e, 1]),-(Subscript[e, 6]),-(Subscript[e, 0]),(Subscript[e, 7]),(Subscript[e, 3]),-(Subscript[e, 5])},
{(Subscript[e, 5]),-(Subscript[e, 6]),(Subscript[e, 3]),-(Subscript[e, 2]),-(Subscript[e, 7]),-(Subscript[e, 0]),(Subscript[e, 1]),(Subscript[e, 4])},
{(Subscript[e, 6]),(Subscript[e, 5]),-(Subscript[e, 7]),(Subscript[e, 4]),-(Subscript[e, 3]),-(Subscript[e, 1]),-(Subscript[e, 0]),(Subscript[e, 2])},
{(Subscript[e, 7]),(Subscript[e, 3]),(Subscript[e, 6]),-(Subscript[e, 1]),(Subscript[e, 5]),-(Subscript[e, 4]),-(Subscript[e, 2]),-(Subscript[e, 0])}
};

makealgebra[octoniontable]

mtx[]

The function associators[n] searches the algebra table for non-associative triple products and prints the first n it finds. If fewer than n are present, it prints Done and the number actually found, but in that case it could take a long time to search a high-dimension algebra.

associators[9]

The absence of the triple {(Subscript[e, 1]),(Subscript[e, 2]),(Subscript[e, 4])} implies that this is an associative quaternion subalgebra; i.e.,

((Subscript[e, 1])**(Subscript[e, 2]))**(Subscript[e, 4])-(Subscript[e, 1])**((Subscript[e, 2])**(Subscript[e, 4]))

Since {(Subscript[e, 1]),(Subscript[e, 2]),(Subscript[e, 3])} do not associate, the 0-forms {q1,q2,q3} introduced at the start as quaternions, become truncated octonions by σ -> e ,

o1=q1/.σ->e

o2=q2/.σ->e

o3=q3/.σ->e

and O1 will be an octonion-valued 1-form,

O1=o1/.X->ω

when makeforms is used,

makeforms[coeffs[O1]]

A special property of octonions guarantees that any two octonion 0-forms are associative; e.g.,

(o1**o2)**o1-o1**(o2**o1)

(o1**o2)**o2-o1**(o2**o2)

For three independent octonions, associativity is lost,

collect[(o1**o2)**o3-o1**(o2**o3)]

but the "flexible" property is demonstrated by the opposite signs of the next expression,

collect[(o3**o2)**o1-o3**(o2**o1)]

The above associative property does not hold in general for octonion-valued 1-forms, which are not even triply power associative,

(O1**O1)**O1-O1**(O1**O1)

collect[(O1**O1)**o1-O1**(O1**o1)]

but with no exterior product involved,

(o1**O1)**o1-o1**(O1**o1)

III.c.8. The exceptional Jordan algebra

All the finite Jordan algebras with one exception can be obtained from the symmetric derived algebras using ⊕ with associative underlying algebras. As mentioned in Okubo's book (p.81), octonion-valued matrices provide a representation for the single 27-dim. exceptional Jordan algebra. For brevity, we shall use the truncated octonion triplet {o1,o2,o3}, their conjugates, and 3 additional diagonal elements, to write a reduced 15-dim. example,

(OverBar[o1])=-o1/.(Subscript[X, 0])->-(Subscript[X, 0]);
(OverBar[o2])=-o2/.(Subscript[Y, 0])->-(Subscript[Y, 0]);
(OverBar[o3])=-o3/.(Subscript[Z, 0])->-(Subscript[Z, 0])

The matrix J1 then represents a truncated element of the exceptional Jordan algebra,

J1={{(Subscript[a, 1])(Subscript[e, 0]),o1,o2},{(OverBar[o1]),(Subscript[a, 2])(Subscript[e, 0]),o3},{(OverBar[o2]),(OverBar[o3]),(Subscript[a, 3])(Subscript[e, 0])}}

mtx[%]

An independent matrix of the same form is given by,

J2=J1/.{a->b,X->U,Y->V,Z->W};
mtx[J2]

and the symmetrized Jordan product ⊕ can be modified for matrix arguments to,

CirclePlus[arg1_,arg2_]:=arg1⊗(arg2/2)+(arg2/2)⊗arg1

For example,

J3=collect[J1⊕J1]

Using matrix multiplication, the Jordan identity as introduced for the derived algebra (SuperPlus[A]) becomes,

((J1⊗J1)⊕J2)⊕J1-(J1⊗J1)⊕(J2⊕J1)

or equivalently, using J3 = J1⊕J1, just calculated,

(J3⊕J2)⊕J1-J3⊕(J2⊕J1)

Executing the next statement confirms that the unsymmetrized matrix product is not associative.

collect[(J3⊗J2)⊗J1-J3⊗(J2⊗J1)]

III.c.9. Clean up

makeclear[]

Remove["Global`*"]

ModifiedGlobalVariables

IV. Advanced computations

IV.a. Orthonormal frames and Hodge star operations

This is taken from the file HodgeStar_Demo.nb.

IV.a.1. General comments

A set of up to 6 basis forms (which may include a subset of the existing forms) can be designated as an orthonormal frame by the command makeframe[list]. The argument is just a list of form symbols, except that the symbol for any frame form with negative signature must be preceded by a minus sign.

The basis forms may be input in any order, but will be re-arranged into canonical order (and the signs stripped off) before being assigned to the reserved variable frame. The signs are saved in the reserved variable signature. Any new symbols are added to forms, and the frame forms will be moved to the front of the forms list.  Existing drules are left unchanged, so any new frame forms (even exact ones, if new) will require them.

IV.a.2. Cartesian orthogonal frame

The first example sets up for Euclidean 3-space using Cartesian coordinates and the associated natural orthogonal basis. The makecoords command is described fully at the end of the Lie differentiation section.

makecoords[{x,y,z}]

dscalars

Using the argument dscalars in the next statement avoids introducing new basis forms, and obviates any need for drules.

makeframe[dscalars]

signature

scalars

forms

dforms

drules

The makeframe command implements the Hodge star operation for frame. Mathematica does not include an appropriate prefix operator for this, so it is written hs[arg], where arg is any AVF, or list of AVF's.

vol=hs[1]
hs[vol]

f=Y[depend]
hs[f]

A=A1[depend]dx+A2[depend]dy+A3[depend]dz
hs[A]

A co-derivative operator, δ , is also defined:  δ[arg] = hs[hs[1]] hs[d[hs[arg]]]. No universally accepted convention exists for the overall sign of Hodge star operations; the use of the factor hs[hs[1]] in δ generally gives results consistent with signature.

df=d[f]

delsquaredf=δ[df]

curlgradf=δ[hs[df]]

divA=δ[A]

curlA=Collect[hs[d[A]],frame]

divcurlA=δ[curlA]

Note the use of da[] in the next statement which (with appropriate drules, when necessary) ensures that the result of that derivative is expressed in terms of frame.

delsquaredA= Collect[da[δ[A]]-δ[d[A]],frame]

IV.a.3. A non-Cartesian orthogonal frame

Except in flat space with a Cartesian frame, the orthonormal frame forms will have unspecified exterior derivatives which need drules to be expressed back in terms of frame (unless they have been selected from the dscalars list, as was done above). 

Furthermore, if the frame forms are not in dscalars, the transformations dcoords->frame must be provided in drules, so that exterior differentiation of all frame forms and scalar functions of the coordinates can be accomplished using the da[] operator. All calculations are performed in the orthonormal frame. However, input expressions may be expressed in the coordinate frame, and the orthonormal output is convertible, as shown in the examples.

The example of spherical coordinates shows what is required.

makecoords[{r,θ,ϕ}]

makeframe[{(OverHat[r]),(OverHat[θ]),(OverHat[ϕ])}]

signature

scalars

dscalars

forms

dforms

Now the framedrules will be established:

tocoords={frame[[1]]->dr,frame[[2]]->r dθ,frame[[3]]->r Sin[θ] dϕ}

The shortcut for this is:

tocoords = Thread[frame -> {dr, r dθ, r Sin[θ] dϕ}]

The AVF command prune[list,expr] is useful to select the relevant part of a longer list. In this case, it returns a list containing the members of dscalars that appear in tocoords.

prunedlist=prune[dscalars,tocoords]

toframe=Flatten[Solve[(tocoords/.Rule->Equal),prunedlist]]

The next command constructs the appropriate frame derivatives to be used in framedrules.

dframe=expand[d[frame/.tocoords]/.toframe]

framedrules=Thread[dforms->dframe]

And now these  are established as drules,

makedrules[Join[framedrules,toframe]]

Of course, it would be convenient to collect these preparation commands into a subroutine. Problems may arise from using Solve to get the inverse transformation and the possible need at times for Simplify. A better approach for other cases is to copy the relevant parts of this program into a new Notebook and modify them as necessary.

vol=hs[1]
expand[vol/.tocoords]

Using Hodge, an inner product, called dot, can be defined for any two p-forms (of the same degree). For the frame forms themselves, it exhibits the orthonormality;

dot[(OverHat[ϕ]),(OverHat[ϕ])]
dot[(OverHat[r]),(OverHat[θ])]

and for the coordinate basis it will give the covariant metric,

mtx[Inverse[Table[dot[dscalars[[j]],dscalars[[k]]],{j,coordsdim},{k,coordsdim}]]]

f=Y[depend]
hs[f]

df=d[f]

da[f]

divdf=δ[df]

curldf=δ[hs[df]]

A=A1[depend] (OverHat[r])+A2[depend] (OverHat[θ])+A3[depend] (OverHat[ϕ])
hs[A]

B=B1[depend] dr+B2[depend] dθ+B3[depend] dϕ
hs[B]
expand[%/.tocoords]

The Hodge operator hs[] also can be applied to AVF arrays.

hs[{{df,A},{B,df}}]

divA=δ[A]

curlA=Collect[hs[d[A]],frame]

curlB=Collect[expand[hs[d[B]]/.tocoords],prunedlist]

divcurlA=δ[curlA]
divcurlB=δ[curlB]

delsquaredA=Collect[da[δ[A]]-δ[d[A]],frame]

Some inner products calculated by dot, where the second and third demonstrate its symmetry;

dot[B,B]

dot[A,df]

dot[df,A]

IV.a.4. Clean up

makeclear[]

Remove["Global`*"]

ModifiedGlobalVariables

IV.b. Implementing Clifford algebras

This is taken from the file CAV_Demo.nb.

IV.b.1. Making a Clifford algebra

A Clifford algebra representation of quaternions will be used as the first example. The argument of makeclifford[arg] is the desired signature list; i.e., for quaternions, {-1,-1}.

makeclifford[{-1,-1}]

The dimension is given by cadim, and the elements list has length eldim=2^cadim.

dforms

cadim

elements

eldim

The first element, (Subscript[γ, 0]), is the identity; (Subscript[γ, 1])and (Subscript[γ, 2])are the orthonormal generators, both with negative signature; and the complete product element here is, (Subscript[γ, 3])= (Subscript[γ, 1])(Subscript[γ, 2]), which also has a negative square. The command mtx[] outputs the algebra table in MatrixForm.

mtx[]

As described in the Introduction section, all the following graded symbol lists and CAV quantites are constructed:

gammas

thetas

omegas

forms

(OverHat[θ])

(OverHat[ω])

The generalized torsion and curvature 2-forms are defined by the CAV expressions;

            (OverHat[Θ]) = d[(OverHat[θ])]+(1/2)((OverHat[ω])**(OverHat[θ])+(OverHat[θ])**(OverHat[ω]))
          
            (OverHat[Ω]) = d[(OverHat[ω])]+(1/2)((OverHat[ω])**(OverHat[ω])) 

and can be evaluated for any assigned { (OverHat[θ]) , (OverHat[ω]) } with the functions;

maketorsion[]

makecurvature[]

The identity element, (Subscript[γ, 0]), appears explicitly because the functions use the collect command to group the expressions into coefficients of elements. These expressions are assigned to the variable names, (OverHat[Θ]) and (OverHat[Ω]) . They satisfy the general differential identities given in the Introduction section.

curvatureidentity[]

torsionidentity[]

A general 0-form quaternion with constant components can be constructed by

(OverHat[q])=(OverHat[ω])/.ω->q

and the components become scalar fields when established as scalars,

makescalars[coeffs[(OverHat[q])]]

collect[(OverHat[q])**d[(OverHat[q])]]

d[%]

IV.b.2. Clifford algebra for a spacetime metric

Using a Lorentzian 4-space signature:

makeclifford[{-1,1,1,1}]

elements

forms

mtx[]

The general values of (OverHat[θ]) and (OverHat[ω]) , including all grades, are assigned by the makeclifford command.

(OverHat[θ])

(OverHat[ω])

The CAV 2-forms of generalized torsion  (OverHat[Θ])  and curvature  (OverHat[Ω])  can be constructed using those values:

maketorsion[]

makecurvature[]

and again the differential identities can be verified.

torsionidentity[]

curvatureidentity[]

The following two commands solve for all dforms by annulling first torsion and then curvature,

zt=zerotorsion[]

zc=zerocurvature[]

and this establishes the solution as drules,

makedrules[Join[zt,zc]];

applydrules[{(OverHat[Θ]),(OverHat[Ω])}]

These drules are shown to represent valid Maurer-Cartan relations of a closed Lie algebra by the next result. The inner application da[forms] just returns dforms and then replaces them by the rhs of the drules, but the second outer da[] differentiates each of those expressions, substitutes back all the drules into them, and expands the resulting 3-forms. For 32 such lengthy expressions, this takes some time.

da[da[forms]]

IV.b.3. A Riemannian geometry problem

For the following problem of spherically symmetric spacetimes, we use a truncated Clifford algebra. The algebra can be truncated since Riemannian geometry only requires doing products up to grade[2];

makeclifford[{-1,1,1,1},2]

mtx[]

We want the CAV co-frame to be grade[1] and the CAV connection to be grade[2],

(OverHat[θ])=grade[1,(OverHat[θ])]
(OverHat[ω])=grade[2,(OverHat[ω])]

Introduce a set of scalar variables for coordinates,

makescalars[{t,r,θ,ϕ}]

dscalars

The input required is to give coordinate expressions for the orthonormal frame forms. We specify r as the curvature coordinate in the line element,

-((T[r])^2)(dt^2)+ ((R[r])^2)(dr^2)+ (r^2)((dθ)^2)+ (r^2) ((Sin[θ])^2)((dϕ)^2);

tocoords=Thread[coeffs[(OverHat[θ])]->{T[r]dt,R[r]dr,r dθ,r Sin[θ] dϕ}]

so in the coordinate basis, (OverHat[θ]) becomes,

(OverHat[θ])=(OverHat[θ])/.tocoords

At this point, many Clifford algebra approaches define new variable elements by,

Thread[Coefficient[%,dscalars]->{(Subscript[γ, t]),(Subscript[γ, r]),(Subscript[γ, θ]),(Subscript[γ, ϕ])}]

giving an equivalent expression for (OverHat[θ]) ,

(OverHat[θ])/.%

The AVF package, however, is based throughout on constant algebra elements with any spatial dependence residing in their p-form coefficients.

IV.b.4. Deriving the field equations

For demonstration, the steps will be presented in detail. Generally most of it can be automated, as shown in the Riemann section below.

To find the connection we can expand its components on the frame 1-forms, using a non-standard matrix of 24 rotation coefficients. Either the coordinate, or the orthonormal, basis 1-forms can be used. Here we use the coordinate 1-forms, which is a bit more straightforward since it doesn't require defining drules.

MK=Table[(Subscript[K, i,j]),{i,4},{j,6}]

onframe=Thread[coeffs[(OverHat[ω])]->dscalars.MK]

(OverHat[ω])=(OverHat[ω])/.onframe

With this  (OverHat[ω])  the torsion becomes,

tor=maketorsion[]

The independent 2-forms are given by

twobasis={dr⋀dθ,dr⋀dϕ,dr⋀dt,dt⋀dθ,dt⋀dϕ,dθ⋀dϕ}

and the List multiplication statement Outer[] constructs the 24 independent  (gammas)*(twobasis) components,

comps=Flatten[Outer[Times,prune[elements,tor],twobasis]]

all coefficients of which must vanish for zero torsion.

terms=Coefficient[tor,comps]

The setzero command simply equates its list of arguments to zero giving equations for Solve,

eqns=setzero[terms]

soln=Flatten[Solve[%,Flatten[MK]]]

and the final result for (OverHat[ω]) is,

(OverHat[ω])=(OverHat[ω])/.soln

To verify the solution, this (OverHat[ω]) can be used to calculate the torsion again,

maketorsion[]

Constructing the CAV curvature 2-form from this  (OverHat[ω]) ,

makecurvature[]

which shows only (Subscript[R, i,j,i,j]) components.

The CAV grade[3] 3-form, (OverHat[G]) , is the differential form expression of the Einstein tensor,

(OverHat[G])=collect[Simplify[makeeinstein[]]]

Mathematica could be asked to DSolve the field equations (OverHat[G ])= 0 but just for demonstration,

Schwarzschild={R->Function[r,1/(Sqrt[1-2 m/r])],T->Function[r,(Sqrt[1-2 m/r])]}

Simplify[(OverHat[G])/.Schwarzschild]

One advantage of using orthonormal frame forms is that the built-in Hodge star operator becomes available. See section on Hodge duality below. Using the thetas list, and Mathematica's Thread to get the Clifford signature in, saves some typing,

Thread[signature  Take[thetas,{2,5}]]

makeframe[%]

signature

and frame is now at the front of forms:

forms

The Hodge star function is written hs[arg]; e.g.,

hs[1]

hs[%]

Using it on more general expressions requires setting up the inverse transformation and appropriate drules; i.e.,

toframe=Flatten[Solve[(tocoords/.Rule->Equal),dscalars]]

dframe=expand[d[frame/.tocoords]/.toframe]

dframerules=Thread[d[frame]->dframe]

makedrules[Join[dframerules,toframe]]

The HodgeStar algorithm includes a symmetric product for p-forms of the same degree, denoted dot[p1,p2], and with the above drules it can be used to give the covariant metric tensor in the coordinate basis, which simply confirms the set-up statements,

mtx[Inverse[Table[dot[dscalars[[i]],dscalars[[j]]],{i,4},{j,4}]]]

and the AVF Einstein 3-form can be converted to a dual 1-form, making its diagonal structure clearer,

collect[hs[(OverHat[G])]]

Simplify[%/.Schwarzschild]

The Hodge operators will return the wave equation for a function of coordinates in this metric. Defining the scalars as coords simply gives a better formatting for partial derivatives;

makecoords[scalars]

f=Ψ[depend]

d[f]

The scalar wave equation is,

δ[d[f]]

%/.Schwarzschild

and for flat spacetime,

%/.m->0

IV.b.5. Matrix representations for Clifford algebras

The CAV facilities include a makematrices[] command which constructs a set of matrices for the algebra elements (gammas) of the active Clifford algebra. They are denoted by upper case, Γ, with the same indices as the lower case elements, so that CAV expressions can be converted to matrix form by replacement of the symbol kernel. The matrices have dimension 2^p with p=cadim/2 for cadim even, and p=(cadim-1)/2 for cadim odd. For example, in the present case,

makematrices[]
(Subscript[Γ, 0])
(Subscript[Γ, 1])

(-(Subscript[Γ, 1])).(Subscript[Γ, 1])==((Subscript[Γ, 2])).(Subscript[Γ, 2])==((Subscript[Γ, 3])).(Subscript[Γ, 3])==((Subscript[Γ, 4])).(Subscript[Γ, 4])==(Subscript[Γ, 0])

(Subscript[Γ, 24])

(Subscript[γ, 24])/.γ->Γ

and for a CAV expression,

(OverHat[ω])

matω=%/.γ->Γ

Any AVF matrices can be multiplied by the CircleTimes infix operator,

matω⊗matω

which must give the same result as,

(OverHat[ω])**(OverHat[ω])/.γ->Γ

The makematrices[S] command will accept as an argument any invertible 2^p matrix S and will perform a similarity transformation (Subscript[Γ, i])-> S (Subscript[Γ, i])(S^(-1)) on the matrices returned by the function. For example,

Q={{0,a,0,0},{-b,0,0,0},{0,0,0,-c},{0,0,d,0}}

Inverse[Q]

makematrices[Q]
(Subscript[Γ, 1])
(Subscript[Γ, 4])

((Subscript[Γ, 1])).(Subscript[Γ, 1])
((Subscript[Γ, 1])).(Subscript[Γ, 4])+((Subscript[Γ, 4])).(Subscript[Γ, 1])

IV.b.6. The CliffordAlgebras folder

There is just one CAV variable available before using makeclifford[]. Named clifflist, it contains a list of the files in the "CliffordAlgebras" folder.

clifflist

Filenames begin with "Cl" followed by parentheses containing either 1 or 2 parameters, separated by commas. The first is just a string of plus and minus signs, representing the signature. The second parameter is optional. It specifies the highest grade of elements (gammas) for which the table of products (algebra) has been calculated. When omitted, the algebra table is constructed for all grades, assuming enough memory is available to accomplish it. In the clifflist given above, all the higher dimensional algebras (cadim>6) have been truncated to grade(2) for economy.

Note that the signature argument for the makeclifford[] function is not in the same format as the filenames. It is typed by giving the List of  ± 1 eigenvalues, as demonstrated in the above examples, followed by the grade restriction if desired. After converting that List to the appropriate filename, makeclifford[] looks for it in clifflist and if found, reads the file. For example, the quaternion filename Cl(- -) was found and that file was input, as were all the other examples used above.

If the filename of the required algebra is not included in the list, the algebra will be constructed, which will take some time for cadim>5. Any difference in the signature from those in clifflist will launch a new construction; i.e., unless all positions of  ± 1 match. The resulting algebra and associated quantities are output to a file in the CliffordAlgebras folder, and it's filename is added to clifflist.

IV.b.7. Clean up

makeclear[]

Remove["Global`*"]

ModifiedGlobalVariables

IV.c. Riemannian geometry with orthonormal frames

This is taken from the file Riemann.nb.

IV.c.1. General comments

Here we calculate the Ricci rotation coefficients, Cartan connection forms, and Riemann, Ricci and Weyl curvature components in an orthonormal co-frame, orthoframe = { (Subscript[θ, i])},  defined in terms of a set of coordinates. The space may have any dimension, and the orthonormal basis may have any signature.

The algorithm has syntax makeorthonormalcurvature[signature, tocoords, output]. If output=True, unsimplified results are printed as obtained; output=False specifies printing just a line of text describing what's being calculated at that time and a name for the results so they can be accessed at the end. Then select toortho, rotationcomps, ricciscalar, etc. for what is desired.

The Simplify commands at the very end of the program can be executed to see the results, which are presented as replacement rules obtained from Mathematica's Solve command. Unsimplified results can be displayed just by typing their names.

A new problem can be inserted by copying one of these problem cells and making the appropriate changes in signature, makecoords, tocoords and explicit. For speed and economy, it is generally preferable to leave any complicated metric functions unspecified, and use explicit to replace them at the end.

IV.c.2. Metric on a spheroid

signature={1,1};
makescalars[{}];
makecoords[{θ,ϕ}];
tocoords={(Subscript[θ, 1])->r0 (Sqrt[1-k Sin[θ]^2])dθ,(Subscript[θ, 2])->r0  Sin[θ]dϕ};
explicit={dummy->dummy};
makeorthonormalcurvature[signature,tocoords,True]

IV.c.3. Ruled surface taken from Eisenhart

signature={1,1};
makescalars[{u,v}];
makecoords[{u,v}];
tocoords={(Subscript[θ, 1])->du,(Subscript[θ, 2])->(Sqrt[(u-α[v])^2+β[v]^2])dv};
explicit={dummy->dummy};
makeorthonormalcurvature[signature,tocoords,True]

IV.c.4. Exterior Schwarzschild

signature={1,1,1,-1};
makescalars[{}];
makecoords[{r,θ,ϕ,t}]
tocoords={(Subscript[θ, 1])->dr/(Sqrt[1-2m/r]),(Subscript[θ, 2])->r  dθ,(Subscript[θ, 3])->r  Sin[θ]dϕ,(Subscript[θ, 4])->(Sqrt[1-2m/r])  dt};
explicit={dummy->dummy};
makeorthonormalcurvature[signature,tocoords,True]

IV.c.5. Interior Schwarzschild

signature={1,1,1,-1};
makescalars[{}];
makecoords[{r,θ,ϕ,t}]
tocoords={(Subscript[θ, 1])->dr/(Sqrt[1-2ρ0 r^2/3]),(Subscript[θ, 2])->r  dθ,(Subscript[θ, 3])->r  Sin[θ]dϕ,(Subscript[θ, 4])->(3(Sqrt[1-2ρ0 R^2/3])-(Sqrt[1-2ρ0 r^2/3]))  dt};
explicit={dummy->dummy};
makeorthonormalcurvature[signature,tocoords,True]

IV.c.6. Robertson-Walker (closed)

The flat and open models can be obtained by changing "explicit" at the end and re - simplifying with it.

signature={1,1,1,-1};
makescalars[{}];
makecoords[{r,θ,ϕ,t}];
tocoords=
	{(Subscript[θ, 1])->R[t]dr,(Subscript[θ, 2])->R[t]S[r] dθ,
		(Subscript[θ, 3])->R[t]S[r] Sin[θ]dϕ,(Subscript[θ, 4])->dt}
explicit={S->Function[r,Sin[r]]};
makeorthonormalcurvature[signature,tocoords,True]

IV.c.7. Kerr metric in spheroidal coordinates

signature={1,1,1,-1};
makescalars[{}];
makecoords[{x,y,ϕ,t}];
g=x^2+y^2;
Φ=(Sqrt[g/(h1[x]-h2[y])]);
radius=δ r0 Φ (Sqrt[h1[x] h2[y]]);
twist=2 δ  m x h2[y]/(h1[x]-h2[y]);
tocoords={(Subscript[θ, 1])->r0 (Sqrt[g/h1[x]])dx,(Subscript[θ, 2])->r0 (Sqrt[g/h2[y]])dy,(Subscript[θ, 3])->radius dϕ,(Subscript[θ, 4])->(dt-twist dϕ)/Φ};
explicit={h1->Function[x,1+x^2-2 m x/r0],h2->Function[y,1-y^2]};
makeorthonormalcurvature[signature,tocoords,True]

IV.c.8. Solution for a rigidly rotating fluid body

The following is a case in which Mathematica's Simplify command will not achieve a useful result in a reasonable time, unless the option Trig->False is included, and even then may take quite a while. This option is usually used inside the  calculation procedure to avoid wasting time, since simplifying with the default Trig option (i.e., True) can always be tried later. After waiting several minutes without success, one may want to Abort the calculation, and try something else. Simplify does succeed on the matter tensor components, as illustrated by the riccicomps command.

signature={1,1,1,-1};
makescalars[{}];
makecoords[{u,v,ϕ,t}];
g=Cos[2u]+Cosh[2v];
Φ=(Sqrt[κ g/(h1[u]-h2[v])]);
radius=2 r0 Φ (Sqrt[h1[u] h2[v]]);
twist=2κ r0(h1[u](Cosh[2v]-Cosh[2vA])+h2[v](Cos[2u]+Cosh[2vA]))/(h1[u]-h2[v]);
tocoords={(Subscript[θ, 1])->(Sqrt[g/h1[u]/μ0])du,(Subscript[θ, 2])->(Sqrt[g/h2[v]/μ0])dv,(Subscript[θ, 3])->radius dϕ,(Subscript[θ, 4])-> ( dt-twist dϕ)/Φ};
explicit={h1->Function[u,h0+e0 Cos[2 u]+(u+u0)Sin[2u]],h2->Function[v,h0-e0 Cosh[2v]+(v+v0)Sinh[2v]]};
makeorthonormalcurvature[signature,tocoords,True]

IV.c.9. P-P gravity wave

Null coordinates {u, v} defined by u = t - z, v = t + z.

signature={1,1,1,-1}
makescalars[{u,v,x,y}]
tocoords={(Subscript[θ, 1])->L[u](E^(β[u]))dx,(Subscript[θ, 2])->L[u](E^(-β[u]))dy,(Subscript[θ, 3])->dv/2-du/2,(Subscript[θ, 4])->dv/2+du/2}
metric=Expand[(((Subscript[θ, 1])^2)+((Subscript[θ, 2])^2)+((Subscript[θ, 3])^2)-((Subscript[θ, 4])^2))/.tocoords]
explicit={dummy->dummy};
makeorthonormalcurvature[signature,tocoords,True]

IV.c.10. Simplified results (for the P-P wave)

To display results execute the commands below. In complicated problems they may take a minute or two, even with the option Trig->False. Jose: To avoid a proliferation of new global symbols in the package, we have canverted them into the corresponding string names and wrapped them with the head ONFvalue (Ortho Normal Frame value).

res1=Simplify[ONFvalue["rotationcomps"]/.explicit]

res1=Simplify[ONFvalue["rotationcomps"]/.explicit]

res1=Simplify[ONFvalue["rotationcomps"]/.explicit,Trig->False]

res2=Simplify[ONFvalue["riemanncomps"]/.explicit]

res2=Simplify[ONFvalue["riemanncomps"]/.explicit,Trig->False]

res3=Simplify[ONFvalue["riccicomps"]/.explicit]

res3=Simplify[ONFvalue["riccicomps"]/.explicit,Trig->False]

res4=Simplify[ONFvalue["ricciscalar"]/.explicit]

res5=Simplify[ONFvalue["weylcomps"]/.explicit]

res5=Simplify[ONFvalue["weylcomps"]/.explicit,Trig->False]

In 4-dim. spacetimes, the timelike vector dual to (Subscript[θ, 4])is often a preferred vector field. The 3-space components of the acceleration, a , angular velocity, Ω , and rate-of-strain, S , of this timelike congruence are given in the "dyadics" list.

res6=Simplify[ONFvalue["dyadics"]/.res1]

res6=Simplify[ONFvalue["dyadics"]/.res1,Trig->False]

In the local rest-frame of this congruence, the components of the stress-energy tensor are given in the "stress" list. The symbols are: ρ = energy density, p = pressure, μ = ρ + 3 p ,  t = momentum density 3-vector, and M = T +p I, the anisotropic stress dyadic with TrM = 0. Units are  4π G/(c^2) = 1 .

res7=Simplify[ONFvalue["stress"]/.res3]

res7=Simplify[ONFvalue["stress"]/.res3,Trig->False]

Simplify[%]

The "electric", A , and "magnetic", B , components of the Weyl tensor in the same rest-frame are given in the "AB" list. Both A and B are symmetric, traceless, dyadics. The complex matrix, Q = A+i B.

res8=Simplify[ONFvalue["AB"]/.res5]

res8=Simplify[ONFvalue["AB"]/.res5,Trig->False]

ONFvalue["Q"]=ONFvalue["Q"]/.res8

lambdas=Simplify[Eigenvalues[ONFvalue["Q"]]]

Some special massaging is required for the lambdas of the Kerr solution.

kerrsimps1={(Sqrt[(1-((2 m x)/r0)+(x^2)) (1-(y^2))]) (Sqrt[((r0 ((x^2)+(y^2)))/(r0-2 m x+r0 (x^2)))]) (Sqrt[(((x^2)+(y^2))/(1-(y^2)))])->(x^2)+(y^2),(Sqrt[-(((r0-2 m x+r0 (x^2)) (-1+(y^2)))/r0)]) (Sqrt[((r0 ((x^2)+(y^2)))/(r0-2 m x+r0 (x^2)))]) (Sqrt[((-(x^2)+(y^2))/(-1+(y^2)))])->(x^2)+(y^2)};kerrsimps2={ (x^2)+(y^2)->(x-I y) (x+I y),(Sqrt[(m^2) (r0^6) (((x-I y))^14) (((x+I y))^8)])->m (r0^3) (((x-I y))^7) (((x+I y))^4)};
Simplify[lambdas/.kerrsimps1]//.kerrsimps2

IV.c.11. Clean up

makeclear[]

Remove["Global`*"]

ModifiedGlobalVariables

IV.d. Exterior differential systems and application to embedding

This is taken from the file CartanCharacters.nb.

IV.d.1. General comments

This program calculates any number of Cartan characters, and solution vectors, for a closed ideal of forms comprising pforms[1],..., pforms[maxnum], for a specified value of maxnum. The separate lists of forms must be input with those names. The calculation uses random integers to construct the solution vectors, since in very large ideals symbolic vectors lead to overwhelming algebraic complexity. The parameter maxrandom specifies the absolute value of the largest integer which can be randomly selected. Positive or negative values are also chosen at random. The smallest allowed value of maxrandom is 3; if not specified it defaults to 3. The rational numbers generated during the calculation may become very large, so it is best to keep maxrandom small at first, except for very simple ideals. Generally, the correct answer for the characters will be obtained in every run. The calculation should be repeated for a few trials, however, to guard against the occasional degeneracy. If the results from several trials are inconsistent, the value of maxrandom will have to be increased to avoid accidental degeneracies. Estabrook’s experience has been that with, say,  maxnum=9 or larger the correct characters are always immediately found in exterior systems that can be of very high dimension.

Different subsections below are independent computations. The list of Cartan characters is output as it is generated. The  commands in section "Detailed Results" at the very end of the program can then be executed after each calculation to display the results in detail (as explained there) and to repeat the calculation possibly with some minor changes.

A new problem can be inserted by copying one of these subsections and making the appropriate changes in the coordinates or basis forms, and in the input lists of forms of the ideal. There must be an input list for each degree of forms, up to the specified maxnum, even if just the null list, {}. Note: the characters program prunes the forms list to the basis 1-forms actually present in the ideal of pforms[1], pforms[2], etc. This subset is called idealforms, and the remainder are in the List called absentforms.  Absentforms reflect the existence of Cauchy Characteristic Vectors in the solutions.  The complete forms list and any previously defined drules for them are saved in the variables, saveforms and savedrules, which can be used to be restore their original values when characters is done.

The characters are returned as ((Subscript[s, 0]), (Subscript[s, 1, ]) (Subscript[s, 2]), ...,  (Subscript[s, n])}.   genus is the number of independent solution vectors found.   dimension is the number of idealforms.

IV.d.2. The KdV ideal with 3 2-forms in 5 dimensions

makescalars[{x,t,u,p,z}];
maxnum=5;
pforms[1]=pforms[3]=pforms[4]=pforms[5]={};
pforms[2]={du⋀dt-z dx⋀dt,dz⋀dx-p dx⋀dt,du⋀dx-dp⋀dt-12 u z dx⋀dt}
maxrandom=11;
characters

IV.d.3. A 2-dim string, embedded in flat 4-dim spacetime

The volume 2-form (Subscript[θ, 1])⋀(Subscript[θ, 2]) is the Cartan form for variation.  The subroutine embedsub constructs the necessary forms and bases.

embedsub[2,{-1,1,1,1}]
makescalars[{}];
maxnum=5;
pforms[3]=pforms[4]=pforms[5]={};
pforms[1]
pforms[2]=Join[embeddingforms,fieldforms[(Subscript[θ, 1])⋀(Subscript[θ, 2])]]
maxrandom=27;
characters

IV.d.4. The vacuum axi-stationary ideal with 6 2-forms in 6 dimensions

makescalars[{x,y,g,w,ϕ,ψ}];
maxnum=5;
pforms[1]=pforms[3]=pforms[4]=pforms[5]={};
pforms[2]={-(dg⋀dψ)-((dw⋀dϕ)/(ϕ^5)),((w dg⋀dw)/2)-(x^2) (ϕ^3) dg⋀dϕ+dw⋀dψ,((w dg⋀dx)/(2 x))+((dx⋀dψ)/x)-((dy⋀dϕ)/ϕ),-(1/2) w dg⋀dy-((x dx⋀dϕ)/ϕ)-dy⋀dψ,(ϕ^4) dg⋀dy-((dw⋀dx)/x),-x (ϕ^4) dg⋀dx-dw⋀dy}
maxrandom=17;
characters

IV.d.5. A 4-dim Riemannian spacetime embedded in a flat 10-dim space

The subroutine embedsub constructs the embedding 2-forms and bases. In a problem such as this in which each 1-form consists only of a unique basis form, the oneforms can actually be omitted, so long as their closure 2-forms are included. Doing so will reduce the length of the solution vectors, and may lessen the execution time. The program will give the first character,  (Subscript[s, 0])=0, but its actual value is clearly just the length of oneforms, since they are all independent

embedsub[4,{-1,1,1,1,1,1,1,1,1,1}]
makescalars[{}];
maxnum=5;
pforms[1]=pforms[3]=pforms[4]=pforms[5]={};
pforms[2]=embeddingforms
maxrandom=9;
characters

The result that (Subscript[s, 4])=6 can be interpreted as 6 degrees of gauge freedom.

IV.d.6. A 4-dim Ricci-flat spacetime embedded in a flat 10-dim space

The subroutine embedsub constructs the Ricci 3-forms, subRθ, and bases. This time the oneforms are included, although again they could be omitted.

embedsub[4,{-1,1,1,1,1,1,1,1,1,1}]
makescalars[{}];
maxnum=5;
pforms[4]=pforms[5]={};
pforms[1]
pforms[2]=embeddingforms
pforms[3]=subRθ
maxrandom=5;
characters

IV.d.7. A 5-dim Riemannian manifold embedded in a flat 15-dim space

The subroutine embedsub constructs the embedding 2-forms and bases.

embedsub[5,{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}]
makescalars[{}];
maxnum=6;
pforms[3]=pforms[4]=pforms[5]=pforms[6]={};
pforms[1]
pforms[2]=embeddingforms
maxrandom=3;
characters

IV.d.8. A 6-dim Riemannian manifold embedded in a flat 21-dim space

The subroutine embedsub constructs the embedding 2-forms and bases. This problem is included simply to illustrate what happens for a case in which 6 characters are not sufficient to give a complete result. However, the final answer here is obvious, though it takes a while.

embedsub[6,{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}]
makescalars[{}];
maxnum=5;
pforms[3]=pforms[4]=pforms[5]={};
pforms[1]
pforms[2]=embeddingforms
maxrandom=3;
characters

Indeed, by increasing maxnum we can see that the genus is smaller:

embedsub[6,{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}]
makescalars[{}];
maxnum=7;
pforms[3]=pforms[4]=pforms[5]=pforms[6]=pforms[7]={};
pforms[1]
pforms[2]=embeddingforms
maxrandom=3;
characters

IV.d.9. Detailed results of IV.d.8 with maxnum=7.  Checking the results,  checking involutory vectors in solutions.

The variable solutionvectors contains the independent vectors, v[i], found. In large ideals these vectors may be very long.

solutionvectors

involutoryvectors will show a set of independent vectors with the leftmost components in involution. This shows which basis forms, pulled back into solutons, can be linked to independent variables in equivalent sets of partial differential equations.

involutoryvectors

allones shows all 1-forms generated during the calculation.

allones

Length[allones]

The procedure check first constructs an arbitrary linear combination of involutoryvectors, called genvec. It then contracts genvec on allones, which must give zero for each of them. The list invset contains the involutory vector components; i.e., the leftmost non-zero components. Any of the original forms which do not appear in the ideal are obviously either Cauchy characteristics or basis oneforms that were deliberately omitted. They are in the variable absentforms. The routine cauchys attempts to find other potential Cauchy characteristics which annul the oneforms and twoforms, but does not investigate any higher degree forms.

check

genvec

invset

idealforms

absentforms

cauchys

To check independence for any subspace, the following commands can be changed to some other subset of forms and/or of solution vectors:

forms

sub=forms[[1]]⋀forms[[2]]⋀forms[[3]]⋀forms[[4]]

checkinvolution=charv[4]∘charv[3]∘charv[2]∘charv[1]∘sub

Changing the order of the basis 1-forms in the forms list can be accomplished by executing the next cell to get the idealforms list and then re-ordering the output line. It will convert to input format with the first edit. Continue editing in this line. 

When finished (being careful not to omit or duplicate any forms and/or commas), type new= in front of the new list and enter. Then execute the makeforms[new] statement. To change maxrandom assign a new value in the next statement; if maxrandom is not re-set it will retain the previous value.

Finally, select the characters cell and enter. Doing this last step alone will simply repeat a calculation with the same forms list and a randomly different set of integers selected from the same range.  

Re-ordering the forms list can have a significant effect on the size of generated integers and so may have some effect on time and memory usage. As a general rule, placing the basis forms which appear more frequently in the ideal at the end of the list, gives smaller integers and a simpler solution.

idealforms

IV.d.10. Clean up

makeclear[]

Remove["Global`*"]

Cleaning up must be done by hand here, for these variables:

ModifiedGlobalVariables