8.1. MakeRule

Defining rules is one of the most important components of a tensor package. The function IndexRule takes care of dummy generation, but there are other points to consider when defining a rule:
    1. Checking consistency between left and right hand sides.
    2. Defining rules that work only for a given vbundle.
    3. Extending the rule to pattern expressions with equivalent index-structure under symmetries.
    4. Extendig the rule to patterns with a different up/down character if metrics are present.
We define the function MakeRule, which takes care of all these things. Note that there is not a parallel function for Set, but below we present a way to automatize a collection of rules.

MakeRule                Construct rules between xTensor` expressions
AutomaticRules            Automate rules

Construction of rules.

In[778]:=

Options[MakeRule]

Out[778]=

{PatternIndices→All, TestIndices→True, MetricOn→None, UseSymmetries→True, Verbose→False, ContractMetrics→False}

The simplest way to define a rule would easily give corrupted answers:

In[779]:=

$Tensors

Out[779]=

In[780]:=

rule = v[a_] →T[a, -b] v[b]

Out[780]=

v_ ^Underscript[a, _] →T_ ( b)^a  v_ ^b

In[781]:=

v[b]/.rule

Validate :: repeated : Found indices with the same name b .

Throw :: nocatch : Uncaught Throw[Null] returned to top level. More…

Out[781]=

Hold[Throw[Null]]

We have seen that changing to IndexRule we can solve those problems (underlined indices denote patterns):

In[782]:=

rule = v[a_] |→T[a, b] v[-b]

Out[782]=

HoldPattern[v_ ^Underscript[a, _]] :→Module[{b}, T_  ^ab v_b^ ]

In[783]:=

v[b]/.rule

Out[783]=

T_  ^ba v_a^

In[784]:=

%/.rule

Out[784]=

T_a ^( c) T_  ^ba v_c^

We can also define the same rule using MakeRule. Note that there is no pattern on the lhs; by default all indices on the LHS are converted into patterns:

In[785]:=

rule = MakeRule[{v[a], T[a, -b] v[b]}, MetricOn→None]

Out[785]=

{HoldPattern[v_ ^Underscript[Underscript[a, _], _]] :→Module[{b}, T_ ( b)^a  v_ ^b]}

In[786]:=

T[-a, -b] v[a] v[b]/.rule

Out[786]=

T_ab^   T_ ( c)^a  T_ ( d)^b  v_ ^c v_ ^d

In[787]:=

InputForm[rule]

Out[787]//InputForm=

{HoldPattern[v[(a_Symbol)?TangentM3`Q]] :> Module[{h$41203}, T[a, -h$41203]*v[h$41203]]}

Due to the option TestIndices→True, membership of the indices of the LHS is checked. The function M3`Q checks that an up-index belongs to M3, but it does not accept down-indices (this is due to the option MetricOn->None):

In[788]:=

v[a]/.rule

Out[788]=

T_ ( b)^a  v_ ^b

In[789]:=

v[-a]/.rule

Out[789]=

v_a^

In[790]:=

v[A]/.rule

Out[790]=

v_ ^A

In order to allow both up/down-indices of a given vbundle we use MetricOn. We need to have a metric first. (If the vbundle of the index did not have a metric MakeRule would refuse to change the up/down character):

In[791]:=

rule = MakeRule[{v[a], T[a, -b] v[b]}, MetricOn→ {a}, ContractMetrics→True]

Out[791]=

{HoldPattern[v_ ^Underscript[Underscript[a, _], _]] :→Module[{b}, T_ ( b)^a  v_ ^b]}

In[792]:=

InputForm[rule]

Out[792]//InputForm=

{HoldPattern[v[(a_)?TangentM3`pmQ]] :> Module[{h$41215}, T[a, -h$41215]*v[h$41215]]}

In[793]:=

v[a]/.rule

Out[793]=

T_ ( b)^a  v_ ^b

In[794]:=

v[-a]/.rule

Out[794]=

T_ab^   v_ ^b

If we have symmetries the situation gets even more complicated (here we need to use 6 rules):

In[795]:=

(rule = MakeRule[{U[a, b, c] v[-c], v[a] T[b] - v[b] T[a]}, MetricOn→All, ContractMetrics→True])

Out[795]=

In[796]:=

U[-a, b, c] v[-b]/.rule

Out[796]=

-T_ ^c v_a^ + T_a^  v_ ^c

In[797]:=

U[-a, b, c] v[a]/.rule

Out[797]=

T_ ^c v_ ^b - T_ ^b v_ ^c

In[798]:=

U[-a, c, -c] v[a]/.rule//ToCanonical

Out[798]=

0

It is possible to automate rules, declaring them as definitions for a symbol, in this case the tensor U:

In[799]:=

AutomaticRules[U, rule]

   Rules  {1, 2, 3, 4, 5, 6}  have been declared as UpValues for U .

In[800]:=

U[-a, b, c] v[-b]

Out[800]=

-T_ ^c v_a^ + T_a^  v_ ^c

In[801]:=

U[-a, b, c] v[a]

Out[801]=

T_ ^c v_ ^b - T_ ^b v_ ^c

In[802]:=

? U

Global`U

Dagger[U]^:=U
DependenciesOfTensor[U]^:={M3}
Info[U]^:={tensor,}
PrintAs[U]^:=U
SlotsOfTensor[U]^:={-TangentM3,-TangentM3,-TangentM3}
SymmetryGroupOfTensor[U]^:=StrongGenSet[{1,2},GenSet[-Cycles[{1,2}],-Cycles[{2,3}]]]
TensorID[U]^:={}
xTensorQ[U]^:=True

The simplest way to remove those definitions for U is removing the tensor and defining it again:

In[803]:=

UndefTensor[U]

** UndefTensor: Undefined tensor U

In[804]:=

DefTensor[U[-a, -b, -c], M3, Antisymmetric[{1, 2, 3}]]

** DefTensor: Defining tensor U[-a, -b, -c] .


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