# TensorField

### Basics

TensorField represents a function like f_mn[x_a] or derivative of function like f~(1)_a[x_i]. Like any other expression, it inherits all properties of Tensor. Additionally it inherits all properties of SimpleTensor and adopts same convention on its indices: the indices of TensorField (SimpleIndices) are sorted by their types, but the relative ordering of indices within a particular type is same as defined by the user:

def t = 'f_cba^\\alpha_AB[t_mn, f_i]'.t
println t.indices

    > _{cbaAB}^{\alpha}

The relative ordering is not changed even if tensor has symmetry property; in latter case Redberry uses algorithms provided by Mappings of indices to compare expressions instead of trying to put expression in canonical form.

Symmetries of TensorField can be specified exactly in the same way as for SimpleTensor:

addSymmetry 'f_pqr[k_l, k_l]', [1, 0].p
//or equivalently


In case of derivatives, the total indices of TensorField are formed by concatenation of initial indices and inverted indices of differentiating variables. For example, the indices of $\frac{\delta}{\delta f^{abc}} \frac{\delta}{\delta f^{de}} F_{mn}\left(f_{abc}, f_{ab}\right)$ will be formed by sequential concatenation of initial indices $_{mn}$, indices of differentiating variable corresponding to first argument $_{abc}$ and indices of differentiating variable corresponding to second argument $_{de}$; thus, the resulting indices will be $_{mnabcde}$ and the corresponding tensor field

'F~(1, 1)_{mn abc de}[f_abc, f_ab]'.t

Additionally, if derivative taken several times with respect to same slot, the corresponding indices will be symmetric, since the relative order of differentiation is not relevant:
println 'F~(2)_{mn ab cd}[f_ab] + F~(2)_{mn cd ab}[f_ab]'.t

   > F~(2)_{mn ab cd}[f_ab]


Since TensorField inherits both Tensor and SimpleTensor it provides all features found in them like container properties, utterable, symmetries etc. On the other hand, the .name property from SimpleTensor will additionally encode information about arguments of TensorFiels, so e.g. functions like f_i[x_a] and f_i[x_ab] will have different .name.

The additional features of TensorField appear when it represents derivative:

 .isDerivative() returns whether TensorField represents derivative of function (e.g. f~(3)[x]) or just function (e.g. f[x]) .getDerivativeOrder(i) returns order of derivative with respect to argument at i-th position .parentField returns function from which the derivative is taken .partitionOfIndices returns partition of derivative indices; this partition separates indices of parent function and indices appended by derivatives

Let us consider for example derivative $\displaystyle \frac{\delta}{\delta x^{cd}} \frac{\delta^2}{\delta t^m \, \delta t^n} F_{ab}\left(x_{mn}, t_i, x\right)$:

def f = 'F~(1,2,0)_{ab cd mn}[x_mn, t_i, x]'.t
assert f.isDerivative()
println f.getDeivativeOrder(1)

   > 2

println f.parentField

   > F_{ab}[x_{mn},t_{i},x]

println( (0..(f.size() - 1)).collect { f.getDeivativeOrder(it) })

   > [1, 2, 0]

println f.partitionOfIndices

   > [[_{ab}], [_{cd}], [_{m}, _{n}], []]

The first element in .partitionOfIndices is indices of parent field, while (i+1)-th element of this array corresponds to indices of derivatives with respect to i-th slot.