# strange behaviour of @substitute!(%) (bug ??)

I have to compute:

H^{a b} \nabla_{m}{\nabla_{n}{H_{r s}}} \commutator{ \commutator{\Gamma^{m}}{\Gamma_{a b}} }{\Gamma^{n r s}};


I expand the commutators:

@substitute!(%)(\commutator{ \commutator{\Gamma^{m}}{\Gamma_{a b}} }{\Gamma^{n r s}}  -> \commutator{\Gamma^{m}}{\Gamma_{a b}} \Gamma^{n r s} - \Gamma^{n r s} \commutator{\Gamma^{m}}{\Gamma_{a b}}  );
@substitute!(%)( \commutator{\Gamma^{m}}{\Gamma_{a b}}   -> \Gamma^{m} \Gamma_{a b} - \Gamma_{a b}  \Gamma^{m} );


and expand out gamma products

@distribute!(%);
@join!(%){expand};
@distribute!(%);
@join!(%){expand};
@distribute!(%);


then I want to put \gamma_{mn} = 0 (cause I am computing the trace of this object)

@substitute!(%)( \Gamma^{m n}  -> 0 );
@rename_dummies!(%);


but the result is not = 0 as it should be, the subsitution is partial only apparently!

+1 vote

I can't really judge what's causing this because you did not include your complete computation. But I suspect that your output contains factors like \Gamma^{m}_{n}, i.e. with indices not in the same position as in the substitution rule. Those kind of substitutions should in principle work when you declare your indices position=free, but Cadabra 1.x has a number of bugs which sometimes make it fail. Another reason why things may not have worked is that perhaps you did not declare all your indices to be in the same set.

Below is how I would do this in Cadabra 2.x. It's worth moving to 2.x as I do not have time anymore to do substantial work on 1.x, and all the interesting developments happen in 2.x.

The first bit is the same:

