Cadabra Q&A - Recent questions and answers in General questions
https://cadabra.science/qa/qa/general-questions
Powered by Question2AnswerAnswered: question about eliminate_metric
https://cadabra.science/qa/2920/question-about-eliminate_metric?show=2923#a2923
<p>Hi Eureka and Kasper.</p>
<p>Thank you K for the suggestions in solving the issue. I used your point to evaluate the code by Eureka. </p>
<p>I noted that the accent desappear when the <code>ex</code> got evaluated, unless the accent surround just the symbol <code>g</code> (wihtout the indices).</p>
<p>Here my code:</p>
<pre><code>{\mu,\nu,\rho}::Indices(vector, position=fixed).
g^{\mu\nu}::InverseMetric.
g_\mu^\nu::KroneckerDelta.
g^\mu_\nu::KroneckerDelta.
\delta{#}::Accent.
ex:=\delta{g}_{\mu\nu} g^{\nu\rho};
eliminate_metric(_);</code></pre>
<p>Best wishes,
Dox</p>General questionshttps://cadabra.science/qa/2920/question-about-eliminate_metric?show=2923#a2923Mon, 05 Aug 2024 14:26:20 +0000Answered: Factor out of numerical coefficient
https://cadabra.science/qa/2899/factor-out-of-numerical-coefficient?show=2911#a2911
<p>The main reason why you cannot factor out <em>only</em> a numerical factor is that Cadabra stores rational pre-factors in a special location (the 'multiplier') inside each node in the expression tree. </p>
<p>Cadabra will always rewrite expressions so that a <code>\sum</code> node will have a unit multiplier. So all multipliers are associated to the summands. This is a canonicalisation choice which many algorithms in Cadabra rely on, so it's not easy to change that. Similarly, all child nodes of a <code>\prod</code> node will have unit multiplier.</p>
<p>As soon as you have a product in your expression node, like in <code>6 A (B + C)</code>, the multiplier is associated to the <code>\prod</code> node. So you still have </p>
<pre><code>\prod{A}{ \sum{B}{C} }</code></pre>
<p>with a unit multiplier for the <code>\sum</code>,
but now the <code>\prod</code> node has multiplier 6.</p>General questionshttps://cadabra.science/qa/2899/factor-out-of-numerical-coefficient?show=2911#a2911Thu, 18 Jul 2024 13:30:43 +0000Answered: I'm trying to reproduce equation 4.6 from 4.5 in Carrolls Spacettime ;and Geometry
https://cadabra.science/qa/2901/trying-reproduce-equation-from-carrolls-spacettime-geometry?show=2902#a2902
<p>Hi ChuckW.</p>
<p>I ran your code, compared the output with the result reported in the book, and it seems that the result is correct.</p>
<p>The last piece of the puzzle is the use of the chain rule. I complemented your code with the following:</p>
<pre><code>chain_rule := \partial_{\lambda}{x^{\nu}} \partial_{\nu}{A??} -> \partial_{\lambda}{A??};
substitute(expr, chain_rule);</code></pre>
<p>Hope this suggestions works to complete your task.</p>
<p>Cheers,
Dox.</p>General questionshttps://cadabra.science/qa/2901/trying-reproduce-equation-from-carrolls-spacettime-geometry?show=2902#a2902Fri, 28 Jun 2024 08:24:56 +0000Answered: how to deal with lovelock gravity?
https://cadabra.science/qa/2898/how-to-deal-with-lovelock-gravity?show=2900#a2900
<p>Hi Eureka.</p>
<p>In the article <a rel="nofollow" href="https://arxiv.org/pdf/2210.00005">here</a>, we provide an algorithm to find the Lagrangian and field equations of the Lanczos--Lovelock models.</p>
<p>At the time we wrote the article going beyond $m=4$ would take a virtually infinite amount of time.</p>
<p>I invite you (or any person interested) to go through our algorithm, and we could discuss ways to improve its performance.</p>
<p>Cheers,
Dox (aka Oscar)</p>General questionshttps://cadabra.science/qa/2898/how-to-deal-with-lovelock-gravity?show=2900#a2900Mon, 24 Jun 2024 17:34:46 +0000Answered: How to copy output as tex format in jupyter notebook?
https://cadabra.science/qa/2871/how-to-copy-output-as-tex-format-in-jupyter-notebook?show=2873#a2873
<p>Hi! You can use</p>
<pre><code> ._latex_()</code></pre>
<p>method.</p>General questionshttps://cadabra.science/qa/2871/how-to-copy-output-as-tex-format-in-jupyter-notebook?show=2873#a2873Mon, 03 Jun 2024 19:32:48 +0000Answered: How can I store the result of evaluating g(.,v) as a co-vector?
https://cadabra.science/qa/2852/how-can-i-store-the-result-of-evaluating-g-v-as-a-co-vector?show=2872#a2872
<p>Hi paul.</p>
<p>Following your approach</p>
<pre><code>{m,n,a,b,c,d,q,r,s}::Indices(values={0,1}).
g_{a b}::Metric.
g^{a b}::InverseMetric.
g:=[g_{0 0}=28, g_{0 1}=2, g_{1 0}=3, g_{1 1}=-1];
v:=[v^{0}=12, v^{1}=-11];
ex:=g_{a b} v^{a};</code></pre>
<p>You can assing the evaluated expression to a variable using <code>python</code>'s notation (the <code>=</code> asignation, not the <code>:=</code> from <code>cadabra</code>)</p>
<pre><code>evaluate(ex,join(g,v), rhsonly=True);
w = _;</code></pre>
<p>If you want to loop the components of the resulting expression, I'd use (again) <code>python</code>'s notation</p>
<pre><code>import cdb.core.component as comp
for xx in range(2):
comp.get_component(w, Ex(f"{xx}"));</code></pre>
<p>Hope this would be useful.
Dox.</p>General questionshttps://cadabra.science/qa/2852/how-can-i-store-the-result-of-evaluating-g-v-as-a-co-vector?show=2872#a2872Wed, 29 May 2024 19:08:30 +0000Answered: Why does evaluate of metric eating vector shows only non-zero components.
https://cadabra.science/qa/2855/does-evaluate-metric-eating-vector-shows-only-zero-components?show=2865#a2865
<p>That's an intentional choice, as for most 'interesting' tensors, there will typically be far more zero components than non-zero components (e.g. Riemann tensors). I guess we could make it configurable, but I haven't had the need for that so far.</p>General questionshttps://cadabra.science/qa/2855/does-evaluate-metric-eating-vector-shows-only-zero-components?show=2865#a2865Sun, 19 May 2024 20:10:55 +0000Answered: Christoffel symbols computation in $d$ dimensions with split indices
https://cadabra.science/qa/2851/christoffel-symbols-computation-dimensions-split-indices?show=2861#a2861
<p>Hi again raulastur.</p>
<p>Perhaps this would be repetitive, since Arina already post an answer to your question... but Ok, we learn by asymptotic approximation!</p>
<h2>Modifications to your work</h2>
<p>As usual, you have to declare the objects and properties</p>
<pre><code>{\mu,\nu,\rho,\sigma,\kappa,\lambda,\eta,\chi#}::Indices(full, position=fixed, values={1,2,3,4}).
{A,B,C,D}::Indices(subspace, position=fixed, parent=full, values={2,3,4}).
{i,j, m,n,p,q,r,v#}::Indices(subspace2, position=fixed, parent=subspace, values={2,3}).
{s1,s2,s3}::Indices(subspace1, position=fixed, parent=subspace, values={4}).
\partial{#}::PartialDerivative.
g_{\mu\nu}::Metric.
g^{\mu\nu}::InverseMetric.
g_{\mu? \nu?}::Symmetric.
g^{\mu? \nu?}::Symmetric.
b_{i j}::Metric.
b^{i j}::InverseMetric.
{\delta^{\mu?}_{\nu?},\delta_{\mu?}^{\nu?}}::KroneckerDelta.
{b_{i j},b^{i j}}::Depends(\partial{#}).</code></pre>
<p>I wanted to keep your definitions almost untouched. </p>
<p>I've added the dependence of the $b$ field on the partial derivative (although it is not important in the following code.</p>
<p>Then, I assume that the long sequence of substitutions would be applied to other expressions as well, so instead of your approach, I prefer to define a set of substitution rules</p>
<pre><code>rl := { g_{1 m} -> 0, g_{1 4} -> 1, g_{m 1} -> 0, g_{m n} -> b_{m n}, g_{m 4} -> U_{m}, g^{4 1} -> 1,
g_{4 m} -> U_{m}, g_{4 4} -> f, g^{1 1} -> U_{m} b^{m n} U_{n} - f, g^{1 m} -> - U_{n} b^{n m}, g^{1 4} -> 1,
g^{m 1} -> - U_{n} b^{n m}, g^{m n} -> b^{n m}, g^{m 4} -> 0, g^{4 1} -> 1, g^{4 m} -> 0, g^{4 4} -> 0,
\partial_{1}{U_{m}} -> 0, \partial_{1 \mu?}{U_{m}} -> 0,
\partial_{\mu? 1}{U_{m}} -> 0, \partial_{\mu? 1}{b_{i j}} -> 0};</code></pre>
<p>Above, I changed the substitutions that used double question marks, <code>U??</code> or other.</p>
<p>Also include the Christoffel definition</p>
<pre><code>Gtog:= \Gamma^{\lambda?}_{\mu? \nu?} = (1/2) * g^{\lambda? \kappa} (\partial_{\nu?}{ g_{\kappa \mu?}}
+ \partial_{\mu?}{g_{\kappa \nu?}} + \partial_{\kappa}{g_{\mu? \nu?} } );</code></pre>
<p>Note that the summed index has to run over the <code>full</code> space, while the other indices have the question mark (<code>?</code>) to ensure that the rule could be applied to whatever type of index (like <code>4</code>).</p>
<p>Now, I define the expression to be manipulated,</p>
<pre><code>Gamma4ij := \Gamma^{4}_{i j};</code></pre>
<p>and expand the indices</p>
<pre><code>substitute(Gamma4ij, Gtog)
split_index(Gamma4ij, $\mu, 1, A$, repeat=True)
split_index(Gamma4ij, $A, i, 4$, repeat=True);</code></pre>
<p>Finally, I use the substitution rule <code>rl</code> to obtain the result:</p>
<pre><code>substitute(Gamma4ij, rl, repeat=True);</code></pre>
<p>The result I obtain is $\partial<em>1 b</em>{i j}$.</p>
<h3>Why?</h3>
<p>When you used the double question mark notation, <code>U??</code>, in the substitution rule, it would substitute not just the variable called <code>U</code>, but <em>any</em> variable. Look at this example:</p>
<pre><code>ex:=A_{m n} + B_{m n};
substitute(_, $A? + B? -> 0$ );
substitute(_, $M?? + N?? -> 0$ );</code></pre>
<p>Hope this would help you.</p>
<p>Dox</p>General questionshttps://cadabra.science/qa/2851/christoffel-symbols-computation-dimensions-split-indices?show=2861#a2861Fri, 17 May 2024 09:45:10 +0000Answered: why can't cadabra find cdb.sympy.calculus?
https://cadabra.science/qa/2845/why-cant-cadabra-find-cdb-sympy-calculus?show=2846#a2846
<p>Similar issue to your other question: upgrade to a more recent version.</p>General questionshttps://cadabra.science/qa/2845/why-cant-cadabra-find-cdb-sympy-calculus?show=2846#a2846Tue, 07 May 2024 21:00:04 +0000Answered: how to compute metric(vector,vector) or g(v,w) where g,v,w already defined without haqving to repeat the definitions.
https://cadabra.science/qa/2839/compute-metric-already-defined-without-haqving-definitions?show=2840#a2840
<p>If you have the rules <code>g</code> and <code>v</code> which define the component values, you can feed those into <code>evaluate</code>. For example, to compute $g_{a b} v^{a} v^{b}$ with the values of your example, do</p>
<pre><code>{m,n,a,b,c,d,q,r,s}::Indices(values={0,1}).
g_{a b}::Metric.
g^{a b}::InverseMetric.
g:={g_{0 0}=28, g_{0 1}=2, g_{1 0}=3, g_{1 1}=-1};
v:={v^{0}=12, v^{1}=-11};
ex:=g_{a b} v^{a} v^{b};
evaluate(ex, join(g,v));</code></pre>
<p>Does that answer your question?</p>General questionshttps://cadabra.science/qa/2839/compute-metric-already-defined-without-haqving-definitions?show=2840#a2840Tue, 07 May 2024 14:40:18 +0000Answered: How to calculate Christoffel symbols with metric defined by abstract matrices?
https://cadabra.science/qa/2780/calculate-christoffel-symbols-defined-abstract-matrices?show=2836#a2836
<p>Let me hint some ideas... although it is a not very helpful example.</p>
<p><strong>Comment 0:</strong> I'll stick to the suggested code, and not the written line-element.</p>
<h2>My suggestions</h2>
<p>Firstly, let's assing some properties</p>
<pre><code>{t,x,y,z}::Coordinate;
{\mu,\nu,\rho,\sigma,\lambda,\kappa,\chi,\gamma}::Indices(values={t,x,y,z},position=independent);
{i,j,k,l,m,n}::Indices(values={x,y,z},position=independent);
\partial{#}::PartialDerivative;
g_{\mu\nu}::Metric;
g^{\mu\nu}::InverseMetric;
h_{i j}::Metric;
h^{i j}::InverseMetric;</code></pre>
<p><strong>Comment 1:</strong> the separation between Latin and Greek indices.</p>
<p>Then, assign some dependencies,</p>
<pre><code>h_{i j}::Depends(t);
N{#}::Depends(x,y,z);</code></pre>
<p>Now, instead of trying to declare sets of components, like <code>g_{0 i}=N_i</code> for the metric, I used a detail declaration,</p>
<pre><code>ss := { g_{t t}=0,
g_{t x}=N_x,
g_{t y}=N_y,
g_{t z}=N_z,
g_{x t}=N_x,
g_{y t}=N_y,
g_{z t}=N_z,
g_{x x}=h_{x x},
g_{y y}=h_{y y},
g_{z z}=h_{z z},
g_{y z}=h_{y z},
g_{z y}=h_{y z},
};
complete(ss, $g^{\mu\nu}$);</code></pre>
<p><strong>Comment 2:</strong> for the sake of "readability" of the output, I used a simplified version of the /spacial/ submetric. If you use a complete example the output is longer.</p>
<p>Finally, you can define the Christoffel rule,</p>
<pre><code>ch:= \Gamma^{\mu}_{\nu\rho} =
1/2 g^{\mu\sigma} (
\partial_{\rho}{g_{\nu\sigma}}
+\partial_{\nu}{g_{\rho\sigma}}
-\partial_{\sigma}{g_{\nu\rho}} );</code></pre>
<p>and evaluate its components,</p>
<pre><code>evaluate(ch, ss, rhsonly=True);</code></pre>
<h3>A more complete metric</h3>
<p>Just if you want to try it</p>
<pre><code>ss := { g_{t t}=N,
g_{t x}=N_x,
g_{t y}=N_y,
g_{t z}=N_z,
g_{x t}=N_x,
g_{y t}=N_y,
g_{z t}=N_z,
g_{x x}=h_{x x},
g_{y y}=h_{y y},
g_{z z}=h_{z z},
g_{x y}=h_{x y},
g_{y x}=h_{x y},
g_{x z}=h_{x z},
g_{z x}=h_{x z},
g_{y z}=h_{y z},
g_{z y}=h_{y z},
};
complete(ss, $g^{\mu\nu}$);</code></pre>
<h3>Additional reflexions</h3>
<p>If you have evaluated the above code, you'll find that it is not very useful!</p>
<p><em>Really long expressions.</em></p>
<p>What if we don't give explicit expressions?</p>
<p><strong>TO BE CONTINUED!</strong></p>
<h2>A better method</h2>
<p>Ok, finally I came with a <em>better</em> solution.</p>
<p>Paradoxically, the <em>best</em> solution uses the <code>substitute</code> algorithm instead of the <code>evaluate</code>.</p>
<p>The problem with the above strategy is that the components have to be given explicitly, but we'd like to treat the indices like time-like and spacial.</p>
<p>Let's start with some assignation of properties:</p>
<pre><code>{t,x,y,z}::Coordinate;
{\mu,\nu,\rho,\sigma,\lambda,\kappa,\chi,\gamma}::Indices(higher, values={t,x,y,z},position=independent);
{\mu,\nu,\rho,\sigma,\lambda,\kappa,\chi,\gamma}::Integer(0..3).
{i,j,k,l,m,n}::Indices(lower, values={x,y,z},position=independent);
{i,j,k,l,m,n}::Integer(1..3);
\partial{#}::PartialDerivative;
g_{\mu\nu}::Metric(higher, signature=-1);
g^{\mu\nu}::InverseMetric(higher, signature=-1);
{g^{\mu}_{\nu},g_{\mu}^{\nu}}::KroneckerDelta(higher).
h_{i j}::Metric(lower, signature=1);
h^{i j}::InverseMetric(lower, signature=1);
{h^{i}_{j},h_{i}^{j}}::KroneckerDelta(lower).</code></pre>
<p>Then, let us define a substitution rule for the ADM decomposition of the metric and its inverse:</p>
<pre><code>ADM := { g_{t t} = - N**2 + h_{i j} N^{i} N^{j},
g_{t i} = h_{i j} N^{j},
g_{i t} = h_{i j} N^{j},
g_{i j} = h_{i j},
g^{t t} = - 1 / N**2,
g^{t i} = N^i / N**2,
g^{i t} = N^i / N**2,
g^{i j} = h^{i j} - N^{i} N^j / N**2
};
refine := { \partial_{i?}{ h_{j}^{k} } -> 0,
\partial_{i?}{ h^{k}_{j} } -> 0,};</code></pre>
<p>Note that I've defined in addition the rule <code>refine</code>, which will be useful in the next step.</p>
<p>Finally, we want to manipulate (not calculate) each component of the metric connection. My strategy would be to loop over the values of the free indices. <code>cadabra</code> uses the command <code>Ex</code> to convert a (formatted python) string into a cadabra expression. <strong>Comment 3:</strong> since curly brackets are used to call a variable within a f-string, other curly brackets have to be escaped (with double curly bracket, with makes the expressions messy).</p>
<pre><code>for mu in ["t", "i"]:
for nu in ["t", "j"]:
for rho in ["t", "k"]:
Ex(f"\Gamma^{{{mu}}}_{{{nu}{rho}}} = ");
foo = Ex(f"1/2 g^{{{mu} \sigma}} (\partial_{{{rho}}}{{ g_{{{nu} \sigma}} }} + \partial_{{{nu}}}{{ g_{{{rho} \sigma}} }} - \partial_{{\sigma}}{{ g_{{{nu} {rho}}} }})");
split_index(foo, $\mu,t,m$, repeat=True)
substitute(foo, ADM, repeat=True)
distribute(foo)
product_rule(foo)
distribute(foo)
eliminate_metric(foo)
eliminate_kronecker(foo)
sort_product(foo)
rename_dummies(foo)
substitute(foo, refine, repeat=True);
# meld(foo);</code></pre>
<p>Hope this latter method would help you!</p>
<p>Cheers,
Dox.</p>General questionshttps://cadabra.science/qa/2780/calculate-christoffel-symbols-defined-abstract-matrices?show=2836#a2836Fri, 26 Apr 2024 09:19:59 +0000convert other format to cadabra2 format
https://cadabra.science/qa/2833/convert-other-format-to-cadabra2-format
<p>From <a rel="nofollow" href="https://cadabra.science/notebooks/scalar_manipulations.html">Using Cadabra and Sympy together</a>, I learn how to convert cadabra2 format to sympy format, but how to do the reverse operation? I.e. How to convert other formals, e.g. sympy format, to cadabra2 format?</p>General questionshttps://cadabra.science/qa/2833/convert-other-format-to-cadabra2-formatWed, 24 Apr 2024 13:31:05 +0000Answered: function expand_power not work for fractional power
https://cadabra.science/qa/2804/function-expand_power-not-work-for-fractional-power?show=2832#a2832
<p>I found a way to do it. One can use function <code>refine</code> in sympy, for example,</p>
<pre><code>from sympy import refine, sqrt, Q
from sympy.abc import L
ex:=(\lambda**{-2})**{1/2};
substitute(_,$\lambda->L$);
refine(_._sympy_(), Q.positive(L));</code></pre>
<p>But there is an another question: How to transform sympy expression to cadabra2 expression?</p>General questionshttps://cadabra.science/qa/2804/function-expand_power-not-work-for-fractional-power?show=2832#a2832Wed, 24 Apr 2024 13:16:26 +0000question about keep_weight
https://cadabra.science/qa/2814/question-about-keep_weight
<p>In the following code,</p>
<pre><code>{u,v,x}::Coordinate.
f::Coordinate.
{a,b,c,d,e,g,h,p,r#}::Indices(full,values={u,v,x},position=independent).
\partial{#}::PartialDerivative.
\nabla{#}::Derivative.
g_{a b}::Metric.
g^{a b}::InverseMetric.
g_a^b::KroneckerDelta.
g^a_b::KroneckerDelta.
g^{a b}::Symmetric.
g_{a b}::Symmetric.
{n_u,n_v,\gamma,w,\alpha,\lambda,A,B,C}::Depends({u,v,f,x}).
{u,v}::Weight(label=field,value=1);
{f}::Weight(label=field,value=2);
metric:={g_{u v}=1,
g_{v u}=1,g_{v v}=-u**2\alpha,g_{v x}=u w,
g_{x v}=u w,g_{x x}=\gamma};
complete(_,$g^{a b}$);
from cdb.sympy.calculus import *
lamb:=(g^{a b}\partial_a{u v}\partial_b{u v})**{-1/2} ;
evaluate(_,metric,rhsonly=True);
substitute(_,$v->f/u$)
simplify(_);
substitute(_,$\alpha->a,w**2\gamma**{-1}->b$);
series(_,$f$,0,5/2);
substitute(_,$\bigO(A??)->0$)
keep_weight(_,$field=1$);</code></pre>
<p>The final result is not right. There seems to be something wrong here.</p>General questionshttps://cadabra.science/qa/2814/question-about-keep_weightFri, 19 Apr 2024 03:46:06 +0000Answered: Error printing as mma format
https://cadabra.science/qa/2776/error-printing-as-mma-format?show=2798#a2798
<p>As I said, the MicroTeX branch is work in progress.</p>
<p>You can always copy an expression to the clipboard by using the <code>pyperclip</code> package. For instance,</p>
<pre><code>import pyperclip
ex:=A_{m n};
pyperclip.copy( ex.mma_form() )</code></pre>General questionshttps://cadabra.science/qa/2776/error-printing-as-mma-format?show=2798#a2798Thu, 18 Apr 2024 09:01:10 +0000Answered: Formula rendering in jupyter notebook 7 and jupyter lab
https://cadabra.science/qa/2773/formula-rendering-in-jupyter-notebook-7-and-jupyter-lab?show=2779#a2779
<p>According to <a rel="nofollow" href="https://docs.mathjax.org/en/latest/output/linebreaks.html">https://docs.mathjax.org/en/latest/output/linebreaks.html</a>, automatic line breaking is not yet implemented in MathJax 3. I do not know if that web page is the current status, but it would explain why formulas do not wrap.</p>General questionshttps://cadabra.science/qa/2773/formula-rendering-in-jupyter-notebook-7-and-jupyter-lab?show=2779#a2779Sat, 13 Apr 2024 13:04:45 +0000Question about Gaussian normal coordinate
https://cadabra.science/qa/2774/question-about-gaussian-normal-coordinate
<p>When I do calculation under Gaussian normal coordinate:</p>
<p>$$
d s^2=-2 d u d v-u^2\alpha(x) d v^2-2u w_i(x) dv dx^i+\gamma_{ij}(x) d x^i d x^j\,\quad x=(uv\,,x^i)
$$</p>
<p>How to get inverse metric and others directly? I don't know how to deal with $w_i$ and $\gamma_{ij}$.</p>General questionshttps://cadabra.science/qa/2774/question-about-gaussian-normal-coordinateThu, 11 Apr 2024 07:20:30 +0000Answered: The Solution of Einstein's Equation in General Dimensions
https://cadabra.science/qa/2492/the-solution-of-einsteins-equation-in-general-dimensions?show=2760#a2760
<p>The following code should be useful:</p>
<pre><code>{M,N,O,P,Q,R,S}::Indices(full, position=independent);
{\alpha,\beta,\mu,\nu,\sigma,\gamma,\lambda}::Indices(subspace1, position=independent, parent=full);
{\alpha,\beta,\mu,\nu,\sigma,\gamma,\lambda}::Integer(0..d-1).
w::Coordinate;
g_{\mu\nu}::Metric.
g^{\mu\nu}::InverseMetric.
g_{\mu\nu}::Symmetric.
g^{\mu\nu}::Symmetric.
g^{\mu}_{\nu}::KroneckerDelta.
g_{\mu}^{\nu}::KroneckerDelta.
from cdb.utils.indices import *
ex:=g_{M N} g^{M O} P^N;
replace_index(_,r"g",r'O',r'\mu');
split_index(_, $M,\mu,w$,repeat=True);
eliminate_metric(_);
eliminate_kronecker(_);
substitute(_,$P^w->A$);</code></pre>General questionshttps://cadabra.science/qa/2492/the-solution-of-einsteins-equation-in-general-dimensions?show=2760#a2760Thu, 21 Mar 2024 09:13:37 +0000Answered: how to swap indices for partial derivatives
https://cadabra.science/qa/2750/how-to-swap-indices-for-partial-derivatives?show=2751#a2751
<p>Hi bin_go.</p>
<p>I'm noting there is plenty of space in your code to improve, but I'm not here for that (in particular because I don't know your workcase scenario).</p>
<p>So, let me illustrate the use of the algorithm <code>indexsort</code> with an example inspired in your code.</p>
<h2>My example</h2>
<p>First, I'll define the indices and the symbol for the partial derivative.</p>
<pre><code>{a,b,c,d}::Indices("flat",position = free).
{a,b,c,d}::Integer(1..N).
\partial{#}::PartialDerivative.</code></pre>
<p>In this example, I'd define some functions of the "coordinates", but saying that they depends on the derivative</p>
<pre><code>{z,w,v{#}}::Depends(\partial{#});</code></pre>
<p>Define the expression</p>
<pre><code> ex := 2 \chi w**(3) M**(\xi+1) \delta{z}
\partial_{a b}{z} \partial_{a c d}{z} v_{b} v_{c} v_{d} -
2 \chi w**(3) M**(\xi+1) \delta{z}
\partial_{a b}{z} \partial_{c d a}{z} v_{b} v_{c} v_{d};</code></pre>
<p>Note that the result is not simplified, unless we sort the indices</p>
<pre><code> indexsort(ex);</code></pre>
<p>Hope this would help.</p>
<p>Cheers,
Dox.</p>General questionshttps://cadabra.science/qa/2750/how-to-swap-indices-for-partial-derivatives?show=2751#a2751Wed, 20 Mar 2024 08:25:07 +0000Answered: Hello i am a beginner in using Cadabra 2
https://cadabra.science/qa/2747/hello-i-am-a-beginner-in-using-cadabra-2?show=2748#a2748
<p>This means that the indices on the left-hand side and the right-hand side of a replacement rule do not match. For instance,</p>
<pre><code>ex:=A_{m n};
substitute(ex, $A_{m n} = B_{m}$);</code></pre>
<p>You would mess up your equations if it would allow such substitutions.</p>
<p>You <em>can</em> do this if you really want to, by using the <code>-></code> notation,</p>
<pre><code>substitute(ex, $A_{m n} -> B_{m}$);</code></pre>
<p>This will work (but may of course still be wrong).</p>
<p>If you don't get the error from something like this, please post a minimal example.</p>General questionshttps://cadabra.science/qa/2747/hello-i-am-a-beginner-in-using-cadabra-2?show=2748#a2748Sat, 16 Mar 2024 19:45:48 +0000How to create derivatives of coordinates with indices?
https://cadabra.science/qa/2738/how-to-create-derivatives-of-coordinates-with-indices
<p>I have two sets of coordinates, and two partial derivatives which can act on these coordinates. These should work in a way such that:</p>
<p>$$
\partial_{x^{\mu}} x^{\nu} = \delta_{\mu}^{\nu} = \partial_{a<em>{\nu}} a\</em>{\mu}.
$$</p>
<p>How would I go about implementing this in Cadabra? I've tried defining partial derivatives of corresponding coordinates directly, I've tried using notation like DX and DA to differentiate between the two and then using LaTeXform to make it more tidy but I inadvertently run into a stop of some sort. </p>
<p>Any and all help will be greatly appreciated!</p>General questionshttps://cadabra.science/qa/2738/how-to-create-derivatives-of-coordinates-with-indicesThu, 15 Feb 2024 17:28:42 +0000Answered: derivatives with two indices
https://cadabra.science/qa/2729/derivatives-with-two-indices?show=2732#a2732
<p>If <code>\partial_{G P}{...}</code> really indicates a single derivative (e.g. <code>G</code> and <code>P</code> are spinor indices obtained from a vector index with the use of a Pauli matrix or something like that), then it may make sense to revert to single-index notation temporarily.</p>
<p>Alternatively, just write a substitution rule, e.g.</p>
<pre><code>{G,P,M,N,K,L}::Indices;
\partial{#}::PartialDerivative;
test:=\partial_{G P}{A_{M N}*A^{K L}};
pr:= \partial_{G P}{A?? B??} = \partial_{G P}{A??} B??
+ A?? \partial_{G P}{B??};
substitute(test, pr);</code></pre>
<p>Cadabra does not have functionality to treat multiple indices as one out-of-the-box at the moment.</p>General questionshttps://cadabra.science/qa/2729/derivatives-with-two-indices?show=2732#a2732Thu, 18 Jan 2024 11:23:35 +0000Answered: evaluate() returns RuntimeError when using the explicit value of an index
https://cadabra.science/qa/2710/evaluate-returns-runtimeerror-using-explicit-value-index?show=2720#a2720
<p>In line with Kasper's comment, here is a solution with all index locations filled with indices, not values. I post it here in the hope it helps someone else, until the issue is fixed.</p>
<p>Instead of calculating explcitly the <code>K_1 e_1</code> multiplication do the more general <code>K_i e_j</code> multiplication, as follows:</p>
<pre><code>d = 3
{i,j,k,l,m,n}::Indices(rotation, values={1..3}).
\epsilon{#}::EpsilonTensor.
ex := K_{i j m} = \epsilon_{i m n} e_{j}_{n};
s = 'e_{1}_{1} = 1, e_{1}_{2} = 0, e_{1}_{3} = 0,' + \
'e_{2}_{1} = 0, e_{2}_{2} = 1, e_{2}_{3} = 0,' + \
'e_{3}_{1} = 0, e_{3}_{2} = 0, e_{3}_{3} = 1'
Ex(s);
evaluate(ex, Ex(s), rhsonly=True);</code></pre>
<p>This works and you can then pick out the <code>K_1 e_1</code> matrix elements: they are the <code>1,m,1</code> elements in the result (with <code>m</code> any of <code>{1,2,3}</code>). (as it happens, they vanish, which is the correct result).</p>
<p>GPN</p>General questionshttps://cadabra.science/qa/2710/evaluate-returns-runtimeerror-using-explicit-value-index?show=2720#a2720Tue, 09 Jan 2024 09:34:59 +0000Answered: How do I use object properties in a python executable?
https://cadabra.science/qa/2711/how-do-i-use-object-properties-in-a-python-executable?show=2712#a2712
<p>Use the following:</p>
<pre><code>import cadabra2 as cad
cad.Indices(cad.Ex("[a,b,c,d]"),
cad.Ex("name=spacetime, position=independent"))</code></pre>
<p>The <code>Indices</code> function takes two Cadabra expression <code>Ex</code> objects. The first is the list of indices, the second all the arguments.</p>General questionshttps://cadabra.science/qa/2711/how-do-i-use-object-properties-in-a-python-executable?show=2712#a2712Sat, 06 Jan 2024 12:12:11 +0000Answered: Simplification of sum of terms r a^m + s a^m to (r+s)a^m
https://cadabra.science/qa/2707/simplification-of-sum-of-terms-r-a-m-s-a-m-to-r-s-a-m?show=2708#a2708
<p>The problem in your code arises because <code>b^{4}</code> is not the same as <code>b**4</code>. If you do <code>print(tree(ex))</code> on the output, you can see that one of the terms has <code>b^{4}</code> and the other <code>b**4</code> (represented as <code>\pow{b}{4}</code>.</p>
<p>You can solve this in various ways. One way is to convert the <code>b**4</code> to <code>b^{4}</code> with another rule. But since you really mean a power, perhaps a quicker way to achieve the wanted result is to use powers everywhere, not superscripts:</p>
<pre><code>a::Symbol;
b::Symbol;
{a**m?, b**n?, a, b}::NonCommuting;
{m,n,r,s}::Integer.
r1 := {
a b**m? -> (1+b a) b**{m?-1},
a b -> 1 + b a,
};
def act(ex):
converge(ex):
substitute(ex,r1)
distribute(ex)
collect_factors(ex)
return ex
act($a b**5$);</code></pre>
<p>I have cut out a few other unnecessary steps in your <code>act</code> function (you don't need to call <code>collect_terms</code> to collect terms in an exponent, and you also never need to call the brute force hammer <code>simplify</code> unless you need a simplification for which SymPy is needed).</p>General questionshttps://cadabra.science/qa/2707/simplification-of-sum-of-terms-r-a-m-s-a-m-to-r-s-a-m?show=2708#a2708Mon, 01 Jan 2024 20:59:09 +0000Answered: Display "hand-made" latex
https://cadabra.science/qa/2702/display-hand-made-latex?show=2703#a2703
<p>Timely question ;-) I have <em>just</em> pushed a change to github which allows you to do</p>
<pre><code>s = LaTeXString(
r'\begin{array}{lll}'
r' 0 & 0 & 0 \\'
r' 0 & 0 & 1 \\'
r' 0 & -1 & 0'
r'\end{array}'
)
s;</code></pre>
<p>which will then show (in cadabra2-gtk and the jupyter frontend) the typeset result. </p>
<p>In other words, this is like a normal string, but with information that the content can be processed as LaTeX.</p>General questionshttps://cadabra.science/qa/2702/display-hand-made-latex?show=2703#a2703Fri, 29 Dec 2023 14:10:52 +0000Answered: Replacing expressions in a matrix
https://cadabra.science/qa/2700/replacing-expressions-in-a-matrix?show=2701#a2701
<p>Some answers I gathered in the hope they help others.</p>
<p>Answer #1:</p>
<p>The following code isn't pretty, but it solves issue #1 by creating a python matrix and storing values into that matrix..</p>
<pre><code>from cdb.core.component import *
from cdb.utils.node import *
d = 3
{k,l,m,n}::Indices(rotation, values={1..3}).
\epsilon{#}::EpsilonTensor.
Kl := (K_{l})_{m n} = \epsilon_{l m n};
evaluate(Kl, rhsonly=True);
mat = [[0 for _ in range(d)] for _ in range(d)]
for ex in Kl[r'\equals']:
lhs = get_lhs(ex.ex())
rhs = get_rhs(ex.ex())
if ${a?,b?,c?}$.matches(lhs):
n = int(str(nth_arg(lhs,0)))
if n == 1:
i = int(str(nth_arg(lhs,1)))
j = int(str(nth_arg(lhs,2)))
mat[i-1][j-1] = str(rhs)</code></pre>
<p>After this, depending on your use case, you can, e.g. turn the matrix into a string and display the string in a LaTeX format, as follows.</p>
<p>Answer #2: beginning in version <code>2.4.5.2</code>, the following (using the new feature <code>LaTeXString</code>) works:</p>
<pre><code>K1 = r'\left[ \begin{array}{cc} '
for i in range(d):
for j in range(d):
if j%d > 0: K1 += ' & '
K1 += str(mat[i][j])
if i%d < d-1: K1 += r' \\'
K1 += r' '
else:
K1 += r'\end{array} \right]'
LaTeXString(K1);</code></pre>
<p>Good luck</p>General questionshttps://cadabra.science/qa/2700/replacing-expressions-in-a-matrix?show=2701#a2701Wed, 27 Dec 2023 19:54:04 +0000Answered: Displaying a matrix with matplotlib error "non-GUI backend"
https://cadabra.science/qa/2698/displaying-a-matrix-with-matplotlib-error-non-gui-backend?show=2699#a2699
<p>Cadabra doesn't use <code>plt.show()</code>. Just display the <code>fig</code> object with</p>
<pre><code>fig;</code></pre>
<p>or</p>
<pre><code>display(fig)</code></pre>General questionshttps://cadabra.science/qa/2698/displaying-a-matrix-with-matplotlib-error-non-gui-backend?show=2699#a2699Mon, 25 Dec 2023 18:48:01 +0000Answered: Displaying components of the epsilon matrix
https://cadabra.science/qa/2696/displaying-components-of-the-epsilon-matrix?show=2697#a2697
<p>Tensors do not have component values by default in Cadabra. You typically write down some tensor expression in abstract form (like that <code>Ki</code> line of yours) and then <code>evaluate</code> the components of that expression by making use of implicit or explicit rules about the components of the tensors that make up this expression.</p>
<p>In your case, try something like</p>
<pre><code>from cdb.core.component import *
{i,j,k,l,m,n}::Indices(topological, values={1,2,3}).
\epsilon{#}::EpsilonTensor.
Ki := (K_{i})_{m n} = \epsilon_{i m n}.
evaluate(Ki, rhsonly=True);
get_component(Ki, $1, 2, 3$);</code></pre>
<p>Note that I have also added the range of the indices.</p>
<p>There isn't anything simple at the moment to get a two-index object in the form of a matrix, unfortunately.</p>General questionshttps://cadabra.science/qa/2696/displaying-components-of-the-epsilon-matrix?show=2697#a2697Sun, 24 Dec 2023 23:16:23 +0000Answered: LaTeXForm expansion fails with "free indices do not match"
https://cadabra.science/qa/2692/latexform-expansion-fails-with-free-indices-do-not-match?show=2693#a2693
<p>That message says that the left-hand side ($\sigma_{\beta}$) does not have the same free indices as the right-hand side. As it stands, the right-hand side does not have any free indices, as functional arguments (things which do not have a sub- or super-script symbol) do not propagate their indices outside the function. </p>
<p>If you add</p>
<pre><code>inner{a?? b??}::IndexInherit.</code></pre>
<p>then the index $\beta$ on the $e_\beta$ inside <code>inner</code> will be 'visible' on the outside of <code>inner</code>, and things match up.</p>General questionshttps://cadabra.science/qa/2692/latexform-expansion-fails-with-free-indices-do-not-match?show=2693#a2693Fri, 22 Dec 2023 13:31:08 +0000Answered: How to collect terms containing derivatives
https://cadabra.science/qa/2680/how-to-collect-terms-containing-derivatives?show=2691#a2691
<p>Hi alonli!</p>
<p>The notation you're using makes me think that you've read our article. If so, thank you very much! It is awesome to note that our work benefits other researchers.</p>
<p>Now, I understand that what you're providing in the question is (probably) a simple example of what you really want to do. However, there are many manipulations that are doing nothing (including the indiscriminate use of the algorithm <code>canonicalise</code>, which is slow because it tries many "simplification" algorithms).</p>
<p>I came out with a shorter list of algorithms that work better in your example (you might have to modify it to fit your necessities):</p>
<pre><code>{a#,b#}::Indices.
\delta{#}::KroneckerDelta.
{a#,b#}::Integer(0..3)
\partial{#}::PartialDerivative.
\epsilon{#}::EpsilonTensor(delta=-\delta).
h_{a1 b1}::Symmetric.
toh := {h_{a1 a1} = h, h_{a1}^{a1} = h}.
def LLmanip(ex):
expand_delta(ex)
distribute(ex)
eliminate_kronecker(ex)
substitute(ex, toh)
sort_product(ex)
rename_dummies(ex)
lower_free_indices(ex)
meld(ex)
rename_dummies(ex)
return ex
LL := \delta^{a1 b1 a2 b2 a3 b3 a4 b4} \partial_{a1}{h_{a2 b2}} \partial_{b1}{h_{a3 b3}} h_{a4 b4};
LLmanip(LL);</code></pre>
<p>I want to drive your attention to the single use of the algorithm <code>meld</code> intead of several <code>canonicalise</code>, single <code>sort_product</code> and <code>rename_dummies</code>, and the lack of the <code>sort_sum</code> (perhaps you might still want it there).</p>
<p>I know that it is useful to define functions for general purpose manipulations, but it is important to keep them "optimal", because once your expressions start to get a bit complex, the functions become very time consuming.</p>
<p>Cheers,
Dox.</p>General questionshttps://cadabra.science/qa/2680/how-to-collect-terms-containing-derivatives?show=2691#a2691Mon, 18 Dec 2023 09:30:53 +0000Answered: Partial derivative of a vector
https://cadabra.science/qa/2669/partial-derivative-of-a-vector?show=2670#a2670
<p>Whenever you <code>evaluate</code>, the expression should not contain derivatives, otherwise simplification by sympy will throw that error. But you can turn that off, so the following does what you want:</p>
<pre><code>\partial{#}::PartialDerivative;
{t,x,y,z}::Coordinate;
{\mu, \nu}::Indices(values={t,x,y,z});
A^{\mu}::Depends(\partial{#});
dA:=\partial_{\mu}{ A^{\mu} };
evaluate(dA, simplify=False);</code></pre>
<p>If you replace the last two lines with</p>
<pre><code>dA:=\partial_{\mu}{ A^{\nu} };
evaluate(dA, simplify=False);</code></pre>
<p>you get that 2x2 expression.</p>General questionshttps://cadabra.science/qa/2669/partial-derivative-of-a-vector?show=2670#a2670Wed, 06 Dec 2023 14:09:56 +0000Answered: A vector-field basis of derivatives?
https://cadabra.science/qa/2665/a-vector-field-basis-of-derivatives?show=2667#a2667
<p>@dbutter thank you! I applied your advice and here is what I got. I think some useful ideas are:</p>
<ul>
<li>define a new class <code>VectorField</code></li>
<li>define the operation <code>v(f)</code>, where <code>v</code> is a vector field and <code>f</code> is a scalar field, as a python <code>__call__</code></li>
</ul>
<p>I hope this helps someone additional.</p>
<pre><code>from cdb.core.manip import multiply_through
\partial{#}::PartialDerivative;
{\mu,\nu}::Indices(spacetime,position=fixed);
{f,}::Depends(\partial{#});
{u^{\mu},v^{\mu}, \partial_{\nu}{f}, \partial_{\mu\nu}{f}, e_{\nu}, f, (1/f)}::SortOrder;
def find_first_index(v):
for ix in v.top().free_indices():
if ix.parent_rel==super:
return ix
raise TypeError(f'{0} has no contravariant index')
class VectorField:
def __init__(self, v: Ex):
self.v = v
def __call__(self, s: Ex):
return self.of_scalar(s)
def of_scalar(self,s):
ix = find_first_index(self.v)
ex = self.v
return $@(ex) \partial_{@(ix)}{@(s)}$
u = VectorField($u^{\mu}$)
v = VectorField($v^{\mu}$)
f := f.
lhs := \commutator{u}{v} f ;
rhs = u(v(f)) - v(u(f));
ex := @(lhs) = @(rhs);
product_rule(ex);
distribute(ex);
sort_product(ex);
meld(ex);
factor_out(ex,$\partial_{\nu}{f}$, right=True);
substitute(ex, $\partial_{\nu}{f} -> e_{\nu} f$);
multiply_through(ex, $1/f$)
collect_factors(ex);</code></pre>
<p>Thanks
GPN</p>General questionshttps://cadabra.science/qa/2665/a-vector-field-basis-of-derivatives?show=2667#a2667Tue, 05 Dec 2023 10:41:44 +0000Answered: Is eliminate_metric supposed to move partial derivative indices?
https://cadabra.science/qa/2508/eliminate_metric-supposed-move-partial-derivative-indices?show=2664#a2664
<p>I did not find a way to do exactly what you want. But here is an alternative. Define <code>\nabla</code> as a <code>Derivative</code> or <code>PartialDerivative</code>.</p>
<pre><code>{\mu, \nu}::Indices(position=independent).
\partial{#}::PartialDerivative.
g_{\mu \nu}::Metric.
g^{\mu \nu}::InverseMetric.
g_{\mu}^{\nu}::KroneckerDelta.
g^{\mu}_{\nu}::KroneckerDelta.
g_{\mu \nu}::Depends(\partial{#}).
g^{\mu \nu}::Depends(\partial{#}).
\nabla{#}::PartialDerivative.
\nabla{#}::Depends(\partial{#}).
expr:=g^{\mu \nu}\nabla_{\nu}{A_{\mu}};
eliminate_metric(_);</code></pre>
<p>The crucial point is that the covariant derivative of the metric is 0, so you do <em>not</em> need to add</p>
<pre><code>g_{\mu \nu}::Depends(\nabla{#}).
g^{\mu \nu}::Depends(\nabla{#}).
</code></pre>
<p>As a result the metric "passes through" the <code>\nabla</code> derivative operator. I hope this helps.</p>
<p>GPN</p>General questionshttps://cadabra.science/qa/2508/eliminate_metric-supposed-move-partial-derivative-indices?show=2664#a2664Mon, 04 Dec 2023 22:15:18 +0000Answered: Avoiding index classes when handling ExNodes
https://cadabra.science/qa/2653/avoiding-index-classes-when-handling-exnodes?show=2661#a2661
<p>Here is a solution that solves some of these issues:</p>
<pre><code>{a,b,c,d,a#}::Indices(vector).
{i,j,k,l,i#}::Indices(isospin).
\nabla{#}::Derivative.
\partial{#}::PartialDerivative.
def expand_nabla(ex):
for nabla in ex[r'\nabla']:
nabla.name=r'\partial'
dindex = nabla.indices().__next__()
for arg in nabla.args():
ret:=0;
for index in arg.free_indices():
indexprop = Indices.get(index, ignore_parent_rel = True)
if indexprop.set_name == 'vector':
t2:= @(arg);
dummy = indexprop.get_dummy(ex)
if index.parent_rel==sub:
t1:= -\Gamma^{@(dummy)}_{@(dindex) @(index)};
t2[index]:= _{@(dummy)};
else:
t1:= \Gamma^{@(index)}_{@(dindex) @(dummy)};
t2[index]:= ^{@(dummy)};
ret += Ex(str(nabla.multiplier)) * t1 * t2
nabla += ret
return ex</code></pre>
<p>This version grabs a dummy index by looking at the entire expression tree, while in practice, we might just want to look at the term in the top-level sum. It knows to ignore isospin indices and only grab vector indices. We also need \nabla and \partial to have IndexInherit (inherited from Derivative). </p>General questionshttps://cadabra.science/qa/2653/avoiding-index-classes-when-handling-exnodes?show=2661#a2661Sun, 03 Dec 2023 14:22:53 +0000Answered: How to get the `weight` value of an object?
https://cadabra.science/qa/2440/how-to-get-the-weight-value-of-an-object?show=2652#a2652
<p>I have pushed a fix based on dbutter's suggestion, so in short, you can now do</p>
<pre><code>x::Weight(value=1, label=field);
weight = Weight.get($x$, label="field").value("field")</code></pre>
<p>to get the weight on the Python side.</p>General questionshttps://cadabra.science/qa/2440/how-to-get-the-weight-value-of-an-object?show=2652#a2652Fri, 01 Dec 2023 20:13:45 +0000Efficiency in python vs cadabra for long substitution rules
https://cadabra.science/qa/2643/efficiency-in-python-vs-cadabra-for-long-substitution-rules
<p>I am applying a list of complicated substitution rules in cadabra. Schematically, these rules look like A_{i} -> (long expression) for some number (say 100) of the A_i. But the expression is very long.</p>
<p>I find that there is a surprising amount of time communicating with the Cadabra server in trying to apply these rules, versus looking for the rule myself.</p>
<p>Here is a sample code:</p>
<pre><code>megasum := x+y.
for i in range(10000):
megasum.top().append_child(Ex( r'B'+str(i) ))
rules = []
for i in range(100):
rules.append(Ex( r'A'+str(i)+'-> @(megasum)' ))
cdbrules = ListToExList(rules)</code></pre>
<p>All the rules in lst are of the form A_i (from A0 to A99) going to the same giant sum. Then I use my Python function ListToExList to convert a Python list to a cadabra list.</p>
<p>On my laptop, the command</p>
<pre><code>substitute($A0$, cdbrules)</code></pre>
<p>requires about 600,000 us to run, and it appears independent of whether I give it A0 to act on or A99.</p>
<p>On the other hand, if on the Python side, I manually search the list for a rule that applies, it seems to run in about 60,000 us (in the worst case) and 5,000 us (in the best case) depending on if I find the rule quickly or not. A simple implementation:</p>
<pre><code>ex := A0.
for i in range(len(keys)):
if keys[i].matches(ex):
substitute(ex, rules[i])
break
</code></pre>
<p>where keys is a list of the LHS of the rules.</p>
<p>I'm trying to understand where the hangup is. My first thought is that Python has to be communicating the entire gargantuan cdbrules, and this is the bottleneck. However, I had the sense from the code that pointers are being used (or aliases to the objects) so that no actual copying is occurring. Does anyone have any ideas?</p>
<p>Apologies in advance for the rather ill-defined question...</p>General questionshttps://cadabra.science/qa/2643/efficiency-in-python-vs-cadabra-for-long-substitution-rulesThu, 30 Nov 2023 19:00:07 +0000Answered: Trigonometric and hyperbolic functions
https://cadabra.science/qa/2635/trigonometric-and-hyperbolic-functions?show=2641#a2641
<p>Hi Ariana,</p>
<p>In principle the manipulation of functions within <code>cadabra</code> is made through <code>SymPy</code>. Hence, one could use (supposedly) any function recognised by <code>SymPy</code>, e.g. <code>\sinh</code>, <code>\cosh</code>, <code>\tanh</code>, etc.</p>
<p>However, <code>cadabra</code> does not necessarily know how to handle the output returned by <code>SymPy</code>, particularly because <code>cadabra</code> expressions are rendered as <code>LaTeX</code> expressions... translated by a "dictionary". If the "dictionary" does not have the function you want, you'll get errors in your notebook.</p>
<p>So, the manipulation of functions is limited by the size of the "dictionary".</p>
<p>I recommend you to see the GitHub page of <a rel="nofollow" href="https://github.com/kpeeters/cadabra2/blob/master/core/DisplaySympy.cc">DisplaySympy</a>, in particular the definition <code>DisplaySympy::DisplaySympy</code></p>
<p>Dox.</p>General questionshttps://cadabra.science/qa/2635/trigonometric-and-hyperbolic-functions?show=2641#a2641Thu, 30 Nov 2023 08:37:08 +0000Hodge dual in exterior calculus
https://cadabra.science/qa/2637/hodge-dual-in-exterior-calculus
<p>I am new to Cadabra and want to derive the Maxwell equations using exterior calculus. I've looked at the tutorials and searched the reference manual but I cannot figure out how to express the Hodge dual.</p>
<p>-erik</p>General questionshttps://cadabra.science/qa/2637/hodge-dual-in-exterior-calculusWed, 29 Nov 2023 18:40:35 +0000Answered: How AntiCommuting information is stored
https://cadabra.science/qa/2609/how-anticommuting-information-is-stored?show=2610#a2610
<p>None of the above ;-) </p>
<p>First, remember that this is all stored on the C++ side. All properties are stored in two ways: a map from patterns to property objects, and a map from property objects to patterns. So for</p>
<p><code>{F1, F2, F3}::AntiCommuting</code></p>
<p>there is a map <code>props</code> which contains</p>
<pre><code>F1 -> A1
F2 -> A1
F3 -> A1</code></pre>
<p>where <code>A1</code> is an instance of the property object <code>AntiCommuting</code>. And there is a map <code>pats</code> which contains</p>
<pre><code>A1 -> F1
A1 -> F2
A1 -> F3</code></pre>
<p>(so an ordered multi-map, to be precise). </p>
<p>Now the <code>properties</code> object which contains all this has methods to find a shared <code>AntiCommuting</code> object for two given patterns. So you can ask it "Do F1 and F2 have an AntiCommuting property in common?". </p>
<p>(This all looks terribly complicated until you start to build in property inheritance and the like, when simpler solutions tend to be insufficient). </p>
<p>Now most of this is not easily accessible on the Python side because it was written long before I added the Python wrapper on top of the C++ core. Your solution (of repeating the list property declaration) is by far the simplest. Of course if you run into something that cannot be done that way.</p>
<p>Unfortunately, while there is a way to retrieve property information for an expression using <code>[PropertyName].get(...)</code>, you cannot use this to check whether to elements are in the same list (yet). So if you do</p>
<pre><code>{F1, F2}::AntiCommuting;
p1 = AntiCommuting.get($F1$)
p2 = AntiCommuting.get($F2$)
p1 == p2</code></pre>
<p>you get <code>False</code>, and there is no</p>
<pre><code>p = AntiCommuting($F1$, $F2$)</code></pre>
<p>yet either (which would probably be the easiest way out).</p>General questionshttps://cadabra.science/qa/2609/how-anticommuting-information-is-stored?show=2610#a2610Tue, 21 Nov 2023 15:04:28 +0000Answered: Differentiate a propagator
https://cadabra.science/qa/2605/differentiate-a-propagator?show=2606#a2606
<p>I now tried</p>
<pre><code>from cdb.sympy.calculus import *
\partial{#}::PartialDerivative;
x^{\rho}::Depends(\partial{#});
diff($1/(\eta_{\mu\nu} x^{\mu}x^{\nu})$, $x^{\rho}$);</code></pre>
<p>which gave the error message</p>
<pre><code>File "/home/gpn/.config/cadabra_packages/cdb/sympy/calculus.py", line 20, in diff
dvars.append( sbtmp.to_sympy() )
RuntimeError: Dependencies on derivatives are not yet handled in the SymPy bridge</code></pre>
<p>so I conclude this is not yet possible in cdb.
If anyone has a better answer please let me know.</p>
<p>Thanks
GPN</p>General questionshttps://cadabra.science/qa/2605/differentiate-a-propagator?show=2606#a2606Sat, 18 Nov 2023 13:46:11 +0000Answered: eliminate_vielbein "eliminates" with a Minkowski metric
https://cadabra.science/qa/2586/eliminate_vielbein-eliminates-with-a-minkowski-metric?show=2604#a2604
<p>In the hope it helps someone else:</p>
<p>I found no way to tell Cadabra that the Minkowski metric is "special". In the case I gave above, "swallowing" the Vielbein into the metric is just the Cadabra behavior.</p>
<p>In cases where I needed to eliminate Vielbein with each other, I could use <code>eliminate_vielbein</code>:</p>
<pre><code>{a,b,c,d}::Indices(flat, position=fixed).
V^{a}_{\mu}::Vielbein.
V_{a}^{\mu}::InverseVielbein.
V^{a}_{b}::KroneckerDelta.
V_{a}^{b}::KroneckerDelta.
ex := V_{a}^{\rho} V^{c}_{\rho} V_{c}^{\sigma};
eliminate_vielbein(ex);
eliminate_kronecker(ex);</code></pre>General questionshttps://cadabra.science/qa/2586/eliminate_vielbein-eliminates-with-a-minkowski-metric?show=2604#a2604Thu, 16 Nov 2023 21:47:40 +0000Answered: How to implement a zoom-sensitive algorithm
https://cadabra.science/qa/2595/how-to-implement-a-zoom-sensitive-algorithm?show=2597#a2597
<p>Good one. Everything which is hidden by <code>zoom</code> is wrapped inside an <code>\ldots{...}</code> node. So in principle you can avoid acting on those hidden terms by checking whether your node has an <code>\ldots</code> parent node.</p>
<p>Unfortunately, there isn't really anything that helps with that, unless you want to give up the simple way of walking the expression tree as in that covariant derivative example.</p>
<p>Fortunately, this was trivial to add on the C++ side. I have just pushed 2.4.5 which does the right thing and makes <code>ExNode</code> iterators jump over hidden nodes. Can you let me know if that works for you? (or let me know if you need a binary package if you cannot build from source).</p>General questionshttps://cadabra.science/qa/2595/how-to-implement-a-zoom-sensitive-algorithm?show=2597#a2597Mon, 13 Nov 2023 20:06:15 +0000Answered: How could the partial derivatives be sorted?
https://cadabra.science/qa/2579/how-could-the-partial-derivatives-be-sorted?show=2585#a2585
<p>This works in most cases:</p>
<pre><code>{i,j,k,l}::Indices(space, position=free).
{t, \tau}::Indices(time, position=free).
{i,j,k,l,t}::SortOrder;
\partial{#}::PartialDerivative;
ex := \partial_{t i}{ T^{j} };
canonicalise(ex);
ex := \partial_{t i j}{ T^{j} };
canonicalise(ex);
ex := \partial_{t i t j}{ T^{k} };
canonicalise(ex);</code></pre>
<p>The only case which is not exactly what you want is when an index is summed according to the Einstein convention; the summation and canonicalization have the effect of raising one of the indices.</p>
<p>The following is another variant, which also has an issue when an index is summed according to the Einstein convention, it's just a different issue:</p>
<pre><code>{i,j,k,l}::Indices(space, position=independent).
{t, \tau}::Indices(time, position=independent).
{i,j,k,l,t}::SortOrder;
\partial{#}::PartialDerivative;
ex := \partial_{t i}{ T^{j} };
canonicalise(ex);
ex := \partial_{t i j}{ T^{j} };
canonicalise(ex);
ex := \partial_{t i t j}{ T^{k} };
canonicalise(ex);</code></pre>General questionshttps://cadabra.science/qa/2579/how-could-the-partial-derivatives-be-sorted?show=2585#a2585Fri, 10 Nov 2023 07:59:46 +0000Answered: How to calculate the determinant of a tensor density?
https://cadabra.science/qa/2574/how-to-calculate-the-determinant-of-a-tensor-density?show=2581#a2581
<p>Hi GPN.</p>
<p>To the extend of my knowledge <code>cadabra</code> does not calculate... I would say manipulate expressions (you assign properties to "objects" and use algorithms to manipulate them).</p>
<p><code>cadabra2.x</code> comunicates with <code>SymPy</code> to evaluate expressions (in other word, calculate!). However, the comunication is not "bijective" (it is somehow incomplete), and there is a possibility that the dictionary doesn't translate the operation <code>\det</code>.</p>
<p>If you ask me... I would use <code>substitute</code>! (unless it is not possible)</p>
<p>Cheers,
Dox.</p>General questionshttps://cadabra.science/qa/2574/how-to-calculate-the-determinant-of-a-tensor-density?show=2581#a2581Thu, 09 Nov 2023 08:50:43 +0000Answered: Expansion of covariant derivative
https://cadabra.science/qa/2041/expansion-of-covariant-derivative?show=2578#a2578
<p>The answer I'm posting (after two years) is based on an idea by @dominicprice (former student of Kasper, and developer of many aspects of <code>cadabra</code>).</p>
<h1>The code</h1>
<pre><code>def expand_nabla(ex, *, index_name=None, index_set=None):
if index_name is None:
index_name = "expandnablaidx"
Indices($expandnablaidx, expandnablaidx#$, $expandnablaindices$)
index_counter = 1
for nabla in ex[r'\nabla']:
nabla.name=r'\partial'
dindex = nabla.indices().__next__()
for arg in nabla.args():
ret:=0;
for index in arg.free_indices():
t2:= @(arg);
newidx = Ex(index_name + str(index_counter))
index_counter += 1
if index.parent_rel==sub:
t1:= -\Gamma^{@(newidx)}_{@(dindex) @(index)};
t2[index]:= _{@(newidx)};
else:
t1:= \Gamma^{@(index)}_{@(dindex) @(newidx)};
t2[index]:= ^{@(newidx)};
ret += Ex(str(nabla.multiplier)) * t1 * t2
nabla += ret
distribute(ex, repeat=True)
if index_set is not None:
rename_dummies(ex, "expandnablaindices", index_set)
return ex</code></pre>
<h1>How does it work?</h1>
<p>The problem I found with the algorithm <code>expand_nabla</code> reported in the cadabra book <a rel="nofollow" href="https://cadabra.science/notebooks/ref_programming.html">https://cadabra.science/notebooks/ref_programming.html</a>, was that when considering higher order derivatives, the name of the dummy index wouldn't change, resulting in a "repeated indices" error.</p>
<p>It is desirable that the algorithm could use one of the declared indices!</p>
<p>Therefore, we have to give a name to the set of indices:</p>
<pre><code>\nabla{#}::Derivative.
\partial{#}::PartialDerivative.
{a, b, c, d, e, f, g, h, i, j, k ,l}::Indices(space, position=fixed).
{\mu,\nu,\lambda,\rho}::Indices(spacetime, position=fixed).</code></pre>
<p><strong>NOTE:</strong> there are two types of indices: <code>space</code> and <code>spacetime</code>.</p>
<p>Now, we declare an expression and expand the nabla operator (covariant derivative).</p>
<pre><code>foo := \nabla_{c}{ h^{a}_{b} };
expand_nabla(_, index_set="space");</code></pre>
<p>Since we have asked to expand with dummy indices of type <code>space</code>, the result is</p>
<p>$$\partial<em>{c}{h^{a},</em>{b}}+\Gamma^{a},<em>{c d} h^{d},</em>{b}-\Gamma^{d},<em>{c b} h^{a},</em>{d}$$</p>
<p>However, if we expand indices of type <code>spacetime</code>, we get</p>
<p>$$\partial<em>{c}{h^{a}\,</em>{b}}+\Gamma^{a}\,<em>{c \mu} h^{\mu}\,</em>{b}-\Gamma^{\mu}\,<em>{c b} h^{a}\,</em>{\mu}$$</p>
<h2>Higher orders</h2>
<p>Higher orders (I was able to calculate up to third order) can be computed with ease, for example:</p>
<pre><code>foo := \nabla_{e}{\nabla_{d}{\nabla_{c}{ h^{a}_{b} }}};
#expand_nabla(_, index_set="vector");
expand_nabla(_, index_name=r'\lambda');</code></pre>
<p>The <code>index_name=r'\lambda'</code> ask the algorithm to use the name <code>\lambda</code> to expand the dummy indices.</p>General questionshttps://cadabra.science/qa/2041/expansion-of-covariant-derivative?show=2578#a2578Wed, 08 Nov 2023 08:54:16 +0000How to change the order of two indexes in a complex statement
https://cadabra.science/qa/2568/how-to-change-the-order-of-two-indexes-in-a-complex-statement
<p>Thanks for all the help. Another newbie question: I have read the doc carefully but <code>asym(..., ..., antisymmetric=False)</code> did not solve the following question.</p>
<p>Consider please the two expressions:</p>
<pre><code>ex1 := g_{\mu\kappa} \partial_{\nu}{g^{\rho\kappa}} ->
-g^{\rho\kappa} \partial_{\nu}{g_{\mu\kappa}};
ex2 := g_{\mu\kappa} \partial_{\nu}{g^{\kappa\rho}} ->
-g^{\rho\kappa} \partial_{\nu}{g_{\mu\kappa}};</code></pre>
<p>They are identical except for a change of order <code>ρκ <--> κρ</code> in <code>g^{\rho\kappa}</code>. I find this change does make a differnce in some substitutions, so that's why I need it.</p>
<p>Is there a way to make that change of order programmatically, without writing out the expression by hand? <code>asym()</code> will (anti-)symmetrize but then when I canonicalise I get back the original order rather than the order I want.</p>
<p>Many thanks as always
GPN</p>General questionshttps://cadabra.science/qa/2568/how-to-change-the-order-of-two-indexes-in-a-complex-statementTue, 24 Oct 2023 17:31:54 +0000Zooming in on a specific term and applying a rule
https://cadabra.science/qa/2553/zooming-in-on-a-specific-term-and-applying-a-rule
<p>A newbie question, I guess. I am challenged to zoom in on specific terms and apply a rule to them.</p>
<p>I want to say "zoom in on the 4th and 8th term in a 9 term statement and apply a substitution rule", <strong>specifically when all the terms</strong> are complex expressions with multiple indexes and partial derivatives. How do I do that?</p>
<p>In more detail, I have a complex expression with 9 terms and each term has a lot of indexes, but for simplicity lets just call these 9 terms</p>
<p>A + B + C + D + E + F + G + H + I</p>
<p>What I want to do, for example, is zoom in on terms D and H and apply a subsitution rule which is itself involving a lot of indexes and a partial derivative.</p>
<p>My problem is that all these terms involve partial derivatives as well as indexes and zoom does not seem to capture these well.</p>
<p>Here is example code that provides perhaps some context:</p>
<pre><code>from cdb.relativity.abstract import *
from cdb.core.manip import *
g_{\mu\nu}::Metric.
g_{\mu\nu}::Depends(\partial{#}).
g^{\mu\nu}::InverseMetric.
g^{\mu\nu}::Depends(\partial{#}).
\Gamma^{\mu}_{\nu\rho}::Depends(\partial{#}).
ch = christoffel_from_metric();
ch_2 := \Gamma^{\rho}_{\nu\sigma}\Gamma^{\sigma}_{\rho\mu};
substitute(ch_2,ch);
distribute(_)
sort_product(_)
sort_sum(_)
rename_dummies(_);</code></pre>
<p>Now how do I <code>zoom</code> in on the 4th and 8th terms of this last expression? It can be through the <code>zoom()</code> function, but I am also happy with <code>take_match()</code> or any of the <code>manip</code> functions. I wasn't able to solve it with them.</p>
<p>Many thanks
GPN</p>General questionshttps://cadabra.science/qa/2553/zooming-in-on-a-specific-term-and-applying-a-ruleWed, 18 Oct 2023 13:44:14 +0000Getting two terms with derivatives to form a product
https://cadabra.science/qa/2549/getting-two-terms-with-derivatives-to-form-a-product
<p>Sorry for the newbie question, I actually did carefully read the doc and do some of the tutorials, but haven't found the probably obvious answer.</p>
<p>I have an expression with two partial derivative terms and some other terms, of the form</p>
<p>R = dA + B + A * (G^(-1) dG) + C</p>
<p>Of course I would like it to simplify to</p>
<p>R = G^(-1) d(GA) + B + C</p>
<p>I tried <code>collect_terms</code> but no luck, the above expression remains unchanged.</p>
<p>Note that the above is simplified, in the actual problem the A,B,C also have indices.</p>
<p>Any advice please?</p>
<p>Many Thanks
GPN</p>General questionshttps://cadabra.science/qa/2549/getting-two-terms-with-derivatives-to-form-a-productSun, 15 Oct 2023 17:08:01 +0000symmetrise slots function
https://cadabra.science/qa/2538/symmetrise-slots-function
<p>Hi! I tryed to use symmetrise_slots function from cdb.utils.indices package, and I thought that it would symmetrise only free indices, but then I use it with expressions like </p>
<pre><code>ind.symmetrise_slots($R_{a b} R_{c d} h_{s w} h^{a c} h^{b d}$, [0,1]);</code></pre>
<p>I obtain</p>
<pre><code>R_{a b} R_{c d} h_{s w} h^{a c} h^{b d} + R_{b a} R_{c d} h_{s w} h^{a c} h^{b d}</code></pre>
<p>How can it be used to symmetrise only free indiced?</p>General questionshttps://cadabra.science/qa/2538/symmetrise-slots-functionThu, 14 Sep 2023 14:38:29 +0000