Differences

This shows you the differences between two versions of the page.

Link to this comparison view

documentation:guide:tensors_and_indices [2015/11/21 12:33]
documentation:guide:tensors_and_indices [2015/11/21 12:33] (current)
Line 1: Line 1:
 +====== Tensors and Indices ======
 +<​html>​
 +<div class="​text-right"​ style="​font-size:​ 15px; ">
 +</​html>​
 +Next topic: [[documentation:​guide:​einstein_notation]]
 +<​html>​
 +<span class="​glyphicon glyphicon-arrow-right"></​span>​
 +</​div>​
 +</​html>​
 +
 +----
 +
 +There are three central object types in Redberry: [[documentation:​ref:​Tensor]],​ [[documentation:​ref:​Indices]],​ and [[documentation:​ref:​Transformation]]. Objects of the same type share common properties and can be manipulated in a common way. Tensors and their indices are considered in this section, while transformations are discussed in 
 +[[documentation:​guide:​applying_and_manipulating_transformations]]. ​
 +=====Tensors=====
 +Each mathematical expression in Redberry is a [[documentation:​ref:​Tensor]]. Using object-oriented programming terminology,​ this means that all mathematical types are inherited from a base super type [[documentation:​ref:​Tensor]],​ and thereby can be manipulated in a uniform way and share a common properties like presence of indices. Here we briefly overview types of mathematical expressions in Redberry and how one can access and modify their structure.
 +====Types of tensors====
 +There are following subtypes of tensors in Redberry:
 +  * [[documentation:​ref:​SimpleTensor]] ​ --- a simple variable like ''​x''​ or ''​f_mn'' ​
 +  * [[documentation:​ref:​TensorField]] ---  a function like ''​f[x]''​ or ''​T_ab[x_m,​ y]'' ​
 +  * [[documentation:​ref:​Product]] --- product of tensors
 +  * [[documentation:​ref:​Sum]] --- sum of tensors
 +  * [[documentation:​ref:​Power]] --- a power like ''​%%a**2%%'' ​
 +  * ''​Complex''​ --- any number like ''​2''​ or ''​2+I''​ or ''​1.232'' ​
 +  * ''​Expression''​ --- a substitution rule like ''​x = y''​ etc.  ​
 +
 +One can find the type of expression in the following way:
 +
 +<sxh groovy; gutter: true>
 +def t = 'a * T_mn + g_mn'​.t
 +//print name of Tensor subtype
 +println t.class.simpleName
 +</​sxh>​
 +
 +<sxh plain; gutter: false>
 +   > Sum
 +</​sxh>​
 +
 +<sxh groovy; gutter: true; first-line: 4>
 +//check that t is of type Tensor
 +println(t instanceof Tensor)
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > true
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 6>
 +//check that t is of type Sum
 +println(t instanceof Sum)
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > true
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 8>
 +//check that t is not Product
 +println(t instanceof Product) ​
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > false
 +</​sxh>​
 +====Structure of tensors====
 +Each mathematical expression in Redberry is a [[documentation:​ref:​Tensor]]. Any [[documentation:​ref:​Tensor]] has [[documentation:​ref:​Indices]] and content (summands in case of sum, arguments in case of functions, etc.; thus, tensors in Redberry are containers of other tensors). The [[documentation:​ref:​Indices]] of tensor can be obtained by getting the value of ''​.indices''​ property:
 +<sxh groovy; gutter: false>
 +def p = 'a * F^a_{mn} + b^a * h_m * h_n'.t
 +//accessing indices of tensor
 +println p.indices
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > ^{a}_{mn}
 +</​sxh>​
 +[[documentation:​ref:​Indices]] of tensors will be discussed [[#​Indices|below]].
 +
 +The following lines highlight container features of tensors:
 +<sxh groovy; gutter: true>
 +def p = 'a * F^a_{mn} + b^a * h_m * h_n + t_mn^a'​.t
 +//size of tensor as container
 +println p.size()
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > 3
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 4>
 +//getting elements by index
 +println( [p[0], p[2] ] ) 
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > [a*F^a_{mn}, ​ t_mn^a]
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 4>
 +//get several elements by index as a list
 +println( p[0, 2] as List ) 
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > [a*F^a_{mn}, ​ t_mn^a]
 +</​sxh>​
 +<sxh groovy; gutter: true;  first-line: 6>
 +//​enumerating elements
 +p.each{ i -> println i } 
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > a*F^a_{mn}+
 +   > b^a*h_m*h_n ​
 +   > t_mn^a
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 10>
 +//convert tensor to a list of tensors
 +println p as List
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > [a*F^a_{mn},​ b^a*h_m*h_n,​ t_mn^a]
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 12>
 +//get range as list
 +println p[0..1] as List
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > [a*F^a_{mn},​ b^a*h_m*h_n]
 +</​sxh>​
 +
 +For more specialised methods of tensors see [[documentation:​ref:​Tensor]] page.
 +====Modifying and instantiating tensors====
 +In most cases expressions are modified using transformations (expand or collect terms, eliminate metrics etc.). However, sometimes it is useful to modify expressions "in place" (set or remove parts of expressions etc.). Tensors are immutable in Redberry and all modification operations return new instances. So, in order to modify expressions one can do:
 +<sxh groovy; gutter: true>
 +def t = 'A_i + C_i + D_i'.t
 +def x = t.set(1, '​B_i'​.t)
 +println x
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > A_i + B_i + D_i
 +</​sxh>​
 +<sxh groovy; gutter: true;​first-line:​ 4>
 +def y = t.remove(0)
 +println y
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > C_i + D_i
 +</​sxh>​
 +<sxh groovy; gutter: true;​first-line:​ 6>
 +y = t.remove(0, 2)
 +println y
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > C_i
 +</​sxh>​
 +<sxh groovy; gutter: true;​first-line:​ 8>
 +println t
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > A_i + C_i + D_i
 +</​sxh>​
 +
 +
 +As one can see that original tensor ''​t''​ was not modified, but new tensors ''​x''​ and ''​y''​ were created.
 +
 + In order to create tensors programmatically,​ Redberry defines all arithmetic operations for [[documentation:​ref:​Tensor]] objects:
 +<sxh groovy; gutter: false>
 +def x = '​x'​.t,​ y = '​y'​.t
 +def t = (-x+sin(y))**2/​(x+sin(-y))+x-sin(y)
 +println t
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > 2*Sin[-y]+2*x
 +</​sxh>​
 +Such syntax, however, may be inconvenient when dealing with indexed objects, since 
 +names of variables do not reflect structure of indices ​ of expressions. For further reading see [[documentation:​ref:​Tensor]] page.
 +
 +See [[documentation:​guide:​mappings_of_indices]] on how to modify indices of tensor.
 +=====Indices=====
 +The presence of indices is a main distinguishing property of tensorial CASs. As mentioned above, there is an ''​.indices''​ property defined for each expression in Redberry. The returned object is an object of type [[documentation:​ref:​Indices]]. It has a number of methods and properties to work with it. Consider some examples:
 +<sxh groovy; gutter: true>
 +def t = '​2*x_am*f^m*(a^n+b^n)'​.t
 +def ind = t.indices
 +println([ind,​ ind.size()])
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > [^{mn}_{am},​ 4]
 +</​sxh>​
 +<sxh groovy; gutter: true;​first-line:​ 4>
 +//get only free indices
 +println ind.free
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > ^{n}_{a}
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 6>
 +//get inverted indices
 +println ind.inverted
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > ^{am}_{mn}
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 8>
 +//get upper indices ​
 +println ind.upper
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > ^{mn}
 +</​sxh>​
 +
 +Methods used in the above example, are inherent in any indices object. Their names 
 +clearly implies their meaning. For further information about properties of ''​Indices''​ see [[documentation:​ref:​Indices|Indices]].
 +
 +====Ordering of indices====
 +Although the presence of indices is inherent in all tensors, different types  of
 +expressions have different subtypes of [[documentation:​ref:​Indices]]. This
 +difference arises from availability or unavailability of information about
 +indices ordering. Consider indices of [[documentation:​ref:​SimpleTensor]]:​
 +<sxh groovy; gutter: false>
 +def simple = '​F_{mn}^{\\beta\\alpha}_{ba\\alpha}'​.t
 +println simple.indices
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > _{mnba}^{\beta\alpha}_{\alpha}
 +</​sxh>​
 +
 +The indices of [[documentation:​ref:​SimpleTensor]] are [[documentation:​ref:​SimpleIndices]]. The ordering of indices inside [[documentation:​ref:​SimpleIndices]] is same as specified by the user --- this is the main distinguishing property of [[documentation:​ref:​SimpleIndices]]. In other words, reordering of indices will result in changing of mathematical sense of corresponding simple tensor (unless this tensor is symmetric with respect to this permutation,​ see [[documentation:​guide:​Symmetries of Tensors]]). However, since each index belongs to some [[documentation:​ref:​IndexType|index type]] (e.g. Greek upper/lower case or Latin upper/lower case, etc.)  and indices of different types have different mathematical nature (e.g. Greek indices are Lorentz, Latin are SU(N) etc.), the relative positions of indices with different types is not important. Thus, Redberry sorts indices of simple tensors according to their types, preserving the relative order of indices belonging to the same type (as in the above example). Indices of [[documentation:​ref:​TensorField]] are also [[documentation:​ref:​SimpleIndices]] and follows the same ordering rules.
 +
 +Another type of indices is inherent in all other types of tensors. Consider the following [[documentation:​ref:​Product]]:​
 +<sxh groovy; gutter: false>
 +def pr = '​F_{mn}*F^{\\beta\\alpha}*F_{ba\\alpha}'​.t
 +println pr.indices
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > ^{\alpha\beta}_{abmn\alpha}
 +</​sxh>​
 +
 +From the mathematical point of view, the ordering of [[documentation:​ref:​Product]] indices is undefined. This allows to set up some certain ordering rules (mainly for technical reasons, related to performance). As one can see from the example, all indices are sorted according to the following rules: first upper then lower, first Latin then Greek, in each group of indices with the same type indices are sorted in lexical order. The similar rules are adopted for [[documentation:​ref:​Sum]]:​
 +<sxh groovy; gutter: false>
 +def sum = '​R^a_amn^\alpha + K^i_inm^\alpha'​.t
 +println sum.indices
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > ^{\alpha}_{mn}
 +</​sxh>​
 +The only difference, is that according to the sense of [[documentation:​ref:​Sum]],​ its  [[documentation:​ref:​Indices]] are  actually free indices of its summands.
 +
 +All methods from above listings (''​.inverted'',​ ''​.free''​ etc.), return objects with the same rules of ordering as in the initial ​ [[documentation:​ref:​Indices]].
 +
 +====Single index====
 +At the low-level, Redberry stores each 
 +single index as 32-bit integer that encodes all information about index: state, ​
 +type and name (serial number in the alphabet). Within a particular index type, 
 +there are $2^{16}$ possible names, which can be inputted using the subscript like 
 +<sxh groovy; gutter: false>
 +def t = '​X_{a_1 a_{122} b_9 \\mu_3}'​.t
 +</​sxh>​
 +
 +One can access different properties of single index in the following way:
 +<sxh groovy; gutter; true>
 +def indices = '​^abc'​.si
 +//take second index
 +def index = indices[1]
 +//print index
 +println index.toStringIndex()
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > ^b
 +</​sxh>​
 +<sxh groovy; gutter; true; first-line: 6>
 +//get index type
 +println index.type
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > LatinLower
 +</​sxh>​
 +<sxh groovy; gutter; true; first-line: 8>
 +//check whether index is upper
 +println index.isUpper()
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > true
 +</​sxh>​
 +<sxh groovy; gutter; true; first-line: 10>
 +//convert index to covariant and print
 +println index.toLower().toStringIndex()
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > _b
 +</​sxh>​
 +<sxh groovy; gutter; true; first-line: 12>
 +//invert index and print
 +println index.invert().toStringIndex()
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > _b
 +</​sxh>​
 +
 +
 +====Parsing indices====
 +In order to parse  [[documentation:​ref:​Indices]] from its string representation one can use ''​.i''​ property:
 +<sxh groovy; gutter:​false>​
 +def indices = '​_{\\beta n m}^{\\alpha}'​.i
 +println indices
 +</​sxh>​
 +<sxh plain; gutter:​false>​
 +   > ^{\alpha}_{mn\beta}
 +</​sxh>​
 +In the case of  [[documentation:​ref:​SimpleIndices]] one can use ''​.si''​ property:
 +<sxh groovy; gutter:​false>​
 +def indices = '​_{\\beta n m}^{\\alpha}'​.si
 +println indices
 +</​sxh>​
 +<sxh plain; gutter:​false>​
 +   > _{nm\beta}^{\alpha}
 +</​sxh>​
 +
 +=====See also=====
 +  * Related guides: [[documentation:​guide:​applying_and_manipulating_transformations]]