Differences

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

Link to this comparison view

documentation:ref:tensor [2015/11/21 12:33]
documentation:ref:tensor [2015/11/21 12:33] (current)
Line 1: Line 1:
 +====== Tensor ======
 +----
 +=====Basics=====
 +''​Tensor''​ is a parent object type for all mathematical expressions used in Redberry. Thus, //all expressions in Redberry are tensors//. From the programming point of view that means, that ''​Tensor''​ is a parent class for all types of mathematical expressions used in Redberry (sums, products, etc.). ''​Tensor''​ defines common properties and functional shared in all its subtypes.
 +
 +
 +=====Common properties =====
 +There are several unifying properties of all mathematical expressions like size,  indices, container properties etc. All these properties can be obtained from any expression using methods defined in ''​Tensor''​. Let us consider each property in detail.
 + 
 +====Indices====
 +Presence of indices it a key feature of all tensorial expressions. [[documentation:​ref:​Indices]] can be obtained for any expression using ''​.indices''​ property (or equivalently ''​getIndices()''​ method):
 +<sxh groovy; gutter: false>
 +println 'g_ab * T^cd'​.t.indices
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > ^cd_ab
 +</​sxh>​
 +<sxh groovy; gutter: false>
 +println '​T_ba^dc'​.t.indices
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > _ba^dc
 +</​sxh>​
 +(in case of pure scalars ''​.indices''​ will return [[documentation:​ref:​Indices]] ​ with zero size).
 +
 +[[documentation:​ref:​Indices]] ​ is a feature which is inherent in any type of expression (sum, product, function, simple tensor etc.). Meanwhile, indices of different types of expressions can have slightly different nature. ​ For example, indices of ''​SimpleTensor''​ will appear exactly in that order as they were specified by the user, while indices of e.g. ''​Product''​ will be always sorted in some way; indices of ''​Sum''​ are sorted free indices of its summands etc. Thus, ''​Tensor''​ defines only abstract method ''​.indices''​ while each particular subtype of ''​Tensor''​ is responsible for implementation. For more details see [[documentation:​guide:​tensors_and_indices]].
 +====Container====
 +Any tensor has a content (summands in case of [[documentation:​ref:​Sum]],​ multipliers in case of [[documentation:​ref:​Product]] etc.). The following table summarises, how one can access //container properties//​ of expressions:​
 +
 +<​html>​
 +<table style="​width:​600px;"​ cellpadding="​10">​
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;"><​code>​T.size()</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;">​returns a size of tensor, i.e. number of summands in case of sum, number of arguments in case of function etc.</​td> ​
 +</tr>
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px;​margin-top:​ 35px;​border:​ 1px solid gray;"><​code>​T[i]</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px;​margin-top:​ 35px;​border:​ 1px solid gray;">​returns element at <​i>​i</​i>​-th position</​td> ​
 +</tr>
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px;​margin-top:​ 35px;​border:​ 1px solid gray;"><​code>​T[i..j]</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px;​margin-top:​ 35px;​border:​ 1px solid gray;">​returns a list of elements from <​i>​i</​i>​-th ​ (inclusive) to <​i>​j</​i>​-th (exclusive) ​ </​td> ​
 +</tr>
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px;​margin-top:​ 35px;​border:​ 1px solid gray;"><​code>​T[i,​ j, k]</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px;​margin-top:​ 35px;​border:​ 1px solid gray;">​returns a list of elements at specified positions ​ </​td> ​
 +</tr>
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px;​margin-top:​ 35px;​border:​ 1px solid gray;"><​code>​T.set(i,​ expr)</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px;​margin-top:​ 35px;​border:​ 1px solid gray;">​returns a new tensor with <​code>​expr</​code>​ at <​i>​i</​i>​-th position </​td> ​
 +</tr>
 +</​table>​
 +</​html>​
 +(one can also find more special methods like ''​remove''​ in [[Sum]] and [[Product]])
 +
 +One can also construct ''​Tensor''​ from a list in the following way
 +<sxh groovy; gutter: true;> ​
 +def list = ['​a',​ '​b',​ '​c'​]
 +println list as Sum // same as list.sum()
 +</​sxh>​
 +<sxh plain; gutter: false;> ​
 +   > a + c + b
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line 3> 
 +def t = 'a + b + c + d + e + f + g'.t
 +println t[1..4] as Product // same as t[1..4].multiply()
 +</​sxh>​
 +<sxh plain; gutter: false;> ​
 +   > b*d*e
 +</​sxh>​
 +
 +**Note,** that the ordering of expressions (summands in sum, or multipliers in product) can be different from that one in which the expression was inputted by the user. So, if one inputted e.g.
 +<sxh groovy; gutter: false;> ​
 +def t = 'a + b + c'.t
 +</​sxh>​
 +and then take ''​t[0]'',​ the result will not necessary be ''​a''​ but also can be ''​b''​ or ''​c''​. This ordering will be always same during a single run of Redberry, by can be changed from run to run. In order to make this ordering same in all runs one can put the following line in the beginning of the code:
 +<sxh groovy; gutter: false;> ​
 +CC.resetTensorNames(1)
 +</​sxh>​
 +====Iterable====
 +This simply means that one can iterate through expression content using ''​for''​ loop:
 +<sxh groovy; gutter: true>
 +def expr = '​a*(b+e)*Sin[c]*d*(e+f)'​.t
 +def sums = []
 +for (def t in expr) //iterating through expr
 +    if (t instanceof Sum) //taking only sums
 +        sums << t
 +println sums
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > [b+e, e+f]
 +</​sxh>​
 +<sxh groovy; gutter: true;​first-line:​ 7>
 +println sums as Sum
 +</​sxh> ​
 +<sxh plain; gutter: false>
 +   > b + 2*e + f
 +</​sxh>​
 +
 +In such a way one can iterate only through //direct %%"​children"​%%//​ of expression. In order to iterate through //all// expression parts, one should use [[documentation:​guide:​tree_traversal]].
 +
 +=====Creating tensors programmatically=====
 +In most cases one will input expression by hand, but often it becomes necessary to construct tensors programmatically from a given content. There are a variety ways to do that in Redberry. ​
 +
 +First of all, Redberry allows to use simple algebraic operators on tensors:
 +<sxh groovy; gutter: false>
 +def x = '​x'​.t,​ y = '​y'​.t
 +println x/y + sin(x*y) + y**3
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > x/y + Sin[x] + y**3
 +</​sxh>​
 +(however such syntax may be inconvenient for indexed expressions in some cases, since it does not reflect presence of indices)
 +
 +Sometimes we need to construct expression from a given content. Here is a some useful methods that allow to do that: 
 +<​html>​
 +<table style="​width:​800px;"​ cellpadding="​10">​
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;"><​code>​sum(exprs)</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;">​returns a sum of specified expressions</​td> ​
 +</tr>
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;"><​code>​multiply(exprs)</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;">​returns a product of  specified expressions</​td> ​
 +</tr>
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;"><​code>​simpleTensor(head,​ indices)</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;">​returns a simple tensor with specified name and simple indices</​td> ​
 +</tr>
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;"><​code>​field(head,​ indices, args)</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;">​returns a tensor field with specified name, simple indices and arguments</​td> ​
 +</tr>
 +<tr>
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;"><​code>​fieldDerivative(field,​ dIndices, arg, order)</​code></​td>​
 +  <td valign="​top"​ style="​padding:​ 15px; border: 1px solid gray;">​returns a derivative of field with respect to specified argument, argument indices and order</​td> ​
 +</tr>
 +</​table>​
 +</​html>​
 +
 +Consider examples:
 +<sxh groovy; gutter: true>
 +def list = ['​a',​ '​b',​ '​c'​].t
 +println sum(list)
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > a+b+c
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 3>
 +println multiply(list)
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > a*b*c
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 4>
 +println simpleTensor('​f',​ '​_abc'​.si)
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > f_abc
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 5>
 +println field('​f',​ '​_abc'​.si,​ list)
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > f_abc[a,​b,​c]
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 6>
 +println fieldDerivative('​f_a[x_a,​ y_b]'​.t,​ '​_ij'​.si,​ 1, 2)
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > f~(0,​2)_{aij}[x_a,​ y_b]
 +</​sxh>​
 +
 +One should be careful when using ''​multiply()''​ to multiply tensors with dummy indices. By default, ​ ''​multiply()''​ will not rename conflicting dummy indices:
 +<sxh groovy; gutter: false>
 +println multiply('​A^a_a'​.t,​ '​B^a_a'​.t)
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > InconsistentIndicesException:​ Inconsistent index ^a.
 +</​sxh>​
 +If one need to rename such dummies, one can use ''​multiplyAndRenameConflictingDummies()'':​
 +<sxh groovy; gutter: false>
 +println multiplyAndRenameConflictingDummies('​A^a_a'​.t,​ '​B^a_a'​.t)
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > A^{a}_{a}*B^{b}_{b}
 +</​sxh>​
 +
 +
 +=====Advanced features: builders and factories=====
 +In some cases (especially when writing custom transformations) it becomes necessary to rebuild expression without knowing it particular type in advance. For this purpose, each expression provide a "​builder"​ (via ''​.builder''​ property), which allows to construct tensor of same type. 
 +
 +For example, suppose we need to implement a "​toy"​ transformation which simply removes all simple tensors from product or sum. This can be done in the following way:
 +<sxh groovy; gutter: true>
 +def tr = { expr ->
 +    def builder = expr.builder
 +    for (def t in expr)
 +        if (t.class != SimpleTensor)
 +            builder << t
 +    builder.build()
 +} as Transformation
 +
 +def product = '​a*(b+e)*Sin[c]*d*(e+f)'​.t
 +println tr >> product
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > Sin[c]*(e+b)*(f+e)
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 11>
 +def sum = '​a+b*e+Sin[c]+d+e*f'​.t
 +println tr >> sum
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > Sin[c]+b*e+e*f
 +</​sxh>​
 +
 +When the length of result is known in advance, one  can use ''​.factory''​. Consider a "​toy"​ transformation which appends tensor ''​a''​ to expression:
 +<sxh groovy; gutter: true>
 +def tr = { Tensor expr ->
 +    def data = expr as List
 +    data << '​a'​.t
 +    expr.factory.create(data)
 +} as Transformation
 +
 +def product = '​f[x]*Sin[a]'​.t
 +println tr >> product
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > a*Sin[a]*f[x]
 +</​sxh>​
 +<sxh groovy; gutter: true; first-line: 9>
 +println tr >> (product as List).sum()
 +</​sxh>​
 +<sxh plain; gutter: false>
 +   > a+Sin[a]+f[x]
 +</​sxh>​
 +
 +The general convention on builders and factories is that if ''​t''​ is any expression, then the result of rebuild is same:
 +<sxh groovy; gutter: false>
 +assert t == (t.builder << (t as List)).build()
 +assert t == t.factory.create(t as List)
 +</​sxh>​
 +
 +=====See also=====
 +  * Related guides: [[documentation:​guide:​tensors_and_indices]],​ [[documentation:​guide:​tree_traversal]]
 +  * Related reference material: [[documentation:​ref:​sum]],​ [[documentation:​ref:​product]],​ [[documentation:​ref:​indices]],​ [[documentation:​ref:​simpletensor]],​ [[documentation:​ref:​tensorfield]]
 +  * JavaDocs: [[http://​api.redberry.cc/​redberry/​1.1.9/​java-api/​cc/​redberry/​core/​tensor/​Tensor.html| Tensor]]
 +  * Source code: [[https://​bitbucket.org/​redberry/​redberry/​src/​tip/​core/​src/​main/​java/​cc/​redberry/​core/​tensor/​Tensor.java|Tensor.java]]