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

documentation:guide:substitutions [2015/11/21 12:33] |
documentation:guide:substitutions [2015/11/21 12:33] (current) |
||
---|---|---|---|

Line 1: | Line 1: | ||

+ | ====== Substitutions ====== | ||

+ | <html> | ||

+ | <div class="text-right" style="font-size: 15px; "> | ||

+ | </html> | ||

+ | Next topic: [[documentation:guide:list_of_transformations]] | ||

+ | <html> | ||

+ | <span class="glyphicon glyphicon-arrow-right"></span> | ||

+ | </div> | ||

+ | </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: | ||

+ | <sxh groovy; gutter: false> | ||

+ | def s = 'x = x_a^a'.t | ||

+ | def t = '(x*f_a + y_a)*(x*f_b + z_b)'.t | ||

+ | println s >> t | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > (x_{d}^{d}*f_{a}+y_{a})*(x_{c}^{c}*f_{b}+z_{b}) | ||

+ | </sxh> | ||

+ | 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: | ||

+ | <sxh groovy; gutter: false> | ||

+ | 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 | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > T^{ab}*(p_{a}-q_{a})*(p_{b}+q_{b}) | ||

+ | </sxh> | ||

+ | 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: | ||

+ | <sxh groovy; gutter: true> | ||

+ | 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 | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > x_{k}*y_{a}*f^{a} | ||

+ | </sxh> | ||

+ | <sxh groovy; gutter: true; first-line: 4> | ||

+ | t = 'F_k[x_i*y_j:_ji]'.t | ||

+ | println s >> t | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > x_{a}*y_{k}*f^{a} | ||

+ | </sxh> | ||

+ | |||

+ | ====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 | ||

+ | <sxh groovy; gutter: false> | ||

+ | 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 | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > 0 | ||

+ | </sxh> | ||

+ | 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: | ||

+ | <sxh groovy; gutter: false> | ||

+ | 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 | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > 0 | ||

+ | </sxh> | ||

+ | The result is zero since tensor $(A_{cb} - A_{bc})$ is antisymmetric. As well, | ||

+ | Redberry takes care about symmetries of indexless objects: | ||

+ | <sxh groovy; gutter: false> | ||

+ | 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 | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > x = c**3 - s**3 | ||

+ | </sxh> | ||

+ | 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: | ||

+ | <sxh groovy; gutter: false> | ||

+ | def X2YandY2X = 'x=y'.t & 'y=x'.t, | ||

+ | X2YorY2X = 'x=y'.t | 'y=x'.t, | ||

+ | tensor = 'x+2*y'.t | ||

+ | println X2YandY2X >> tensor | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > 3*x | ||

+ | </sxh> | ||

+ | <sxh groovy; gutter: false> | ||

+ | println X2YorY2X >> tensor | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > y+2*x | ||

+ | </sxh> | ||

+ | 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: | ||

+ | <sxh groovy; gutter: false> | ||

+ | 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 | ||

+ | </sxh> | ||

+ | <sxh plain; gutter: false> | ||

+ | > (a + b)**2 | ||

+ | </sxh> | ||

+ | |||

+ | ====See also==== | ||

+ | * Related guides: [[documentation:guide:applying_and_manipulating_transformations]], [[documentation:guide:list_of_transformations]] | ||