Skip to content

Metrics

Relevant headers

  • metrics/metric_base.h
  • metrics/minkowski.h
  • metrics/spherical.h
  • metrics/qspherical.h
  • metrics/kerr_schild.h
  • metrics/qkerr_schild.h
  • metrics/kerr_schild_0.h

Metrics are key objects of the Entity framework. Superimposed on the discretized mesh, they define the spacetime geometry of the simulation and provide necessary functions for converting coordinates and transforming vectors from one basis to another.

Coordinate systems and bases

To understand how metrics are implemented in Entity, one must first understand the different coordinate systems and bases the Entity works with. For each metric, there are two or three levels of coordinates.

  • Physical, \(x^I\): this is the coordinate system in which the metric is originally defined (e.g., for Kerr-Schild -- it's spherical, for Minkowski -- Cartesian).
  • Linear: this is the coordinate system in which the grid discretization is uniform. It is often stretched or squeezed w.r.t. the original physical (e.g., for Q-Kerr-Schild -- it's quasi-spherical, for Kerr-Schild -- it's the same as the physical);
  • Code-unit, \(x^i\): finally, this is the coordinate system the code works with; it takes the linear coordinate system and remaps it to the interval of \([0, n_i)\), where \(n_i\) is the number of grid points in the \(i\)-th direction on the given domain.

Qspherical coordinates

All qspherical metrics (QSpherical, QKerrSchild) take spherical coordinates as their base \((r,\theta,\phi)\), then stretch them to quasi-spherical coordinates \((\xi,\eta,\phi)\), and finally map them to code-unit coordinates \((x^1,x^2,x^3)\).

\[ \begin{CD} (r,\theta,\phi) @>\text{stretch}>> (\xi,\eta,\phi) @>\text{map}>> (x^1,x^2,x^3) \end{CD} \]

where stretching is done via \(\xi=\log{(r-r_0)}\), \(\theta = x_2 + 2h \eta (\pi - 2 \eta) (\pi - \eta) / \pi^2\) (\(\eta\) set implicitly), and mapping -- via \(x^1 = (\xi - \xi_{\rm min})/n_1\), etc.

The diagram below demonstrates the stretching of the quasi-spherical coordinates in the \(\xi\) direction, and how that maps to both the physical and code-unit coordinates. Here we stretch \(r=[1, 90)\) logarithmically \(\xi=\ln{r}\), and map it to \(x^1=[0, 18)\) which coincides with our discretization. The result is a non-uniformly discretized grid with more cells focused towards the origin.

Vectors in Entity can also be defined in different bases. We typically define covariant and contravariant vectors in code-, \(x^i\), and physical-, \(x^I\), generally non-orthonormal coordinates: \(u_i\), \(u^i\), and \(u_I\), \(u^I\). We can also define a locally-flat orthonormal basis, \(u_{\hat{i}}\equiv u^{\hat{i}}\equiv u^{\hat{I}}\equiv u_{\hat{I}}\), also called the tetrad basis. For special-relativistic metrics, tetrad basis is exactly the same in all points of space, and is thus global. For general-relativistic metrics, the tetrad basis is defined locally, and is different in each point of space.

Metric classes

Each metric has a number of distinct attributes. These are:

  • D: the dimensionality of the metric:
    • Dim::_1D, Dim::_2D, Dim::_3D
  • Label: a string that identifies the metric;
  • CoordType: the type of coordinates used in the metric;
    • Coord::Cart, Coord::Sph, Coord::Qsph
  • PrtlDim: the dimensionality of the particle coordinates. PrtlDim == Dim::_3D for SR spherical metrics, and == D otherwise; (1)

    1. 🙋‍♂️ In 2D axisymmetric SR simulations, particles carry all three coordinates to recover their full Cartesian position, and transform fields to/from the global Cartesian basis.

Methods

method description arguments returns
h_ metric components $h_{ij}$ coord_t<D> x_C real_t
h inverse metric components $h^{ij}$ coord_t<D> x_C real_t
alpha lapse function $\alpha$ coord_t<D> x_C real_t
beta1 shift vector component $\beta^1$ coord_t<D> x_C
sqrt_det_h $\sqrt{\det{h_{ij}}}$ coord_t<D> x_C real_t
sqrt_det_h_tilde $\sqrt{\det{h_{ij}}} / \sin{\theta}$ coord_t<D> x_C real_t
sqrt_h_ $\sqrt{h_{ij}}$ coord_t<D> x_C real_t
polar_area $A_{\theta\phi}$ real_t x1_C real_t
convert converts the $i$-th component of a coordinate to another basis real_t real_t
convert converts the full $D$-dimensional coordinate to another basis coord_t<D>, &coord_t<D>
convert_xyz explicitly converts to/from a Cartesian basis coord_t<PrtlDim>, &coord_t<PrtlDim>
transform transforms the $i$-th component of a vector to another frame coord_t<D> x_C, real_t real_t
transform transforms the full $3D$ vector to another frame coord_t<D>, vec_t<3D>, &vec_t<3D>
transform_xyz explicitly transforms to/from a Cartesian frame coord_t<PrtlDim>, vec_t<3D>, &vec_t<3D>

= only defined for SR metrics

= only defined for GR metrics

= only defined for spherical metrics

The in and out template arguments for the convert<> and transform<> functions are, respectively, the coordinate bases (stored as an enum Crd::) and the vector reference frame (stored as enum Idx::). The members of these enums are:

description
Crd::Cd code-unit coordinates: $x^i$
Crd::XYZ cartesian coordinates: $x^{x}$
Crd::Sph spherical coordinates: $x^{r}$
Crd::Ph "physical" coordinates: $x^{I}$

Crd::Ph

Depending on the metric, Crd::Ph is equivalent to Crd::XYZ or Crd::Sph.

description
Idx::U upper (contravariant) basis (code units): $u^i$
Idx::D lower (covariant) basis (code units): $u_i$
Idx::T tetrad (orthonormal) basis $u^{\hat{i}} \equiv u_{\hat{i}} \equiv u^{\hat{I}} \equiv u_{\hat{I}}$
Idx::XYZ global Cartesian basis: $u^{\hat{x}}\equiv u_{\hat{x}}$
Idx::Sph global spherical basis: $u^{\hat{r}}\equiv u_{\hat{r}}$
Idx::PU physical contravariant basis: $u^I$
Idx::PD physical covariant basis: $u_I$

= only possible in SR

Note

For Cartesian metric, transforming to Idx::T is equivalent to converting to Idx::XYZ, and similarly for the spherical metric, transforming to Idx::T is equivalent to converting to Idx::Sph.

Code

Metric component \(1,1\) in the covariant basis, \(h_{11}\), can be accessed via in the certain position x_Code in code units by calling (assuming D is the dimension of the metric):

coord_t<D> x_Code;
// define x_Code
metric.template h_<1, 1>(x_Code)
To convert x_Code to physical coordinates:
coord_t<D> x_Ph { ZERO }; // init with zero so the compiler doesn't complain
metric.template convert<Crd::Cd, Crd::Ph>(x_Code, x_Ph);
To transform a vector v_Cov from the covariant basis to the tetrad basis:
vec_t<Dim::_3D> v_Cov;
// define v_Cov
vec_t<Dim::_3D> v_T { ZERO };
metric.template transform<Idx::D, Idx::T>(x_Code, v_Cov, v_T);
For SR metrics you can also explicitly convert coordinates and transform vectors to/from the cartesian basis:
coord_t<PrtlDim> x_Code;
// define x_Code (notice, that for 2D spherical metrics this will be 3D)
metric.template convert_xyz<Crd::Cd, Crd::XYZ>(x_Code, x_Cart);

vec_t<Dim::_3D> v_Cntrv;
// define v_Cntrv
vec_t<Dim::_3D> v_XYZ { ZERO };
metric.template transform_xyz<Idx::U, Idx::XYZ>(x_Code, v_Cntrv, v_XYZ);

Below is a diagram demonstrating all the possible transformations.

Metric structure and hierarchy

Schematics below shows the structure of the metric classes and their inheritance hierarchy with all the private/public variables and methods.

classDiagram
  direction LR
  class MetricBase~Dimension~{
    +bool is_metric$
    +Dimension Dim$
    #const real_t nx1
    #const real_t nx2
    #const real_t nx3
    #const real_t x1_min
    #const real_t x1_max
    #const real_t x2_min
    #const real_t x2_max
    #const real_t x3_min
    #const real_t x3_max
    #real_t dx_min
    +find_dxMin() real_t*
    +dxMin() real_t
    +set_dxMin(real_t)
  }
  class Metric~Dimension~{
    +const char* Label$
    +Dimension PrtlDim$
    +Metric MetricType$
    +Coord CoordType$
    +find_dxMin() real_t
    +h_~idx_t|idx_t~(coord_t~D~) real_t
    +sqrt_det_h(coord_t~D~) real_t
    +convert~idx_t|Crd|Crd~(real_t) real_t
    +convert~Crd|Crd~(coord_t~D~, coord_t~D~)
    +transform~idx_t|Idx|Idx~(coord_t~D~, real_t) real_t
    +transform~Idx|Idx~(coord_t~D~, vec_t, vec_t)
  }
  class Minkowski~Dimension~ {
    -const real_t dx, dx_inv
    +sqrt_h_~idx_t|idx_t~(coord_t~D~) real_t
    +convert_xyz~Crd|Crd~(coord_t~PrtlDim~, coord_t~PrtlDim~)
    +transform_xyz~Idx|Idx~(coord_t~PrtlDim~, vec_t, vec_t)
  }
  class Spherical~Dimension~ {
    -const real_t dr, dtheta, dphi
    -const real_t dr_inv, dtheta_inv, dphi_inv
    +sqrt_h_~idx_t|idx_t~(coord_t~D~) real_t
    +convert_xyz~Crd|Crd~(coord_t~PrtlDim~, coord_t~PrtlDim~)
    +transform_xyz~Idx|Idx~(coord_t~PrtlDim~, vec_t, vec_t)
    +polar_area(real_t) real_t
  }
  class QSpherical~Dimension~ {
    -const real_t r0, h, chi_min, eta_min, phi_min
    -const real_t dchi, deta, dphi
    -const real_t dchi_inv, deta_inv, dphi_inv
    -const real_t dchi_sqr, deta_sqr, dphi_sqr
    +sqrt_h_~idx_t|idx_t~(coord_t~D~) real_t
    +convert_xyz~Crd|Crd~(coord_t~PrtlDim~, coord_t~PrtlDim~)
    +transform_xyz~Idx|Idx~(coord_t~PrtlDim~, vec_t, vec_t)
    +polar_area(real_t) real_t
    -dtheta_deta(real_t) real_t
    -eta2theta(real_t) real_t
    -theta2eta(real_t) real_t
  }
  class KerrSchild~Dimension~ {
    -const real_t a, rg_, rh_
    -const real_t dr, dtheta, dphi
    -const real_t dr_inv, dtheta_inv, dphi_inv
    +h~idx_t|idx_t~(coord_t~D~) real_t
    +sqrt_det_h_tilde(coord_t~D~) real_t
    +alpha(coord_t~D~) real_t
    +beta1(coord_t~D~) real_t
    +polar_area(real_t) real_t
  }
  class KerrSchild0~Dimension~ {
    -const real_t dr, dtheta, dphi
    -const real_t dr_inv, dtheta_inv, dphi_inv
    +h~idx_t|idx_t~(coord_t~D~) real_t
    +sqrt_det_h_tilde(coord_t~D~) real_t
    +alpha(coord_t~D~) real_t
    +beta1(coord_t~D~) real_t
    +polar_area(real_t) real_t
  }
  class QKerrSchild~Dimension~ {
    -const real_t a, rg_, rh_
    -const real_t chi_min, eta_min, phi_min
    -const real_t dchi, deta, dphi
    -const real_t dchi_inv, deta_inv, dphi_inv
    +h~idx_t|idx_t~(coord_t~D~) real_t
    +sqrt_det_h_tilde(coord_t~D~) real_t
    +alpha(coord_t~D~) real_t
    +beta1(coord_t~D~) real_t
    +polar_area(real_t) real_t
    -dtheta_deta(real_t) real_t
    -eta2theta(real_t) real_t
    -theta2eta(real_t) real_t
  }
  class Mesh~Metric~{
    see mesh...*
  }
  MetricBase <|-- Metric : inherits
  Metric <|-- Minkowski : implements
  Metric <|-- Spherical : implements
  Metric <|-- QSpherical : implements
  Metric <|-- KerrSchild : implements
  Metric <|-- QKerrSchild : implements
  Metric <|-- KerrSchild0 : implements
  Mesh --* Metric : contains
  note "+: public\n-: private\n#: protected\nunderline: static constexpr\nitalic: virtual"