KADATH SPECTRAL SOLVER

Tutorial 10 : General Metrics

This tutorial is devoted to the use of general metrics.

The Metric_tensor class

In order to deal with metrics, one must use a special type of tensor Metric_tensor. It is a rank-2 symmetric tensor. Both indices are of the same type but can be covariant or contravariant, so that this class can describe the metric or its inverse.

// Assume a spherical space has been defined (put 9 points in theta and 8 in phi to be safe)
// The tensorial basis
Base_tensor basis (space, CARTESIAN_BASIS) ; 
Metric_tensor gmet (space, COV, basis) ;

// Affectation to flat metric everywhere
for (int i=1 ; i<=3 ; i++)  {
     gmet.set(i,i) = 1. ;
    for (int j=i+1 ; j<=3 ; j++)
         gmet.set(i,j) = 0 ;
}
// Non trivial stuff in domain 1
for (int i=1 ; i<=3 ; i++)
     for (int j=i ; j<=3 ; j++)
           gmet.set(i,j).set_domain(1) = 
              gmet(i,j)(1) + space.get_domain(1)->get_cart(i)*space.get_domain(1)->get_cart(j) ;

// Standard base in that case
gmet.std_base() ;
//cout << gmet << endl ;

Using constant metrics

Constant metrics are described by the class Metric_const. By constant, one means that it is given once and for all and that the system is not allowed to change it. In that respect it works as the constant fields defined using add_cst. (see tutorial 5). Obviously it does not mean that the metric is constant in space.

It then works in the same manner as the flat metrics of tutorial 9.

// Construction of a constant metric
// The numerical value is contained in a Metric_tensor that can be covariant or contravariant.
Metric_const met (gmet) ;

// Passing it to a system 
System_of_eqs syst (space, 1) ;
met.set_system (syst, "g") ;

// One can get the connection coefficients (reserved word Gam)
syst.add_def ("Christo_ij^k = Gam_ij^k") ;
//cout << syst.give_val_def("Christo") << endl ;

// One can also get the Ricci tensor (reserved word R)
syst.add_def ("Ricci_ij = R_ij") ;
//cout << syst.give_val_def("Ricci") << endl ;

Metrics as unknown

Often the metric is given but is part of the physical problem, meaning it is an unknown field that the solver is trying to find. When this is the case, one must use the class Metric_general. It works as the Metric_const except that the metric is now treated as a variable field (see tutorial 5).

Solving the system of equations, will change the Metric_tensor used to define the metric.

// Construction of the fields for inner and outer BC
Metric_tensor ginner (gmet) ; // Contains the initial value of gmet
// No need to call std_base 
Metric_tensor gouter (space, COV, basis) ;
for (int i=1 ; i<=3 ; i++) {
    gouter.set(i,i) = 1. ;
    for (int j=i+1 ; j<=3 ; j++)
        gouter.set(i,j) = 0 ;
}
gouter.std_base() ;

// Construction of a unknown metric
// The initial numerical value is contained in a Metric_tensor.
Metric_general metgen (gmet) ;

// Passing it to a new system 
System_of_eqs systtwo  (space, 1) ;
metgen.set_system (systtwo, "g") ;

// Pass the fields ginner and gouter as constants
systtwo.add_cst ("gin", ginner) ;
systtwo.add_cst ("gout", gouter) ;

// Random equations
systtwo.add_eq_bc (1, INNER_BC, "g_ij = gin_ij") ;
systtwo.add_eq_inside (1, "lap(g_ij) = 0") ;
systtwo.add_eq_bc (1, OUTER_BC, "g_ij = gout_ij") ;

// Newton-Raphson solver
double prec = 1e-8 ;
double error ;
bool endloop = false ;
while (!endloop) {
    endloop = systtwo.do_newton(prec, error) ;
}

// The solution is contained in gmet
// One can check that it is different from ginner that contains the initial value of gmet
for (int i=1 ; i<=3 ; i++)
    for (int j=i ; j<=3 ; j++)
        cout << "Diff in comp " << i << ", " << j << " : " << diffmax(gmet(i,j)(1), ginner(i,j)(1)) << endl ;