# Differences

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

 — documentation:guide:substitutions [2015/11/21 12:33] (current) Line 1: Line 1: + ====== Substitutions ====== + <​html>​ +
+ ​ + Next topic: [[documentation:​guide:​list_of_transformations]] + <​html>​ + ​ + ​ + ​ + + ---- + + ====Basics==== + The most frequent transformation in all computations is a substitution. Here + we shall discuss the usage aspects of substitutions,​ while the idea of the + underlying algorithms can be found in [[documentation:​guide:​Mappings of Indices]]. + + + + The very important feature of any tensorial CAS is automatic relabelling + of dummy indices in the case of dummy indices clash. Redberry takes care about + it in all types of substitutions. Consider, for example, the following simple + substitution:​ + $x = x_a{}^a \qquad\text{in}\qquad ​ (x\, f_a + y_a) (x \, f_b + z_b)$ + Here is a code to perform this substitution in Redberry: + + def s = 'x = x_a^a'​.t + def t = '​(x*f_a + y_a)*(x*f_b + z_b)'​.t + println s >> t + ​ + + > (x_{d}^{d}*f_{a}+y_{a})*(x_{c}^{c}*f_{b}+z_{b}) + ​ + As one can see, the appropriate relabelling was performed automatically. ​ + + ====Substitutions of tensor fields==== + Redberry supports substitutions of [[documentation:​ref:​TensorField|tensorial functions]] and automatically performs matching of function arguments during substitution:​ + + def s = '​F_ij[x_m,​ y_m] = x_i*y_j'​.t + def t = '​T^ab*F_ab[p^a - q^a, p^a + q^a]'​.t + println s >> t + ​ + + > T^{ab}*(p_{a}-q_{a})*(p_{b}+q_{b}) + ​ + If [[documentation:​ref:​TensorField]] depends on indexed argument, then some ambiguities arise when mapping the arguments. For example, the following substitution:​ + ​$​ + F_i (x_{mn}) \,=\, x_{ij} f^j \qquad \rightarrow \qquad F_k(x_i\,​y_j) ​ +$ + can be performed in two different ways: (a) matching $x_{ij} \to x_i y_j$ gives $x_k y_j f^j$, (b) matching $x_{ij} \to x_j y_i$ gives $y_k x_j f^j$. This is because the indices of product ($x_i y_j$) are not ordered by their nature. To explicitly specify the matching rule in such ambiguous situations, Redberry allows to enter the correspondence of indices in the field arguments: ​ + + def s = '​F_i[x_mn] = x_ik*f^k'​.t + def t = '​F_k[x_i*y_j]'​.t //​equivalent to F_k[x_i*y_j:​_ij] + println s >> t + ​ + + > x_{k}*y_{a}*f^{a} + ​ + + t = '​F_k[x_i*y_j:​_ji]'​.t ​ + println s >> t + ​ + + > x_{a}*y_{k}*f^{a} + ​ + + ====Substitutions of products, sums, etc. ==== + As well as [[documentation:​ref:​SimpleTensor]] and [[documentation:​ref:​TensorField]] substitutions,​ Redberry fully supports all other types of substitutions,​ taking into account both indices symmetries and indices contractions. Consider the following complicated example. Let's apply the following substitution ​ + $+ f_{m} + R_{bma}\,​F^{ba} - R_{ljm}\,​F^{lj} = R_{bam}\,​F^{ab} +$ + to tensor + $+ f_i + R_{ijk} F^{jk} + R_{ijk}\,​F^{kj} - R_{kij}\,​F^{jk},​ +$ + where $R_{abc}$ is antisymmetric:​ $R_{abc} \,=\, - R_{cba}$. It is easy to show that the result will be zero. In Redberry one can e.g. do + + addSymmetry '​R_mnp',​ -[[0, 2]].p + def s = 'f_m + R_bma*F^ba - R_ljm*F^lj =  R_bam*F^ab'​.t + def t = 'f_i + R_ijk*F^jk + R_ijk*F^kj - R_kij*F^jk'​.t + println s >> t + ​ + + > 0 + ​ + We see, that Redberry matched the l.h.s. of the substitution in tensor ''​t''​ and automatically reduced the resulting sum to the standard form,  which, in turn, gave zero. + + Redberry takes into account not only predefined symmetries of simple + tensors, but also symmetries of any complicated expression, which arise from + its structure. For example: + + def s = 'K_a * (A^ab - A^ba) = F^a*A_a^b'​.t + def t = 'K_p * (A^qp - A^pq) + F^b*A_b^q'​.t + println s >> t + ​ + + > 0 + ​ + The result is zero since tensor $(A_{cb} - A_{bc})$ is antisymmetric. As well, + Redberry takes care about symmetries of indexless objects: + + def c = 'Cos[a - b] = c'.t, + s = 'Sin[a - b] = s'.t, + t = 'x = Cos[b - a]**3 + Sin[b - a]**3'​.t + println (c | s) >> t + ​ + + > x = c**3 - s**3 + ​ + As one can see, the built-in definitions of sine and cosine are set up to be + odd and even respectively. + + ====Sequential vs. simultaneous substitutions==== + There is an important note on applying several substitutions at a time using the + joining of transformations. Substitutions joined with ''&''​ operator + will be applied sequentially. However, sometimes it is necessary to apply + several substitution rules "​simultaneously"​. Consider the following example: + + def X2YandY2X = '​x=y'​.t & '​y=x'​.t,​ + X2YorY2X ​ = '​x=y'​.t | '​y=x'​.t,​ + tensor = '​x+2*y'​.t ​   ​ + println X2YandY2X >> tensor + ​ + + > 3*x + ​ + + println X2YorY2X >> tensor + ​ + + > y+2*x + ​ + The first transformation (''​X2YandY2X''​) means just sequential applying + of two provided substitutions,​ while the second (''​X2YorY2X''​) + performs both substitutions "​simultaneously"​. + + + ====Constructing substitutions==== + Sometimes it is necessary to create substitution from a given l.h.s and r.h.s that are raised from other calculations (not entered "by hand"​). In order to construct such expression programmatically from a given l.h.s. and r.h.s. one can use the following syntax: + + def lhs = '​x'​.t,​ + rhs = 'a + b'.t + //this is equivalent to subs = 'x = a + b'.t + def subs = lhs.eq(rhs) + //or equivalently + subs = "$lhs =$rhs"​.t + println subs >> '​x**2'​.t + ​ + + > (a + b)**2 + ​ + + ====See also==== + * Related guides: [[documentation:​guide:​applying_and_manipulating_transformations]],​ [[documentation:​guide:​list_of_transformations]]