#!/usr/bin/env python # coding: utf-8 # # # # # [BSSN](http://www2.yukawa.kyoto-u.ac.jp/~yuichiro.sekiguchi/3+1.pdf) Stress-Energy Source Terms # # ## Author: Zach Etienne # # ## This module constructs the BSSN stress-energy source terms, in terms of $T^{\mu\nu}$, as prescribed in the reference metric approach of [Baumgarte, Montero, Cordero-Carrión, and Müller (2012)](https://arxiv.org/abs/1211.6632), which builds upon the covariant Lagrangian BSSN formalism of [Brown (2009)](https://arxiv.org/abs/0902.3652). # # **Notebook Status:** Self-validated # # **Validation Notes:** None yet. # # ### NRPy+ Source Code for this module: [BSSN/BSSN_stress_energy_source_terms.py](../edit/BSSN/BSSN_stress_energy_source_terms.py) # # # ## Introduction # # In [the NRPy+ tutorial on the BSSN formulation](Tutorial-BSSN_formulation.ipynb) we outlined the BSSN formulation of Einstein's equations *in the absence of stress-energy* (i.e., in a vacuum where Einstein's equations reduce to $G^{\mu\nu}=0$). When $T^{\mu\nu}$ is nonzero, stress-energy source terms must appear on the right-hand sides of the BSSN equations in order to ensure Einstein's equations of general relativity are satisfied. # # Analyzing Eqs. 9 of [Baumgarte, Montero, Cordero-Carrión, and Müller](https://arxiv.org/pdf/1211.6632.pdf), we see that adding stress-energy source terms $T_{\mu\nu}$ to Einstein's equations in vacuum simply adjusts the right-hand sides of the $\partial_t \bar{A}_{ij}$, $\partial_t K$, and $\partial_t \bar{\Lambda}^i$ equations as follows: # # # \begin{eqnarray} # \ \partial_t \bar{A}_{ij} &=& \left[\partial_t \bar{A}_{ij}\right]_{\rm vacuum}\ {\color{blue}{-\ 8\pi \alpha e^{-4\phi} \left(S_{ij}\right)^{\rm TF}}} \\ # \partial_t K &=& \left[\partial_t K\right]_{\rm vacuum}\ {\color{blue}{+\ 4\pi \alpha (\rho + S)}} \\ # \partial_t \bar{\Lambda}^i &=& \left[\partial_t \bar{\Lambda}^{i}\right]_{\rm vacuum}\ {\color{blue}{-\ 16\pi \alpha \bar{\gamma}^{ij} S_j}}, # \end{eqnarray} # # where $\rho$, $S$, $S_i$, and $S_{ij}$ are related to the stress-energy tensor $T^{\mu\nu}$ as follows (Eq. 10 of [Baumgarte, Montero, Cordero-Carrión, and Müller](https://arxiv.org/pdf/1211.6632.pdf)): # # \begin{eqnarray} # \ S_{ij} &=& \gamma_{i \mu} \gamma_{j \nu} T^{\mu \nu} \\ # S_{i} &=& -\gamma_{i\mu} n_\nu T^{\mu\nu} \\ # S &=& \gamma^{ij} S_{ij} \\ # \rho &=& n_\mu n_\nu T^{\mu\nu}, # \end{eqnarray} # # the unit normal one-form on each spatial slice $n_{\mu}$ is given by Eq. 10 of [Baumgarte, Montero, Cordero-Carrión, and Müller](https://arxiv.org/pdf/1211.6632.pdf)): # # $$ # n_\mu = (-\alpha,0,0,0), # $$ # # and Baumgarte & Shapiro Eq. 2.27 gives $\gamma_{\mu\nu}$: # # $$\gamma_{\mu\nu} = g_{\mu\nu} + n_\mu n_\nu.$$ # # Further, analyzing Eqs. 13 & 14 of [Baumgarte, Montero, Cordero-Carrión, and Müller](https://arxiv.org/pdf/1211.6632.pdf) we find that adding stress-energy source terms $T_{\mu\nu}$ to Einstein's equations in vacuum adjusts the BSSN constraint equations as follows: # \begin{eqnarray} # \ \mathcal{H} &=& \left[\mathcal{H}\right]_{\rm vacuum}\ {\color{blue}{-\ 16\pi \rho}} \\ # \mathcal{M}^i &=& \left[\mathcal{M}^i\right]_{\rm vacuum}\ {\color{blue}{-\ 8\pi S^i}}, # \end{eqnarray} # # This module will construct expressions for $S_{ij}$, $S_i$, $S$, and $\rho$ in terms of $T^{\mu\nu}$, and also add the necessary terms to the BSSN RHSs and constraints. # # ### A Note on Notation # # As is standard in NRPy+, # # * Greek indices refer to four-dimensional quantities where the zeroth component indicates temporal (time) component. # * Latin indices refer to three-dimensional quantities. This is somewhat counterintuitive since Python always indexes its lists starting from 0. As a result, the zeroth component of three-dimensional quantities will necessarily indicate the first *spatial* direction. # # As a corollary, any expressions involving mixed Greek and Latin indices will need to offset one set of indices by one: A Latin index in a four-vector will be incremented and a Greek index in a three-vector will be decremented. # # # # Table of Contents # $$\label{toc}$$ # # This notebook is organized as follows # # 1. [Step 1](#initializenrpy): Initialize needed Python/NRPy+ modules # 1. [Step 2](#bssn_sourceterms): BSSN source terms, in terms of $T^{\mu\nu}$ # 1. [Step 2.a](#gamma4dd): Define `gamma4DD[mu][nu]` = $g_{\mu \nu} + n_{\mu} n_{\nu}$ # 1. [Step 2.b](#t4uu): Declare `T4UU[mu][nu]`=$T^{\mu\nu}$ # 1. [Step 2.c](#define_bssn_sourceterms): Define BSSN source terms # 1. [Step 3](#add_bssn_sourceterms_to_rhss): Add BSSN source terms to BSSN RHSs # 1. [Step 4](#add_bssn_sourceterms_to_constraints): Add BSSN source terms to BSSN Constraints # 1. [Step 5](#code_validation): Code Validation against `BSSN.BSSN_stress_energy_source_terms` NRPy+ module # 1. [Step 6](#latex_pdf_output): Output this notebook to $\LaTeX$-formatted PDF file # # # # Step 1: Initialize needed Python/NRPy+ modules & set up reference metric \[Back to [top](#toc)\] # $$\label{initializenrpy}$$ # In[1]: # Step 1: Initialize needed Python/NRPy+ modules import sympy as sp # SymPy: The Python computer algebra package upon which NRPy+ depends import NRPy_param_funcs as par # NRPy+: Parameter interface import indexedexp as ixp # NRPy+: Symbolic indexed expression (e.g., tensors, vectors, etc.) support import reference_metric as rfm # NRPy+: Reference metric support import BSSN.ADMBSSN_tofrom_4metric as AB4m # NRPy+: ADM/BSSN <-> 4-metric conversions import BSSN.ADM_in_terms_of_BSSN as AitoB # NRPy+: ADM quantities in terms of BSSN quantities # Step 1.a: Set up reference metric. We'll choose SinhSpherical here, but # could choose any CoordSystem defined in reference_metric.py: par.set_parval_from_str("reference_metric::CoordSystem","Spherical") rfm.reference_metric() thismodule = "BSSN.BSSN_stress_energy_source_terms" # # # # Step 2: BSSN source terms, in terms of $T^{\mu\nu}$ \[Back to [top](#toc)\] # $$\label{bssn_sourceterms}$$ # # # # ## Step 2.a: Define `gamma4DD[mu][nu]` = $g_{\mu \nu} + n_{\mu} n_{\nu}$ \[Back to [top](#toc)\] # $$\label{gamma4dd}$$ # In[2]: # Step 2.a: Define gamma4DD[mu][nu] = g_{mu nu} + n_{mu} n_{nu} alpha = sp.symbols("alpha",real=True) zero = sp.sympify(0) n4D = [-alpha, zero, zero ,zero] AB4m.g4DD_ito_BSSN_or_ADM("BSSN") gamma4DD = ixp.zerorank2(DIM=4) for mu in range(4): for nu in range(4): gamma4DD[mu][nu] = AB4m.g4DD[mu][nu] + n4D[mu]*n4D[nu] # # # ## Step 2.b: Declare `T4UU[mu][nu]`=$T^{\mu\nu}$ \[Back to [top](#toc)\] # $$\label{t4uu}$$ # In[3]: # Step 2.b: Declare T4UU T4UU = ixp.declarerank2("T4UU","sym01",DIM=4) # # # ## Step 2.c: Define BSSN source terms \[Back to [top](#toc)\] # $$\label{define_bssn_sourceterms}$$ # # Recall from above, we have: # \begin{eqnarray} # \ S_{ij} &=& \gamma_{i \mu} \gamma_{j \nu} T^{\mu \nu} \\ # S_{i} &=& -\gamma_{i\mu} n_\nu T^{\mu\nu} \\ # S &=& \gamma^{ij} S_{ij} \\ # \rho &=& n_\mu n_\nu T^{\mu\nu}. # \end{eqnarray} # In[4]: # Step 2.c: Define BSSN source terms # Step 2.c.i: S_{ij} = gamma_{i mu} gamma_{j nu} T^{mu nu} SDD = ixp.zerorank2() for i in range(3): for j in range(3): for mu in range(4): for nu in range(4): SDD[i][j] += gamma4DD[i+1][mu] * gamma4DD[j+1][nu] * T4UU[mu][nu] # Step 2.c.ii: S_{i} = -gamma_{i mu} n_{nu} T^{mu nu} SD = ixp.zerorank1() for i in range(3): for mu in range(4): for nu in range(4): SD[i] += - gamma4DD[i+1][mu] * n4D[nu] * T4UU[mu][nu] # Step 2.c.iii: S = gamma^{ij} S_{ij} AitoB.ADM_in_terms_of_BSSN() S = zero for i in range(3): for j in range(3): S += AitoB.gammaUU[i][j]*SDD[i][j] # Step 2.c.iv: rho = n_{mu} n_{nu} T^{mu nu} rho = zero for mu in range(4): for nu in range(4): rho += n4D[mu]*n4D[nu]*T4UU[mu][nu] # # # # Step 3: Add BSSN source terms to BSSN RHSs \[Back to [top](#toc)\] # $$\label{add_bssn_sourceterms_to_rhss}$$ # # Recall from above we need to make the following modifications: # \begin{eqnarray} # \ \partial_t \bar{A}_{ij} &=& \left[\partial_t \bar{A}_{ij}\right]_{\rm vacuum}\ {\color{blue}{-\ 8\pi \alpha e^{-4\phi} \left(S_{ij}\right)^{\rm TF}}} \\ # \partial_t K &=& \left[\partial_t K\right]_{\rm vacuum}\ {\color{blue}{+\ 4\pi \alpha (\rho + S)}} \\ # \partial_t \bar{\Lambda}^i &=& \left[\partial_t \bar{\Lambda}^{i}\right]_{\rm vacuum}\ {\color{blue}{-\ 16\pi \alpha \bar{\gamma}^{ij} S_j}}, # \end{eqnarray} # # where $$\left(S_{ij}\right)^{\rm TF} = S_{ij} - \frac{1}{3} \bar{\gamma}_{ij} \bar{\gamma}^{km} S_{km}.$$ # # *Exercise to student:* Prove that replacing the $\bar{\gamma}_{ij}$ and $\bar{\gamma}^{km}$ with $\gamma_{ij}$ and $\gamma^{km}$, respectively, results in exactly the same expression for $\left(S_{ij}\right)^{\rm TF}$. # In[5]: # Step 3: Add BSSN stress-energy source terms to BSSN RHSs import BSSN.BSSN_quantities as Bq # Can't #declare M_PI here, as it is not SIMD-compatible. PI = par.Cparameters("REAL", thismodule, ["PI"], "3.14159265358979323846264338327950288") alpha = sp.symbols("alpha",real=True) zero = sp.sympify(0) # Step 3.a: Initialize RHS source terms to zero. sourceterm_trK_rhs = zero sourceterm_a_rhsDD = ixp.zerorank2() sourceterm_lambda_rhsU = ixp.zerorank1() # Step 3.b: trK_rhs sourceterm_trK_rhs = 4*PI*alpha*(rho + S) # Step 3.c: Abar_rhsDD: # Step 3.c.i: Compute trace-free part of S_{ij}: Bq.BSSN_basic_tensors() # Sets gammabarDD gammabarUU, dummydet = ixp.symm_matrix_inverter3x3(Bq.gammabarDD) # Set gammabarUU tracefree_SDD = ixp.zerorank2() for i in range(3): for j in range(3): tracefree_SDD[i][j] = SDD[i][j] for i in range(3): for j in range(3): for k in range(3): for m in range(3): tracefree_SDD[i][j] += -sp.Rational(1,3)*Bq.gammabarDD[i][j]*gammabarUU[k][m]*SDD[k][m] # Step 3.c.ii: Define exp_m4phi = e^{-4 phi} Bq.phi_and_derivs() # Step 3.c.iii: Evaluate RHS for i in range(3): for j in range(3): Abar_rhsDDij = -8*PI*alpha*Bq.exp_m4phi*tracefree_SDD[i][j] sourceterm_a_rhsDD[i][j] = Abar_rhsDDij / rfm.ReDD[i][j] # Step 3.d: Stress-energy part of Lambdabar_rhsU = stressenergy_Lambdabar_rhsU sourceterm_Lambdabar_rhsU = ixp.zerorank1() for i in range(3): for j in range(3): sourceterm_Lambdabar_rhsU[i] += -16*PI*alpha*gammabarUU[i][j]*SD[j] for i in range(3): sourceterm_lambda_rhsU[i] = sourceterm_Lambdabar_rhsU[i] / rfm.ReU[i] # # # # Step 4: Add BSSN source terms to BSSN Constraints \[Back to [top](#toc)\] # $$\label{add_bssn_sourceterms_to_constraints}$$ # # Recall from above we need to make the following modifications: # \begin{eqnarray} # \ \mathcal{H} &=& \left[\mathcal{H}\right]_{\rm vacuum}\ {\color{blue}{-\ 16\pi \rho}} \\ # \mathcal{M}^i &=& \left[\mathcal{M}^i\right]_{\rm vacuum}\ {\color{blue}{-\ 8\pi S^i}}, # \end{eqnarray} # # where # $$ # S^i = \gamma^{ij} S_j, # $$ # and $\gamma^{ij}$ is the inverse ADM 3-metric. # In[6]: # Step 4: Add BSSN stress-energy source terms to BSSN constraints # Step 4.a: Initialize constraint source terms to zero. sourceterm_H = sp.sympify(0) sourceterm_MU = ixp.zerorank1() # Step 4.b: Add source term to the Hamiltonian constraint H sourceterm_H = -16*PI*rho # Step 4.c: Add source term to the momentum constraint M^i # Step 4.c.i: Compute gammaUU in terms of BSSN quantities import BSSN.ADM_in_terms_of_BSSN as AitoB AitoB.ADM_in_terms_of_BSSN() # Provides gammaUU # Step 4.c.ii: Raise S_i SU = ixp.zerorank1() for i in range(3): for j in range(3): SU[i] += AitoB.gammaUU[i][j]*SD[j] # Step 4.c.iii: Add source term to momentum constraint & rescale: for i in range(3): sourceterm_MU[i] = -8 * PI * SU[i] / rfm.ReU[i] # # # # Step 5: Code Validation against `BSSN.BSSN_stress_energy_source_terms` NRPy+ module \[Back to [top](#toc)\] # $$\label{code_validation}$$ # # Here, as a code validation check, we verify agreement in the SymPy expressions for the RHSs of the BSSN equations between # 1. this tutorial and # 2. the NRPy+ [BSSN.BSSN_stressenergy_source_terms](../edit/BSSN/BSSN_stressenergy_source_terms.py) module. # # By default, we analyze these expressions in SinhSpherical coordinates, though other coordinate systems may be chosen. # In[7]: # Step 5: Code Validation against BSSN.BSSN_stress_energy_source_terms NRPy+ module # We already have SymPy expressions for BSSN source terms # in terms of other SymPy variables. # # Here, we will use the above-defined BSSN stress-energy source term expressions # to validate against the same expressions in the # BSSN/BSSN_stress_energy_source_terms.py file, to ensure consistency between # this tutorial and the module itself. import BSSN.BSSN_stress_energy_source_terms as Bsest print("Consistency check between BSSN_stress_energy_source_terms tutorial and NRPy+ module: ALL SHOULD BE ZERO.") print("STRESS-ENERGY SOURCE TERMS:") Bsest.stress_energy_source_terms_ito_T4UU_and_ADM_or_BSSN_metricvars("BSSN") print("rho - Bsest.rho = " + str(rho - Bsest.rho)) print("S - Bsest.S = " + str(S - Bsest.S)) for i in range(3): print("SD["+str(i)+"] - Bsest.SD["+str(i)+"] = " + str(SD[i] - Bsest.SD[i])) for i in range(3): for j in range(3): print("SDD["+str(i)+"]["+str(j)+"] - Bsest.SDD["+str(i)+"]["+str(j)+"] = " + str(SDD[i][j] - Bsest.SDD[i][j])) print("\nBSSN RHSs SOURCE TERMS:") Bsest.BSSN_source_terms_for_BSSN_RHSs() print("sourceterm_trK_rhs - Bsest.sourceterm_trK_rhs = " + str(sourceterm_trK_rhs - Bsest.sourceterm_trK_rhs)) for i in range(3): for j in range(3): print("sourceterm_a_rhsDD["+str(i)+"]["+str(j)+"] - Bsest.sourceterm_a_rhsDD["+str(i)+"]["+str(j)+"] = " + str(sourceterm_a_rhsDD[i][j] - Bsest.sourceterm_a_rhsDD[i][j])) for i in range(3): print("sourceterm_lambda_rhsU["+str(i)+"] - Bsest.sourceterm_lambda_rhsU["+str(i)+"] = " + str(sourceterm_lambda_rhsU[i] - Bsest.sourceterm_lambda_rhsU[i])) print("\nBSSN CONSTRAINTS SOURCE TERMS:") Bsest.BSSN_source_terms_for_BSSN_constraints() print("sourceterm_H - Bsest.sourceterm_H = " + str(sourceterm_H - Bsest.sourceterm_H)) for i in range(3): print("sourceterm_MU["+str(i)+"] - Bsest.sourceterm_MU["+str(i)+"] = " + str(sourceterm_MU[i] - Bsest.sourceterm_MU[i])) # # # # Step 6: Output this notebook to $\LaTeX$-formatted PDF file \[Back to [top](#toc)\] # $$\label{latex_pdf_output}$$ # # The following code cell converts this Jupyter notebook into a proper, clickable $\LaTeX$-formatted PDF file. After the cell is successfully run, the generated PDF may be found in the root NRPy+ tutorial directory, with filename # [Tutorial-BSSN_stress_energy_source_terms.pdf](Tutorial-BSSN_stress_energy_source_terms.pdf) (Note that clicking on this link may not work; you may need to open the PDF file through another means.) # In[8]: import cmdline_helper as cmd # NRPy+: Multi-platform Python command-line interface cmd.output_Jupyter_notebook_to_LaTeXed_PDF("Tutorial-BSSN_stress_energy_source_terms")