Welcome to Cadabra Q&A, where you can ask questions and receive answers from other members of the community.
+1 vote

Hi,

I want to do a diffrentiation w.r.t r variable of a particular expression, which i am typing below. Unfortunately i am getting some problem in the expressions. below is my code

def post_process(ex): sort_product(ex) canonicalise(ex) collect_terms(ex)

{u,r,z1,z2}::Coordinate; {a,b,c,d,e,f,g,h,i,j,k,l,m,n#}::Indices(values={z1,z2}, position=fixed);

q{a b}::Metric; q^{a b}::InverseMetric; A1{a}::Depends(u,z1,z2); A2{a}::Depends(u,z1,z2); A{a}::Depends(u,r,z1,z2); B1{a}::Depends(u,z1,z2); B2{a}::Depends(u,z1,z2); B_{a}::Depends(u,r,z1,z2);

aexp:=A{a}=((A1{a})/r) + ((A2{a})/r**2); bexp:=B{a}=((B1{a})/r) + ((B2{a})/r**2); S:=A{a} B{a};

substitute(S,aexp); substitute(_,bexp); distribute(S); collectfactors(); S*($r**4$); distribute(_); collectfactors(); diff(_,$r$);

after this i am getting an output as

$2rA{1}(DNa)B{1}(DNa)+A{1}(DNa)B{2}(DNa)+A{2}(DNa)B{1}(DNa)$

I was expecting to get

$2rA1{a}B1{a}+A1{a}B2{a}+A2{a}B1{a}$

Is this just a display issue or am i doing something wrong?

in General questions by (650 points)

1 Answer

+2 votes
 
Best answer

First an explanation of what happens here (feel free to skip): When you call diff, what you are actually doing is calling a Sympy function. In order for Sympy to act on your Cadabra expression, it will convert it to a Sympy object by calling S._sympy_(). However, that will produce a version of your expression in which tensor indices are replaced with DN+name or UP+name depending on the position. Once the diff function completes, it returns a Sympy expression, which then stays that way; it does not magically become a Cadabra Ex expression again.

So you need to define your own diff, which converts the Cadabra expression to Sympy form, applies the Sympy function, and then converts back to a Cadabra expression. That's easy,

def diff(ex1, ex2):
   ret = $@(ex1)$
   sb = SympyBridge(ret)
   sb.from_sympy( str(sympy.diff( sb.to_sympy(), ex2 ) ) )
   return ret

Then this works:

ex := A_{a}(r) r;
diff( ex, $r$ )

which produces a new Cadabra expression

$$r \partial_{r}( A_{a}(r) ) + A_{a}(r)$$

Final note: yes, functions like that really should be part of the cdb.sympy package. Lack of time...

by (82.5k points)
selected by

thank you very much.. this was really helpful.

The version currently in github has a cdb.sympy.calculus package with a diff function as above, so you can do

from cdb.sympy.calculus import diff
ex := A_{a}(r) r;
diff( ex, $r$ );
...