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)\).
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)- 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)
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);
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);
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"