\nabla{#}::Derivative;
\delta{#}::KroneckerDelta;
{a,b,c,d,m,n,r,s,t}::Indices(position=free);
\Gamma{#}::GammaMatrix(metric=\delta);
ex:= H^{a b} \nabla_{m}{\nabla_{n}{H_{r s}}} \commutator{ \commutator{\Gamma^{m}}{\Gamma_{a b}} }{\Gamma^{n r s}};


Then substitute the commutator (much easier with patterns):

substitute(_, $\commutator{A??}{B??} -> A?? B?? - B?? A??$);


Work out the gamma products (notice the converge construction, which will apply everything in the block until the expression no longer changes):

converge(_):
distribute(_)
join_gamma(_)
eliminate_kronecker(_)
canonicalise(_)
;


Then finally setting the gammas to zero:

substitute(_, $\Gamma_{a b}->0, \Gamma_{a b c d} -> 0, \Gamma_{a b m n r s}->0$);


This does produce a zero as expected.

Thank you very much for answering!

Anyway, The result before asking to sobstitute is a sum of 4 terms containing a gamma with 2 upper indices each. After asking for the sobstitution, only 3/4 terms vanish and one ramains there, with a Gamma with both upper indices. The other part of the code is simply:

::PostDefaultRules( @@prodsort!(%), @@eliminate_kr!(%), @@canonicalise!(%),
@@collect_terms!(%) ).
{a,b,c,d,k,l,m,n,p,q,r,s,u,v,e,f,g,h,i,z}::Indices(vector).
{a,b,c,d,k,l,m,n,p,q,r,s,u,v,e,f,g,h,i,z}::Integer(0..2).
\eta_{a b}::Metric(signature=1).
\eta_{a? b?}::Symmetric.
\Gamma{#}::GammaMatrix(metric=\eta).
\delta_{m n}::KroneckerDelta.
\Gamma_{s r} \Gamma^{r}_{l} \Gamma_{k m} \Gamma^{m s};
x::Coordinate.
B_{a b}::AntiSymmetric.
H_{a b}::AntiSymmetric.
B_{a b}::Depends(x).
H_{a b}::Depends(x).
\nabla{#}::Derivative.
B_{a b}::Depends(\nabla).
H_{a b}::Depends(\nabla).
C_{a b}::AntiSymmetric.
C_{a b}::Depends(x).
C_{a b}::Depends(\nabla).


So do you suggest me to directly go for Cadabra 2.x? Is it more up-to-date (and with less bugs?)

Thank you again!

That's all fine. I have translated it to 2.x syntax for you below for convenience, folding in the suggestions I made earlier. Yes, it is definitely recommended to go for Cadabra 2.x; it is more up-to-date, has fewer bugs, and the remaining bugs will be fixed there eventually.

As far as the underscore is concerned: when you paste code into the editor, you need to mark it and then press the '{}' button to indent it all by four spaces. That will typeset the code verbatim.

{a,b,c,d,k,l,m,n,p,q,r,s,u,v,e,f,g,h,i,z}::Indices(vector).
{a,b,c,d,k,l,m,n,p,q,r,s,u,v,e,f,g,h,i,z}::Integer(0..2).
\eta_{a b}::Metric(signature=1).
\eta_{a b}::Symmetric.
\Gamma{#}::GammaMatrix(metric=\eta).
\delta_{m n}::KroneckerDelta.
ex:=\Gamma_{s r} \Gamma^{r}_{l} \Gamma_{k m} \Gamma^{m s};
x::Coordinate.
B_{a b}::AntiSymmetric.
H_{a b}::AntiSymmetric.
B_{a b}::Depends(x).
H_{a b}::Depends(x).
\nabla{#}::Derivative.
B_{a b}::Depends(\nabla{#}).
H_{a b}::Depends(\nabla{#}).
C_{a b}::AntiSymmetric.
C_{a b}::Depends(x).
C_{a b}::Depends(\nabla{#});
ex:= H^{a b} \nabla_{m}{\nabla_{n}{H_{r s}}} \commutator{ \commutator{\Gamma^{m}}{\Gamma_{a b}} }{\Gamma^{n r s}};
substitute(_, $\commutator{A??}{B??} -> A?? B?? - B?? A??$);
converge(_):
distribute(_)
join_gamma(_)
eliminate_kronecker(_)
sort_product(_)
canonicalise(_)
;
substitute(_, $\Gamma_{a b}->0$);


Hope this helps.

Sorry, the problem is still there: if I remove canonicalise from the converge structure the result is different!

Without canonicalise at the end I get zero (in 3d, with indices values 0,1,2), without canonicalise the result is different from zero

Moreover, why eliminate delta does eliminate metric with both upper/lower indices too, while eliminate metric is not working?

{a,b,c,d,k,l,m,n,p,q,r,s,u,v,e,f,g,h,i,z}::Indices(position=free);
{a,b,c,d,k,l,m,n,p,q,r,s,u,v,e,f,g,h,i,z}::Integer(0..2).
\eta_{a b}::Metric(signature=1).
\delta_{m n}::KroneckerDelta.
\eta_{a? b?}::Symmetric.
\eta_{a? b?}::InverseMetric.
\eta_{m}^{n}::KroneckerDelta.
\eta^{m}_{n}::KroneckerDelta.
x::Coordinate.
\Gamma{#}::GammaMatrix(metric=\eta).

B_{a b}::AntiSymmetric.
H_{a b}::AntiSymmetric.
B_{a b}::Depends(x).
H_{a b}::Depends(x).
\nabla{#}::Derivative.
B_{a b}::Depends(\nabla{#}).
H_{a b}::Depends(\nabla{#}).
C_{a b}::AntiSymmetric.
C_{a b}::Depends(x).
C_{a b}::Depends(\nabla{#}).

ex:= H^{a b} \nabla_{m}{\nabla_{n}{H_{r s}}} \commutator{ \commutator{\Gamma^{m}}{\Gamma_{a b}} }{\Gamma^{n r s}};

substitute(_, $\commutator{A??}{B??} -> A?? B?? - B?? A??$);
converge(_):
distribute(_)
join_gamma(_)
eliminate_kronecker(_)
;

substitute(_, $\Gamma_{a b}->0$);


This gives zero as it stands for me, without any canonicalise.

If you use position=free indices, it doesn't matter whether an index is a superscript or subscript, it will be treated the same. \eta_{m}^{n} will therefore also match \eta_{m n} and \eta^{m n}; they are all considered Kronecker deltas.

Note that if you change position=free to position=fixed and then re-run the cell, you may get unexpected results. Best to restart the kernel first to be sure.

sorry, the other way round: canonicalising gives a result different from 0. why?

If I add a canonicalise(_) as the last statement of the converge block, I get a result which is non-zero, and proportional to the unit matrix (no gamma matrices). However, it is only superficially non-zero: if you do a rename_dummies(_) on that expression, you get zero.

This is a consequence of the fact that canonicalise can reshuffle the names of dummy indices in an expression. In general, you should always let a canonicalise be followed by a rename_dummies (I may add it as an automatic feature, but I have more radical plans for the canonicalisation routines).

Wow, that a great comment. Perhaps it should be added to the manual! I often get the same issue with canonicalise.

Thank you Kasper!