{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "# [BSSN](http://www2.yukawa.kyoto-u.ac.jp/~yuichiro.sekiguchi/3+1.pdf) Hamiltonian and momentum constraint equations, in ***curvilinear*** coordinates, using a covariant reference metric approach: C code generation\n", "\n", "## Authors: Ian Ruchlin & Zach Etienne\n", "### Formatting improvements courtesy Brandon Clark\n", "\n", "## This module constructs the BSSN Hamiltonian and momentum constraint equations as symbolic (SymPy) expressions, in terms of the core BSSN quantities $\\left\\{h_{i j},a_{i j},\\phi, K, \\lambda^{i}, \\alpha, \\mathcal{V}^i, \\mathcal{B}^i\\right\\}$, as defined in [Ruchlin, Etienne, and Baumgarte (2018)](https://arxiv.org/abs/1712.07658) (see also [Baumgarte, Montero, Cordero-Carrión, and Müller (2012)](https://arxiv.org/abs/1211.6632).\n", "\n", "### This module implements a generic curvilinear coordinate reference metric approach matching that of [Ruchlin, Etienne, and Baumgarte (2018)](https://arxiv.org/abs/1712.07658), which is an extension of the spherical coordinate 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). *See also citations within each article.*\n", "\n", "**Notebook Status:** Validated \n", "\n", "**Validation Notes:** All expressions generated in this module have been validated against a trusted code where applicable (the original NRPy+/SENR code, which itself was validated against [Baumgarte's code](https://arxiv.org/abs/1211.6632)).\n", "\n", "### NRPy+ Source Code for this module: [BSSN/BSSN_constraints.py](../edit/BSSN/BSSN_constraints.py)\n", "\n", "\n", "[comment]: <> (Introduction: TODO)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Table of Contents\n", "$$\\label{toc}$$\n", "\n", "This notebook is organized as follows\n", "\n", "1. [Step 1](#initializenrpy): Initialize needed Python/NRPy+ modules\n", "1. [Step 2](#hamiltonianconstraint): Construct the Hamiltonian constraint $\\mathcal{H}$.\n", "1. [Step 3](#momentumconstraint): Construct the momentum constraint $\\mathcal{M}^i$.\n", "1. [Step 4](#code_validation): Code Validation against `BSSN.BSSN_constraints` NRPy+ module\n", "1. [Step 5](#latex_pdf_output): Output this notebook to $\\LaTeX$-formatted PDF file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 1: Initialize needed Python/NRPy+ modules \\[Back to [top](#toc)\\]\n", "$$\\label{initializenrpy}$$\n", "\n", "We start by loading the needed modules. Notably, this module depends on several quantities defined in the [BSSN/BSSN_quantities.py](../edit/BSSN/BSSN_quantities.py) Python code, documented in the NRPy+ [BSSN quantities](Tutorial-BSSN_quantities.ipynb). In [Step 2](#hamiltonianconstraint) we call functions within [BSSN.BSSN_quantities](../edit/BSSN/BSSN_quantities.py) to define quantities needed in this module." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Step 1: Initialize needed Python/NRPy+ modules\n", "import sympy as sp # SymPy, Python's core symbolic algebra package on which NRPy+ depends\n", "import NRPy_param_funcs as par # NRPy+: Parameter interface\n", "import indexedexp as ixp # NRPy+: Symbolic indexed expression (e.g., tensors, vectors, etc.) support\n", "import grid as gri # NRPy+: Functions having to do with numerical grids\n", "import reference_metric as rfm # NRPy+: Reference metric support\n", "import BSSN.BSSN_quantities as Bq\n", "\n", "# Step 1.a: Set spatial dimension (must be 3 for BSSN, as BSSN is\n", "# a 3+1-dimensional decomposition of the general\n", "# relativistic field equations)\n", "DIM = 3\n", "\n", "# Step 1.b: Given the chosen coordinate system, set up\n", "# corresponding reference metric and needed\n", "# reference metric quantities\n", "# The following function call sets up the reference metric\n", "# and related quantities, including rescaling matrices ReDD,\n", "# ReU, and hatted quantities.\n", "rfm.reference_metric()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 2: $\\mathcal{H}$, the Hamiltonian constraint \\[Back to [top](#toc)\\]\n", "$$\\label{hamiltonianconstraint}$$\n", "\n", "Next we define the Hamiltonian constraint. Eq. 13 of [Baumgarte *et al.*](https://arxiv.org/pdf/1211.6632.pdf) yields:\n", "$$\n", "\\mathcal{H} = {\\underbrace {\\textstyle \\frac{2}{3} K^2}_{\\rm Term\\ 1}} - \n", "{\\underbrace {\\textstyle \\bar{A}_{ij} \\bar{A}^{ij}}_{\\rm Term\\ 2}} + \n", "{\\underbrace {\\textstyle e^{-4\\phi} \\left(\\bar{R} - 8 \\bar{D}^i \\phi \\bar{D}_i \\phi - 8 \\bar{D}^2 \\phi\\right)}_{\\rm Term\\ 3}}\n", "$$" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Step 2: The Hamiltonian constraint.\n", "# First declare all needed variables\n", "Bq.declare_BSSN_gridfunctions_if_not_declared_already() # Sets trK\n", "Bq.BSSN_basic_tensors() # Sets AbarDD\n", "Bq.gammabar__inverse_and_derivs() # Sets gammabarUU\n", "Bq.AbarUU_AbarUD_trAbar_AbarDD_dD() # Sets AbarUU and AbarDD_dD\n", "Bq.RicciBar__gammabarDD_dHatD__DGammaUDD__DGammaU() # Sets RbarDD\n", "Bq.phi_and_derivs() # Sets phi_dBarD & phi_dBarDD\n", "\n", "# Term 1: 2/3 K^2\n", "H = sp.Rational(2,3)*Bq.trK**2\n", "\n", "# Term 2: -A_{ij} A^{ij}\n", "for i in range(DIM):\n", " for j in range(DIM):\n", " H += -Bq.AbarDD[i][j]*Bq.AbarUU[i][j]\n", "\n", "# Term 3a: trace(Rbar)\n", "Rbartrace = sp.sympify(0)\n", "for i in range(DIM):\n", " for j in range(DIM):\n", " Rbartrace += Bq.gammabarUU[i][j]*Bq.RbarDD[i][j]\n", "\n", "# Term 3b: -8 \\bar{\\gamma}^{ij} \\bar{D}_i \\phi \\bar{D}_j \\phi = -8*phi_dBar_times_phi_dBar\n", "# Term 3c: -8 \\bar{\\gamma}^{ij} \\bar{D}_i \\bar{D}_j \\phi = -8*phi_dBarDD_contraction\n", "phi_dBar_times_phi_dBar = sp.sympify(0) # Term 3b\n", "phi_dBarDD_contraction = sp.sympify(0) # Term 3c\n", "for i in range(DIM):\n", " for j in range(DIM):\n", " phi_dBar_times_phi_dBar += Bq.gammabarUU[i][j]*Bq.phi_dBarD[i]*Bq.phi_dBarD[j]\n", " phi_dBarDD_contraction += Bq.gammabarUU[i][j]*Bq.phi_dBarDD[i][j]\n", "\n", "# Add Term 3:\n", "H += Bq.exp_m4phi*(Rbartrace - 8*(phi_dBar_times_phi_dBar + phi_dBarDD_contraction))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 3: $\\mathcal{M}^i$, the momentum constraint \\[Back to [top](#toc)\\]\n", "$$\\label{momentumconstraint}$$\n", "\n", "***Courtesy Ian Ruchlin***\n", "\n", "The following definition of the momentum constraint is a simplification of Eq. 47 or [Ruchlin, Etienne, & Baumgarte (2018)](https://arxiv.org/pdf/1712.07658.pdf), which itself was a corrected version of the momentum constraint presented in Eq. 14 of [Baumgarte *et al*](https://arxiv.org/pdf/1211.6632.pdf).\n", "\n", "Start with the physical momentum constraint\n", "$$\n", "\\mathcal{M}^{i} \\equiv D_{j} \\left ( K^{i j} - \\gamma^{i j} K \\right ) = 0 \\; .\n", "$$\n", "Expanding and using metric compatibility with the physical covariant derivative $D_{i}$ yields\n", "$$\n", "\\mathcal{M}^{i} = D_{j} K^{i j} - \\gamma^{i j} \\partial_{j} K \\; .\n", "$$\n", "The physical extrinsic curvature $K_{i j}$ is related to the trace-free extrinsic curvature $A_{i j}$ by\n", "$$\n", "K_{i j} = A_{i j} + \\frac{1}{3} \\gamma_{i j} K \\; .\n", "$$\n", "Thus,\n", "$$\n", "\\mathcal{M}^{i} = D_{j} A^{i j} - \\frac{2}{3} \\gamma^{i j} \\partial_{j} K \\; .\n", "$$\n", "The physical metric $\\gamma_{i j}$ is related to the conformal metric $\\bar{\\gamma}_{i j}$ by the conformal rescaling\n", "$$\n", "\\gamma_{i j} = e^{4 \\phi} \\bar{\\gamma}_{i j} \\; ,\n", "$$\n", "and similarly for the trace-free extrinsic curvature\n", "$$\n", "A_{i j} = e^{4 \\phi} \\bar{A}_{i j} \\; .\n", "$$\n", "It can be shown (Eq. (3.34) in Baumgarte & Shapiro (2010) with $\\alpha = -4$ and $\\psi = e^{\\phi}$) that the physical and conformal covariant derivatives obey\n", "$$\n", "D_{j} A^{i j} = e^{-10 \\phi} \\bar{D}_{j} \\left (e^{6 \\phi} \\bar{A}^{i j} \\right ) \\; .\n", "$$\n", "Then, the constraint becomes\n", "$$\n", "\\mathcal{M}^i = e^{-4\\phi} \\left(\n", "{\\underbrace {\\textstyle \\bar{D}_j \\bar{A}^{ij}}_{\\rm Term\\ 1}} + \n", "{\\underbrace {\\textstyle 6 \\bar{A}^{ij}\\partial_j \\phi}_{\\rm Term\\ 2}} - \n", "{\\underbrace {\\textstyle \\frac{2}{3} \\bar{\\gamma}^{ij}\\partial_j K}_{\\rm Term\\ 3}}\\right) \\; .\n", "$$\n", "\n", "Let's first implement Terms 2 and 3:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Step 3: M^i, the momentum constraint\n", "\n", "MU = ixp.zerorank1()\n", "\n", "# Term 2: 6 A^{ij} \\partial_j \\phi:\n", "for i in range(DIM):\n", " for j in range(DIM):\n", " MU[i] += 6*Bq.AbarUU[i][j]*Bq.phi_dD[j]\n", "\n", "# Term 3: -2/3 \\bar{\\gamma}^{ij} K_{,j}\n", "trK_dD = ixp.declarerank1(\"trK_dD\") # Not defined in BSSN_RHSs; only trK_dupD is defined there.\n", "for i in range(DIM):\n", " for j in range(DIM):\n", " MU[i] += -sp.Rational(2,3)*Bq.gammabarUU[i][j]*trK_dD[j]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we turn our attention to Term 1. The covariant divergence involves upper indices in $\\bar{A}^{i j}$, but it would be easier for us to finite difference the rescaled $\\bar{A}_{i j}$. A simple application of the inverse conformal metric yields\n", "$$\n", "\\bar{D}_{j} \\bar{A}^{i j} = \\bar{\\gamma}^{i k} \\bar{\\gamma}^{j l} \\bar{D}_{j} \\bar{A}_{k l} \\; .\n", "$$\n", "As usual, the covariant derivative is related to the ordinary derivative using the conformal Christoffel symbols\n", "$$\n", "\\bar{D}_{k} \\bar{A}_{i j} = \\partial_{k} \\bar{A}_{i j} - \\bar{\\Gamma}^{l}_{k i} \\bar{A}_{l j} - \\bar{\\Gamma}^{l}_{k j} \\bar{A}_{i l} \\; .\n", "$$\n", "It is the ordinary derivative above that is approximated by finite difference. The BSSN formulation used here does not rely on spatial derivatives $\\partial_{k} \\bar{A}_{i j}$ in any of the right-hand-sides (except for the advection term, which uses the upwinded derivative), and so we must declare a new ordinary, centered stencil derivative field of rank 3." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# First define aDD_dD:\n", "aDD_dD = ixp.declarerank3(\"aDD_dD\",\"sym01\")\n", "\n", "# Then evaluate the conformal covariant derivative \\bar{D}_j \\bar{A}_{lm}\n", "AbarDD_dBarD = ixp.zerorank3()\n", "for i in range(DIM):\n", " for j in range(DIM):\n", " for k in range(DIM):\n", " AbarDD_dBarD[i][j][k] = Bq.AbarDD_dD[i][j][k]\n", " for l in range(DIM):\n", " AbarDD_dBarD[i][j][k] += -Bq.GammabarUDD[l][k][i]*Bq.AbarDD[l][j]\n", " AbarDD_dBarD[i][j][k] += -Bq.GammabarUDD[l][k][j]*Bq.AbarDD[i][l]\n", "\n", "# Term 1: Contract twice with the metric to make \\bar{D}_{j} \\bar{A}^{ij}\n", "for i in range(DIM):\n", " for j in range(DIM):\n", " for k in range(DIM):\n", " for l in range(DIM):\n", " MU[i] += Bq.gammabarUU[i][k]*Bq.gammabarUU[j][l]*AbarDD_dBarD[k][l][j]\n", "\n", "# Finally, we multiply by e^{-4 phi} and rescale the momentum constraint:\n", "for i in range(DIM):\n", " MU[i] *= Bq.exp_m4phi / rfm.ReU[i]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 4: Code Validation against `BSSN.BSSN_constraints` NRPy+ module \\[Back to [top](#toc)\\]\n", "$$\\label{code_validation}$$\n", "\n", "Here, as a code validation check, we verify agreement in the SymPy expressions for the RHSs of the BSSN equations between\n", "1. this tutorial and \n", "2. the NRPy+ [BSSN.BSSN_constraints](../edit/BSSN/BSSN_constraints.py) module.\n", "\n", "By default, we analyze these expressions in Spherical coordinates, though other coordinate systems may be chosen." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Consistency check between BSSN_constraints tutorial and NRPy+ module: ALL SHOULD BE ZERO.\n", "H - bssncon.H = 0\n", "MU[0] - bssncon.MU[0] = 0\n", "MU[1] - bssncon.MU[1] = 0\n", "MU[2] - bssncon.MU[2] = 0\n" ] } ], "source": [ "# Step 4: Code Validation against BSSN.BSSN_constraints NRPy+ module\n", "\n", "# We already have SymPy expressions for BSSN constraints\n", "# in terms of other SymPy variables. Even if we reset the\n", "# list of NRPy+ gridfunctions, these *SymPy* expressions for\n", "# BSSN constraint variables *will remain unaffected*.\n", "#\n", "# Here, we will use the above-defined BSSN constraint expressions\n", "# to validate against the same expressions in the\n", "# BSSN/BSSN_constraints.py file, to ensure consistency between\n", "# this tutorial and the module itself.\n", "#\n", "# Reset the list of gridfunctions, as registering a gridfunction\n", "# twice (in the bssnrhs.BSSN_RHSs() call) will spawn an error.\n", "gri.glb_gridfcs_list = []\n", "\n", "# Call the BSSN_RHSs() function from within the\n", "# BSSN/BSSN_RHSs.py module,\n", "# which should do exactly the same as in Steps 1-16 above.\n", "import BSSN.BSSN_constraints as bssncon\n", "bssncon.BSSN_constraints()\n", "\n", "print(\"Consistency check between BSSN_constraints tutorial and NRPy+ module: ALL SHOULD BE ZERO.\")\n", "\n", "print(\"H - bssncon.H = \" + str(H - bssncon.H))\n", "for i in range(DIM):\n", " print(\"MU[\"+str(i)+\"] - bssncon.MU[\"+str(i)+\"] = \" + str(MU[i] - bssncon.MU[i]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 5: Output this notebook to $\\LaTeX$-formatted PDF file \\[Back to [top](#toc)\\]\n", "$$\\label{latex_pdf_output}$$\n", "\n", "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\n", "[Tutorial-BSSN_constraints.pdf](Tutorial-BSSN_constraints.pdf) (Note that clicking on this link may not work; you may need to open the PDF file through another means.)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created Tutorial-BSSN_constraints.tex, and compiled LaTeX file to PDF file\n", " Tutorial-BSSN_constraints.pdf\n" ] } ], "source": [ "import cmdline_helper as cmd # NRPy+: Multi-platform Python command-line interface\n", "cmd.output_Jupyter_notebook_to_LaTeXed_PDF(\"Tutorial-BSSN_constraints\")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.3" } }, "nbformat": 4, "nbformat_minor": 2 }