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

For example, when looking at ADM formalism, I have $ds^2 = -N^2dt^2+g_{ij}(dx^{i}+N^{i}dt)(dx^{j}+N^{j}dt)$ in which the specific function relation between $g_{\mu \nu}$ and coordinates is not that clear so is abstract. Then how to do calculation on this kind of metric to get, say, the Christoffel symbols or other quantities after that? Below is what I've tried, but it didn't work with a result that all the Christoffel symbols are 0.

By the way, as a very beginner in ADM formalism, is it the case that I have some misunderstanding in the calculation of it?

{t,x,y,z}::Coordinate;
{\mu,\nu,\rho,\sigma,\lambda,\kappa,\chi,\gamma,i,j,k}::Indices(values={t,x,y,z},position=fixed);
\partial{#}::PartialDerivative;
g_{\mu\nu}::Metric;
g^{\mu\nu}::InverseMetric;
h_{i j}::Metric;
h^{i j}::InverseMetric;
ss:={ g_{t t}=0,
    g_{0 i}=N_i,
    g_{i j}=h_{i j}
};
complete(ss, $g^{\mu\nu}$);
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}} );
                                  evaluate(ch, ss, rhsonly=True);
in General questions by (180 points)
edited by

I seem to have forgot about setting dependence for N and h on coordinates, but after adding the dependence, the cadabra2 core just dies when I calculate Christoffel symbols.

h_{i j}::Depends(t);
h^{i j}::Depends(t);
N_i::Depends(x,y,z);

Hi Photon. I've been looking at your code, and there are some mistakes.

I've also found some "misunderstandings" in the manipulation of cadabra... perhaps due to my own ignorance.

I'll be in touch!

Cheers.

Thanks, I'm new to cosmological perturbation theory and also I'm still learning to use cadabra so there might be some error in my code or the computation process.

You probably shouldn't make $\mu,i$ have the same index type.

Yes, that is one of the issues.

I now understand that the induced metric on hypersurface has non-zero 00 and 0i components, which means it cannot be simply taken to be part of the original metric before doing foliation. Is that the reason?

The dimensions of these two spaces are different

Hi everyone. I've updated the answer with a new method that might be useful in many contexts.

Cheers, Dox.

1 Answer

+2 votes

Let me hint some ideas... although it is a not very helpful example.

Comment 0: I'll stick to the suggested code, and not the written line-element.

My suggestions

Firstly, let's assing some properties

{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;

Comment 1: the separation between Latin and Greek indices.

Then, assign some dependencies,

h_{i j}::Depends(t);
N{#}::Depends(x,y,z);

Now, instead of trying to declare sets of components, like g_{0 i}=N_i for the metric, I used a detail declaration,

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}$);

Comment 2: 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.

Finally, you can define the Christoffel rule,

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}} );

and evaluate its components,

evaluate(ch, ss, rhsonly=True);

A more complete metric

Just if you want to try it

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}$);

Additional reflexions

If you have evaluated the above code, you'll find that it is not very useful!

Really long expressions.

What if we don't give explicit expressions?

TO BE CONTINUED!

A better method

Ok, finally I came with a better solution.

Paradoxically, the best solution uses the substitute algorithm instead of the evaluate.

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.

Let's start with some assignation of properties:

{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).

Then, let us define a substitution rule for the ADM decomposition of the metric and its inverse:

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,};

Note that I've defined in addition the rule refine, which will be useful in the next step.

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. cadabra uses the command Ex to convert a (formatted python) string into a cadabra expression. Comment 3: 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).

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);

Hope this latter method would help you!

Cheers, Dox.

by (15.1k points)
edited by
...