1. Symbols and types

1.1. Type information: symbols

There are three primitive types of values in Mathematica: symbols (head Symbol), strings (head String) and numbers (heads Integer, Rational, Real and Complex). Unfortunatlely it is not possible to define new primitive types. Tensors and other types of values must be composite types. What follows in this section refers to tensors, but can also be applied to other xTensor` types of values, to be listed below.

Information in Mathematica is associated to symbols only (not to strings, numbers or composite expressions as a whole). In xTensor` we take the following important decision: information on a tensor will be associated to a symbol identifying that tensor. This has two important consequences:
    - Tensors are identified using symbols, and not strings.
    - We cannot have two different tensors identified by the same symbol, to avoid conflicting information.
This decision has also two important advantages:
    - Information on a tensor is only used by Mathematica when the tensor appears in the expression being evaluated.
    - At any time we can collect all the information known about a tensor, using Information (the ? command).
    
There is a harsh limitation in Mathematica: an expression can be associated to a symbol if and only if the symbol is present in the expression at levels 0 or 1, but no deeper. This leads us to introduce a second important decision: symbols with some  xTensor` type will always appear in the composite expression at level 0; in other words, the symbol identifying a tensor will be the head of the tensor, and so on: we shall use A[...] rather than, for example, the more natural notation Tensor[A][...] suggested by Maeder.

It could seem reasonable to use contexts to separate Tensor`A from Manifold`A or Index`A. This simply means using longer names for the objects defined. We could use as well TensorA, ManifoldA, IndexA, or perhaps TenA, ManiA, IndA. In xTensor` we do not force any particular solution, leaving the decision to the user. The only general recommendation is using long names for tensors (like MaxwellF for the electromagnetic Faraday tensor) and short names (a, b, C, etc.) for abstract indices.

It could also seem reasonable to define tensors as abstract types, instead of fixing a particular structure from the very beginning. However, this would be slow for pattern matching. We shall simply try to write code having the abstract model in mind.

1.2. Valid symbols. Attributes

Copied from the Mathematica Reference Guide (A.1.2): The name of a symbol must be a sequence of letters, letter-like forms and digits, not starting with a digit. xTensor` adds a few more restrictions on the symbols that can be used to identify tensors and so on. These restrictions are checked by the xCore function ValidateSymbol, called by all DefType commands:
    1. The symbol is not numeric (checked with NumericQ).
    2. The symbol does not have values (checked with ValueQ).
    3. The symbol does not have a Locked attribute.
    4. The symbol is not already used by xTensor`, xPerm`, xCore` or ExpressionManipulation`.
    5. The symbol is not protected, readprotected or used by Mathematica.
There is an exception to restriction 5: the capitals C, D, K, N, O are used by Mathematica but are accepted as valid symbols for indices and overloaded (that is, without changing their context), issuing a warning message. The capitals E and I are numeric and cannot be used.

Once a symbol is used to identify an object, it cannot be used to identify another object. We use the function
ValidateSymbolInSession to check whether a symbol is currently being used or not. This function is called by all DefType commands.

All
DefType commands have the option ProtectNewSymbol, whose default value is given by the global variable $ProtectNewSymbols (initialized to  False), which allows the user to protect the defined symbol right after all its properties have been assigned. This is a security feature, and, if used, then any protected symbol must be unprotected (with Mathematica's Unprotect) before new definitions can be associated to it.

1.3. Type managing

As we said, xTensor` implements its own way to deal with symbol types. It is certainly nor ellegant nor efficient, but it is the only way to use upvalues and keep a simple input, at the expense of harder patterns. Currently there are the following 12 symbol types (the mathematical meaning of each type will be explained in detail in the following sections):

Symbol  Type Q-function Global list Definition Meaning
ConstantSymbol ConstantSymbolQ $ConstantSymbols DefConstantSymbol Constant with respect to all derivatives
Parameter ParameterQ $Parameters DefParameter Parametric dependency
Manifold ManifoldQ $Manifolds DefManifold Smooth n-dim manifold
VBundle VBundleQ $VBundles DefVBundle Vector bundle
AbstractIndex AbstractIndexQ $AbstractIndices DefAbstractIndex Index associated to a vbundle
Tensor xTensorQ $Tensors DefTensor Tensor field on a manifold
CovD CovDQ $CovDs DefCovD Connection on a manifold
Metric MetricQ $Metrics DefMetric Metric tensor field
InertHead InertHeadQ $InertHeads DefInertHead Wrapper for tensors
ScalarFunction ScalarFunctionQ $ScalarFunctions DefScalarFunction Scalar function on scalars
Basis BasisQ $Bases DefBasis Frame of vector fields
Chart ChartQ $Charts DefChart Coordinate chart on a manifold


Each type has an associated Q-function to identify the symbol type: each user-defined symbol has an upvalue True for the corresponding Q-function, giving False on the other Q-functions. The name of the Q-function is always constructed appending Q to the type name (note the exception of xTensorQ, to avoid conflict with Mathematica's TensorQ). The list of symbols of each type is contained in a global variable whose name is constructed using a $ and the plural of the symbol type (note that the plural of Index is Indices, and the plural of Basis is Bases). Objects of the corresponding type are defined (undefined) using DefType (UndefType) commands, where Type must be replaced by the corresponding symbol type. The option Info allows us to store some information on the type and nature of the defined symbol. The function Undef can undefine any symbol.

Bases and charts are defined and dealt with in the companion package xCoba`. In particular the functions DefBasis and DefChart are defined in there. However the type management is done by xTensor`.

Given an expression, we can find all instances of a given type using the function FindAllOfType.

1.4. Relations among symbols

There are mathematical objects that can only be defined if other objects have already been defined before. For example defining a scalar field T requires the previously defined manifold M where it lives. We shall say the symbol T is a "visitor" of the symbol M, which itself will be called a "host" of T. The lists of visitors associated to a symbol is given by the functions VisitorsOf and HostsOf. A symbol can only be removed when the list of its visitors is empty.

Some objects are automatically defined. For example the tangent bundle of a manifold is automatically defined when the manifold is defined. We say that the tangent bundle is a "servant" of the manifold, and that the manifold is the "master" of the tangent bundle. The list of servants associated to a symbol is given by the function ServantsOf. The master of a symbol is given by the function MasterOf. The master of a symbol is specified at definition time using the option Master of the DefType commands.

Visitors of a symbol frequently have that symbol in their own name. For instance, the Riemann tensor of the covariant derivative CD is called by default RiemannCD. This is controlled through the function GiveSymbol, which in that example would be called as GiveSymbol[Riemann, CD], and has explicit instructions on how to proceed in each case.


Created by Mathematica  (May 16, 2008) Valid XHTML 1.1!