{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<script async src=\"https://www.googletagmanager.com/gtag/js?id=UA-59152712-8\"></script>\n",
    "<script>\n",
    "  window.dataLayer = window.dataLayer || [];\n",
    "  function gtag(){dataLayer.push(arguments);}\n",
    "  gtag('js', new Date());\n",
    "\n",
    "  gtag('config', 'UA-59152712-8');\n",
    "</script>\n",
    "\n",
    "# Tutorial: Setting up the energy-momentum tensor of a massless scalar field\n",
    "\n",
    "## Authors: Leonardo Werneck & Zach Etienne\n",
    "\n",
    "# This module documents the construction of the energy-momentum tensor of a massless scalar field.\n",
    "\n",
    "**Notebook Status:** <font color='green'><b> Validated </b></font>\n",
    "\n",
    "**Validation Notes:** The expressions generated by the NRPy+ module corresponding to this tutorial notebook are used to demonstrate that the initial data for a massless scalar field satisfy Einstein's equations as expected [in this tutorial notebook](Tutorial-Start_to_Finish-BSSNCurvilinear-Setting_up_ScalarField_initial_data).</font>\n",
    "\n",
    "## Python module containing the final expressions constructed here: **[ScalarField/ScalarField_Tmunu.py](../edit/ScalarField/ScalarField_Tmunu.py)**\n",
    "\n",
    "<a id='toc'></a>\n",
    "\n",
    "# Table of Contents\n",
    "$$\\label{toc}$$\n",
    "\n",
    "The module is organized as follows\n",
    "\n",
    "0. [Preliminaries](#preliminaries): The energy momentum tensor of a massless scalar field\n",
    "1. [Step 1](#initializenrpy): Initialize core NRPy+ modules\n",
    "1. [Step 2](#sf4d): The 4-derivatives of the scalar field: $\\partial^{\\mu}\\varphi$\n",
    "1. [Step 3](#energy_momentum_tensor): The energy momentum tensor: $T^{\\mu\\nu}$\n",
    "1. [Step 4](#code_validation): Validation against the [ScalarField/ScalarField_Tmunu.py](../edit/ScalarField/ScalarField_Tmunu.py) module\n",
    "1. [Step 5](#latex_pdf_output): Output this module to $\\LaTeX$-formatted PDF"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='preliminaries'></a>\n",
    "\n",
    "# Preliminaries: The energy momentum tensor of a massless scalar field \\[Back to [top](#toc)\\]\n",
    "$$\\label{preliminaries}$$\n",
    "\n",
    "The energy-momentum tensor for a massless scalar field is given by eq. (5.232) of [B&S](https://books.google.com.br/books/about/Numerical_Relativity.html?id=dxU1OEinvRUC&redir_esc=y), which we right here in contravariant form\n",
    "\n",
    "$$\n",
    "T^{\\mu\\nu} = \\partial^{\\mu}\\varphi\\partial^{\\nu}\\varphi - \\frac{1}{2}g^{\\mu\\nu}\\left(\\partial^{\\lambda}\\varphi\\partial_{\\lambda}\\varphi\\right)\\ .\n",
    "$$\n",
    "\n",
    "This is a key tensor in the problem of gravitational collapse of a massless scalar field, since it will be responsible for how the geometry changes in the presence of the scalar field. In this tutorial module we will be implementing this tensor."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='initializenrpy'></a>\n",
    "\n",
    "# Step 1: Initialize core NRPy+ modules \\[Back to [top](#toc)\\]\n",
    "$$\\label{initializenrpy}$$\n",
    "\n",
    "Let's start by importing all the needed modules from NRPy+:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2021-06-15T10:05:20.101241Z",
     "iopub.status.busy": "2021-06-15T10:05:20.100775Z",
     "iopub.status.idle": "2021-06-15T10:05:20.682804Z",
     "shell.execute_reply": "2021-06-15T10:05:20.682226Z"
    }
   },
   "outputs": [],
   "source": [
    "# Step 1.a: import all needed modules from NRPy+:\n",
    "import sympy as sp                         # SymPy: The Python computer algebra package upon 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 reference_metric as rfm             # NRPy+: Reference metric support\n",
    "import BSSN.BSSN_quantities as Bq          # NRPy+: BSSN quantities\n",
    "import BSSN.ADM_in_terms_of_BSSN as BtoA   # NRPy+: ADM quantities in terms of BSSN quantities\n",
    "import BSSN.ADMBSSN_tofrom_4metric as ADMg # NRPy+: ADM 4-metric to/from ADM or BSSN quantities\n",
    "\n",
    "# Step 1.b: Set the coordinate system for the numerical grid\n",
    "coord_system = \"Spherical\"\n",
    "par.set_parval_from_str(\"reference_metric::CoordSystem\",coord_system)\n",
    "\n",
    "# Step 1.c: 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",
    "par.set_parval_from_str(\"grid::DIM\",DIM)\n",
    "\n",
    "# Step 1.d: 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()\n",
    "\n",
    "# Step 1.e: Set the theta and phi axes to be the symmetry axes; i.e., axis \"1\" and \"2\",\n",
    "#           corresponding to the i1 and i2 directions. This sets all spatial derivatives\n",
    "#           in the theta and phi directions to zero (analytically).\n",
    "par.set_parval_from_str(\"indexedexp::symmetry_axes\",\"12\")\n",
    "\n",
    "# Step 1.e: Import all basic (unrescaled) BSSN scalars & tensors\n",
    "Bq.BSSN_basic_tensors()\n",
    "alpha = Bq.alpha\n",
    "betaU = Bq.betaU\n",
    "\n",
    "# Step 1.g: Define ADM quantities in terms of BSSN quantities\n",
    "BtoA.ADM_in_terms_of_BSSN()\n",
    "gammaDD = BtoA.gammaDD\n",
    "gammaUU = BtoA.gammaUU\n",
    "\n",
    "# Step 1.h: Define scalar field quantitites\n",
    "sf_dD   = ixp.declarerank1(\"sf_dD\")\n",
    "Pi      = sp.Symbol(\"sfM\",real=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='sf4d'></a>\n",
    "\n",
    "# Step 2: The 4-derivatives of the scalar field: $\\partial^{\\mu}\\varphi$ \\[Back to [top](#toc)\\]\n",
    "$$\\label{sf4d}$$\n",
    "\n",
    "Consider the ADM 4-metric (eq. 2.119 of B&S)\n",
    "\n",
    "$$\n",
    "g^{\\mu\\nu}=\\begin{pmatrix}\n",
    "-\\alpha^{-2} & \\alpha^{-2}\\beta^{i}\\\\\n",
    "\\alpha^{-2}\\beta^{j} & \\gamma^{ij} - \\alpha^{-2}\\beta^{i}\\beta^{j}\n",
    "\\end{pmatrix}\\ ,\n",
    "$$\n",
    "\n",
    "and the definition of the scalar field's conjugate momentum, $\\Pi$, as given by eq. 2.522 of B&S\n",
    "\n",
    "$$\n",
    "\\Pi\\equiv-\\frac{1}{\\alpha}\\left[\\partial_{t}\\varphi - \\beta^{i}\\partial_{i}\\varphi\\right]\\ .\n",
    "$$\n",
    "\n",
    "Then we have\n",
    "\n",
    "\\begin{align}\n",
    "\\partial^{t}\\varphi &= g^{tt}\\partial_{t}\\varphi + g^{ti}\\partial_{i}\\varphi\\nonumber\\\\\n",
    "&= -\\alpha^{-2}\\partial_{t}\\varphi + \\alpha^{-2}\\beta^{i}\\partial_{i}\\varphi\\nonumber\\\\\n",
    "&= \\alpha^{-1}\\left[-\\frac{1}{\\alpha}\\left(\\partial_{t}\\varphi - \\beta^{i}\\partial_{i}\\varphi\\right)\\right]\\nonumber\\\\\n",
    "&= \\frac{\\Pi}{\\alpha}\\ .\n",
    "\\end{align}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2021-06-15T10:05:20.686039Z",
     "iopub.status.busy": "2021-06-15T10:05:20.685529Z",
     "iopub.status.idle": "2021-06-15T10:05:20.687579Z",
     "shell.execute_reply": "2021-06-15T10:05:20.687068Z"
    }
   },
   "outputs": [],
   "source": [
    "# Step 2a: Set up \\partial^{t}\\varphi = Pi/alpha\n",
    "sf4dU = ixp.zerorank1(DIM=4)\n",
    "sf4dU[0] = Pi / alpha"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we look at\n",
    "\n",
    "\\begin{align}\n",
    "\\partial^{i}\\varphi &= g^{it}\\partial_{t}\\varphi + g^{ij}\\partial_{j}\\varphi\\nonumber\\\\\n",
    "&=\\alpha^{-2}\\beta^{i}\\partial_{t}\\varphi + \\gamma^{ij}\\partial_{j}\\varphi - \\alpha^{-2}\\beta^{i}\\beta^{j}\\partial_{j}\\varphi\\nonumber\\\\\n",
    "&=-\\alpha^{-1}\\beta^{i}\\left[-\\frac{1}{\\alpha}\\left(\\partial_{t}\\varphi-\\beta^{j}\\partial_{j}\\varphi\\right)\\right] + \\gamma^{ij}\\partial_{j}\\varphi\\nonumber\\\\\n",
    "&=-\\frac{\\Pi}{\\alpha}\\beta^{i} + \\gamma^{ij}\\partial_{j}\\varphi\\ .\n",
    "\\end{align}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2021-06-15T10:05:20.695054Z",
     "iopub.status.busy": "2021-06-15T10:05:20.694609Z",
     "iopub.status.idle": "2021-06-15T10:05:20.696519Z",
     "shell.execute_reply": "2021-06-15T10:05:20.696108Z"
    }
   },
   "outputs": [],
   "source": [
    "# Step 2b: Set up \\partial^{i}\\varphi = -Pi*beta^{i}/alpha + gamma^{ij}\\partial_{j}\\varphi\n",
    "for i in range(DIM):\n",
    "    sf4dU[i+1] = -Pi * betaU[i] / alpha\n",
    "    for j in range(DIM):\n",
    "        sf4dU[i+1] += gammaUU[i][j] * sf_dD[j]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The last step is to set up the contraction\n",
    "\n",
    "\\begin{align}\n",
    "\\partial^{\\lambda}\\varphi\\partial_{\\lambda}\\varphi &= \\partial^{t}\\varphi\\partial_{t}\\varphi + \\partial^{i}\\varphi\\partial_{i}\\varphi\\nonumber\\\\\n",
    "&=\\frac{\\Pi}{\\alpha}\\partial_{t}\\varphi - \\frac{\\Pi}{\\alpha}\\beta^{i}\\partial_{i}\\varphi + \\gamma^{ij}\\partial_{i}\\varphi\\partial_{j}\\varphi\\nonumber\\\\\n",
    "&= -\\Pi\\left[-\\frac{1}{\\alpha}\\left(\\partial_{t}\\varphi-\\beta^{i}\\partial_{i}\\varphi\\right)\\right] + \\gamma^{ij}\\partial_{i}\\varphi\\partial_{j}\\varphi\\nonumber\\\\\n",
    "&= -\\Pi^2 + \\gamma^{ij}\\partial_{i}\\varphi\\partial_{j}\\varphi\\ .\n",
    "\\end{align}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2021-06-15T10:05:20.700423Z",
     "iopub.status.busy": "2021-06-15T10:05:20.700006Z",
     "iopub.status.idle": "2021-06-15T10:05:20.702056Z",
     "shell.execute_reply": "2021-06-15T10:05:20.701648Z"
    }
   },
   "outputs": [],
   "source": [
    "# Step 2c: Set up \\partial^{i}\\varphi\\partial_{i}\\varphi = -Pi**2 + gamma^{ij}\\partial_{i}\\varphi\\partial_{j}\\varphi\n",
    "sf4d2 = -Pi**2\n",
    "for i in range(DIM):\n",
    "    for j in range(DIM):\n",
    "        sf4d2 += gammaUU[i][j] * sf_dD[i] * sf_dD[j]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='energy_momentum_tensor'></a>\n",
    "\n",
    "# Step 3: The energy momentum tensor: $T^{\\mu\\nu}$ \\[Back to [top](#toc)\\]\n",
    "$$\\label{energy_momentum_tensor}$$\n",
    "\n",
    "We start by setting up the ADM 4-metric $g^{\\mu\\nu}$, given by eq. (2.119) in [B&S](https://books.google.com.br/books/about/Numerical_Relativity.html?id=dxU1OEinvRUC&redir_esc=y),\n",
    "\n",
    "$$\n",
    "g^{\\mu\\nu}=\\begin{pmatrix}\n",
    "-\\alpha^{-2} & \\alpha^{-2}\\beta^{i}\\\\\n",
    "\\alpha^{-2}\\beta^{j} & \\gamma^{ij} - \\alpha^{-2}\\beta^{i}\\beta^{j}\n",
    "\\end{pmatrix}\\ .\n",
    "$$\n",
    "\n",
    "We do this be calling the [BSSN.adm_four_metric_conversions.py](../edit/BSSN/adm_four_metric_conversions.py) module."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2021-06-15T10:05:20.711589Z",
     "iopub.status.busy": "2021-06-15T10:05:20.711182Z",
     "iopub.status.idle": "2021-06-15T10:05:20.713256Z",
     "shell.execute_reply": "2021-06-15T10:05:20.712745Z"
    }
   },
   "outputs": [],
   "source": [
    "# Step 3a: Setting up g^{\\mu\\nu}\n",
    "ADMg.g4UU_ito_BSSN_or_ADM(\"ADM\",gammaDD=gammaDD,betaU=betaU,alpha=alpha, gammaUU=gammaUU)\n",
    "g4UU = ADMg.g4UU"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We then focus on the energy momentum tensor $T^{\\mu\\nu}$ for a massless scalar field, $\\varphi$ (cf. eq. 5.232 of [B&S](https://books.google.com.br/books/about/Numerical_Relativity.html?id=dxU1OEinvRUC&redir_esc=y) with $V(\\varphi)=0$)\n",
    "\n",
    "$$\n",
    "T^{\\mu\\nu} = \\partial^{\\mu}\\varphi\\partial^{\\nu}\\varphi - \\frac{1}{2}g^{\\mu\\nu}\\left(\\underbrace{\\partial_{\\lambda}\\varphi\\partial^{\\lambda}\\varphi}_{\\equiv \\rm sf4d2}\\right)\\ .\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2021-06-15T10:05:20.726077Z",
     "iopub.status.busy": "2021-06-15T10:05:20.724741Z",
     "iopub.status.idle": "2021-06-15T10:05:20.727857Z",
     "shell.execute_reply": "2021-06-15T10:05:20.727448Z"
    }
   },
   "outputs": [],
   "source": [
    "# Step 3b: Setting up T^{\\mu\\nu} for a massless scalar field\n",
    "T4UU = ixp.zerorank2(DIM=4)\n",
    "for mu in range(4):\n",
    "    for nu in range(4):\n",
    "        T4UU[mu][nu] = sf4dU[mu] * sf4dU[nu] - sp.Rational(1,2) * g4UU[mu][nu] * sf4d2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='code_validation'></a>\n",
    "\n",
    "# Step 4: Validation against the [ScalarField/ScalarField_Tmunu.py](../edit/ScalarField/ScalarField_Tmunu.py) module  \\[Back to [top](#toc)\\]\n",
    "$$\\label{code_validation}$$\n",
    "\n",
    "Here we perform a code validation. We verify agreement in the SymPy expressions for the energy-momentum tensor of a scalar field between\n",
    "1. this tutorial notebook and \n",
    "2. the [ScalarField/ScalarField_Tmunu.py](../edit/ScalarField/ScalarField/ScalarField_Tmunu.py) NRPy+ module.\n",
    "\n",
    "By default, we analyze the RHSs in Spherical coordinates, though other coordinate systems may be chosen."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2021-06-15T10:05:20.730832Z",
     "iopub.status.busy": "2021-06-15T10:05:20.730324Z",
     "iopub.status.idle": "2021-06-15T10:05:22.412864Z",
     "shell.execute_reply": "2021-06-15T10:05:22.412372Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Consistency check between this tutorial and the ScalarField.ScalarField_Tmunu.py module: ALL SHOULD BE ZERO\n",
      "\n",
      "T4UU[0][0] - sfTmunu.T4UU[0][0] = 0\n",
      "T4UU[0][1] - sfTmunu.T4UU[0][1] = 0\n",
      "T4UU[0][2] - sfTmunu.T4UU[0][2] = 0\n",
      "T4UU[0][3] - sfTmunu.T4UU[0][3] = 0\n",
      "T4UU[1][0] - sfTmunu.T4UU[1][0] = 0\n",
      "T4UU[1][1] - sfTmunu.T4UU[1][1] = 0\n",
      "T4UU[1][2] - sfTmunu.T4UU[1][2] = 0\n",
      "T4UU[1][3] - sfTmunu.T4UU[1][3] = 0\n",
      "T4UU[2][0] - sfTmunu.T4UU[2][0] = 0\n",
      "T4UU[2][1] - sfTmunu.T4UU[2][1] = 0\n",
      "T4UU[2][2] - sfTmunu.T4UU[2][2] = 0\n",
      "T4UU[2][3] - sfTmunu.T4UU[2][3] = 0\n",
      "T4UU[3][0] - sfTmunu.T4UU[3][0] = 0\n",
      "T4UU[3][1] - sfTmunu.T4UU[3][1] = 0\n",
      "T4UU[3][2] - sfTmunu.T4UU[3][2] = 0\n",
      "T4UU[3][3] - sfTmunu.T4UU[3][3] = 0\n"
     ]
    }
   ],
   "source": [
    "import ScalarField.ScalarField_Tmunu as sfTmunu # NRPyCritCol: Scalar field energy-momentum tensor\n",
    "sfTmunu.ScalarField_Tmunu()\n",
    "\n",
    "print(\"Consistency check between this tutorial and the ScalarField.ScalarField_Tmunu.py module: ALL SHOULD BE ZERO\\n\")\n",
    "\n",
    "for mu in range(4):\n",
    "    for nu in range(4):\n",
    "        print(\"T4UU[\"+str(mu)+\"][\"+str(nu)+\"] - sfTmunu.T4UU[\"+str(mu)+\"][\"+str(nu)+\"] = \"+str(sp.simplify(T4UU[mu][nu] - sfTmunu.T4UU[mu][nu])))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='latex_pdf_output'></a>\n",
    "\n",
    "# Step 5: Output this module 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-ScalarField_Tmunu.pdf](Tutorial-ScalarField_Tmunu.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": 8,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2021-06-15T10:05:22.415760Z",
     "iopub.status.busy": "2021-06-15T10:05:22.415220Z",
     "iopub.status.idle": "2021-06-15T10:05:24.657551Z",
     "shell.execute_reply": "2021-06-15T10:05:24.657002Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Created Tutorial-ScalarField_Tmunu.tex, and compiled LaTeX file to PDF file\n",
      "    Tutorial-ScalarField_Tmunu.pdf\n"
     ]
    }
   ],
   "source": [
    "import cmdline_helper as cmd    # NRPy+: Multi-platform Python command-line interface\n",
    "cmd.output_Jupyter_notebook_to_LaTeXed_PDF(\"Tutorial-ScalarField_Tmunu\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}