{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "# Transforming BSSN Variables between Two Bases\n", "## Author: Zach Etienne\n", "\n", "\n", "## This notebook demonstrates the use of NRPy+ for the transformation of BSSN variables from one basis to another. The tutorial provides the procedure of Jacobian transformations on vectors and tensors to migrate rescaled BSSN variables from a source grid to a destination grid. This process is outlined, including code validation against the `BSSN.BSSN_basis_transforms` NRPy+ module.\n", "\n", "**Notebook Status:** Validated \n", "\n", "**Validation Notes:** This tutorial notebook has been confirmed to be self-consistent with its corresponding NRPy+ module, as documented [below](#code_validation). In addition, if the same basis & grid are used for both source and destination, source and destination tensors are identical. **Additional validation tests may have been performed, but are as yet, undocumented. (TODO)**\n", "\n", "### NRPy+ Source Code for this module: [BSSN/BSSN_basis_transforms.py](../edit/BSSN/BSSN_basis_transforms.py)\n", "\n", "\n", "\n", "## Introduction:\n", "\n", "Given the rescaled BSSN variables:\n", "\n", "$$\\left\\{h_{i j},a_{i j},\\phi, K, \\lambda^{i}, \\alpha, \\mathcal{V}^i, \\mathcal{B}^i\\right\\},$$ \n", "\n", "we perform needed Jacobian transformations to all vectors and tensors to migrate to another basis. This is a four-step process:\n", "\n", "1. Un-rescale all BSSN variables on source grid\n", "1. Transform source grid basis to Cartesian, using center of source grid as origin\n", "1. Basis transform from Cartesian to destination basis at point on destination grid (`xx0,xx1,xx2`)${}_{\\rm dst}$\n", "1. Compute rescaled BSSN quantities in destination basis" ] }, { "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 core Python/NRPy+ modules and BSSN variables; Unrescale all BSSN variables on source grid\n", "1. [Step 2](#srctocart): Transform source grid basis to Cartesian, using center of source grid as origin\n", "1. [Step 3](#carttodst): Basis transform from Cartesian to destination grid basis at point on destination grid (`xx0,xx1,xx2`)${}_{\\rm dst}$\n", "1. [Step 4](#rescaleindstbasis): Compute rescaled BSSN quantities in destination basis\n", "1. [Step 5](#code_validation): Code Validation Tests\n", " 1. [Step 5.a](#nrpy_module_validate): Confirm identical output to `BSSN.BSSN_basis_transforms` NRPy+ module\n", " 1. [Step 5.b](#confirm_same_basis_identity): Confirm that if same basis chosen for input and output, at the same points `(xx0,xx1,xx2)`, the output is identical to the input\n", "1. [Step 6](#latex_pdf_output): Output this notebook to $\\LaTeX$-formatted PDF file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 1: Initialize core Python/NRPy+ modules and BSSN variables; Unrescale all BSSN variables \\[Back to [top](#toc)\\]\n", "$$\\label{initializenrpy}$$\n", "\n", "Here we declare BSSN quantities on the source grid $$\\left\\{h_{i j},a_{i j},\\lambda^{i}, \\mathcal{V}^i, \\mathcal{B}^i\\right\\}$$ \n", "\n", "Unrescaling is documented in the [BSSN quantities tutorial notebook](Tutorial-BSSN_quantities.ipynb)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:20:37.892646Z", "iopub.status.busy": "2021-03-07T17:20:37.891674Z", "iopub.status.idle": "2021-03-07T17:20:39.551517Z", "shell.execute_reply": "2021-03-07T17:20:39.550810Z" } }, "outputs": [], "source": [ "# Step P1: Import needed NRPy+ core modules:\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 NRPy_param_funcs as par # NRPy+: Parameter interface\n", "\n", "# Step P2: Declare inputs\n", "# Input BSSN variables on source (\"src\") grid:\n", "src_hDD = ixp.declarerank2(\"src_hDD\",\"sym01\")\n", "src_aDD = ixp.declarerank2(\"src_aDD\",\"sym01\")\n", "src_lambdaU = ixp.declarerank1(\"src_lambdaU\")\n", "src_vetU = ixp.declarerank1(\"src_vetU\")\n", "src_betU = ixp.declarerank1(\"src_betU\")\n", "\n", "# Source (\"src\") grid basis and coordinate point (xx0,xx1,xx2)_{src} = src_xx[i]\n", "src_basis = \"SinhCylindrical\"\n", "src_xx = ixp.declarerank1(\"src_xx\")\n", "# Destination (\"dst\") grid basis and coordinate point (xx0,xx1,xx2)_{dst} = dst_xx[i]\n", "dst_basis = \"SinhSpherical\"\n", "dst_xx = ixp.declarerank1(\"dst_xx\")\n", "\n", "# Step 1: Unrescale all BSSN variables\n", "\n", "par.set_parval_from_str(\"reference_metric::CoordSystem\",src_basis)\n", "rfm.reference_metric()\n", "\n", "# STOLEN FROM BSSN/BSSN_quantities.py:\n", "# Step 1.a: gammabarDD and AbarDD:\n", "src_gammabarDD = ixp.zerorank2()\n", "src_AbarDD = ixp.zerorank2()\n", "for i in range(3):\n", " for j in range(3):\n", " # gammabar_{ij} = h_{ij}*ReDD[i][j] + gammahat_{ij}\n", " src_gammabarDD[i][j] = src_hDD[i][j] * rfm.ReDD[i][j] + rfm.ghatDD[i][j]\n", " # Abar_{ij} = a_{ij}*ReDD[i][j]\n", " src_AbarDD[i][j] = src_aDD[i][j] * rfm.ReDD[i][j]\n", "\n", "# Step 1.b: LambdabarU, betaU, and BU:\n", "src_LambdabarU = ixp.zerorank1()\n", "src_betaU = ixp.zerorank1()\n", "src_BU = ixp.zerorank1()\n", "for i in range(3):\n", " src_LambdabarU[i] = src_lambdaU[i] * rfm.ReU[i]\n", " src_betaU[i] = src_vetU[i] * rfm.ReU[i]\n", " src_BU[i] = src_betU[i] * rfm.ReU[i]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 2: Transform source grid basis to Cartesian, using center of source grid as origin \\[Back to [top](#toc)\\]\n", "$$\\label{srctocart}$$\n", "\n", "Within [`reference_metric.py`](../edit/reference_metric.py), the `compute_Jacobian_and_inverseJacobian_tofrom_Cartesian()` function defines Jacobians relative to the center of the source (reference metric) grid, at a point $x^j_{\\rm src}=$(`xx0,xx1,xx2`)${}_{\\rm src}$ on the source grid:\n", "$$\n", "{\\rm Jac\\_dUCart\\_dDsrcUD[i][j]} = \\frac{\\partial x^i_{\\rm Cart}}{\\partial x^j_{\\rm src}},\n", "$$\n", "\n", "via exact differentiation (courtesy SymPy), and the inverse Jacobian\n", "$$\n", "{\\rm Jac\\_dUsrc\\_dDCartUD[i][j]} = \\frac{\\partial x^i_{\\rm src}}{\\partial x^j_{\\rm Cart}},\n", "$$\n", "\n", "using NRPy+'s `generic_matrix_inverter3x3()` function. \n", "\n", "In terms of these, the transformation of BSSN tensors from `\"reference_metric::CoordSystem\"` coordinates to Cartesian may be written:\n", "\n", "\\begin{align}\n", "\\bar{\\Lambda}^i_{\\rm Cart} &= \\frac{\\partial x^i_{\\rm Cart}}{\\partial x^\\ell_{\\rm src}} \\bar{\\Lambda}^\\ell_{\\rm src}\\\\\n", "\\beta^i_{\\rm Cart} &= \\frac{\\partial x^i_{\\rm Cart}}{\\partial x^\\ell_{\\rm src}} \\beta^\\ell_{\\rm src}\\\\\n", "B^i_{\\rm Cart} &= \\frac{\\partial x^i_{\\rm Cart}}{\\partial x^\\ell_{\\rm src}} B^\\ell_{\\rm src}\\\\\n", "\\bar{\\gamma}^{\\rm Cart}_{ij} &= \n", "\\frac{\\partial x^\\ell_{\\rm src}}{\\partial x^i_{\\rm Cart}}\n", "\\frac{\\partial x^m_{\\rm src}}{\\partial x^j_{\\rm Cart}} \\bar{\\gamma}^{\\rm src}_{\\ell m}\\\\\n", "\\end{align}\n", "\n", "The transformation for vectors is provided by the [`reference_metric.py`](../edit/reference_metric.py) function `basis_transform_vectorU_from_rfmbasis_to_Cartesian(Jac_dUCart_dDrfmUD, src_vectorU)`, and the transformation for rank-2 covariant tensors is provided by `basis_transform_tensorDD_from_rfmbasis_to_Cartesian(Jac_dUrfm_dDCartUD, src_tensorDD)`, also found within `reference_metric.py`.\n", "\n", "After performing the basis transformation to Cartesian, we relabel `(xx0,xx1,xx2)` by `(src_xx0,src_xx1,src_xx2)` to avoid ambiguity." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:20:39.626226Z", "iopub.status.busy": "2021-03-07T17:20:39.590164Z", "iopub.status.idle": "2021-03-07T17:20:39.797030Z", "shell.execute_reply": "2021-03-07T17:20:39.796361Z" } }, "outputs": [], "source": [ "# Step 2: Transform source grid basis to Cartesian, using center of source grid as origin\n", "\n", "# Step 2.a: Construct Jacobian & Inverse Jacobians:\n", "Jac_dUCart_dDrfmUD,Jac_dUrfm_dDCartUD = rfm.compute_Jacobian_and_inverseJacobian_tofrom_Cartesian()\n", "\n", "# Step 2.b: Convert basis of all BSSN *vectors* to Cartesian\n", "CartLambdabarU = rfm.basis_transform_vectorU_from_rfmbasis_to_Cartesian(Jac_dUCart_dDrfmUD, src_LambdabarU)\n", "CartbetaU = rfm.basis_transform_vectorU_from_rfmbasis_to_Cartesian(Jac_dUCart_dDrfmUD, src_betaU)\n", "CartBU = rfm.basis_transform_vectorU_from_rfmbasis_to_Cartesian(Jac_dUCart_dDrfmUD, src_BU)\n", "\n", "# Step 2.c: Convert basis of all BSSN *tensors* to Cartesian\n", "CartgammabarDD = rfm.basis_transform_tensorDD_from_rfmbasis_to_Cartesian(Jac_dUrfm_dDCartUD, src_gammabarDD)\n", "CartAbarDD = rfm.basis_transform_tensorDD_from_rfmbasis_to_Cartesian(Jac_dUrfm_dDCartUD, src_AbarDD)\n", "\n", "# Step 2.d: All BSSN tensor/vector quantities are written in terms of\n", "# rescaled quantities and (xx0,xx1,xx2) on the SOURCE grid.\n", "# To avoid confusion with (xx0,xx1,xx2) on the DESTINATION grid,\n", "# we replace (xx0,xx1,xx2) with (src_xx0,src_xx1,src_xx2) here:\n", "for i in range(3):\n", " for k in range(3):\n", " CartLambdabarU[i] = CartLambdabarU[i].subs(rfm.xx[k],src_xx[k])\n", " CartbetaU[i] = CartbetaU[i].subs(rfm.xx[k],src_xx[k])\n", " CartBU[i] = CartBU[i].subs(rfm.xx[k],src_xx[k])\n", "for i in range(3):\n", " for j in range(3):\n", " for k in range(3):\n", " CartgammabarDD[i][j] = CartgammabarDD[i][j].subs(rfm.xx[k],src_xx[k])\n", " CartAbarDD[i][j] = CartAbarDD[i][j].subs(rfm.xx[k],src_xx[k])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 3: Basis transform from Cartesian to destination grid basis at point on destination grid (`xx0,xx1,xx2`)${}_{\\rm dst}$ \\[Back to [top](#toc)\\]\n", "$$\\label{carttodst}$$\n", "\n", "We define Jacobians relative to the center of the destination grid, at a point $x^j_{\\rm dst}=$(`xx0,xx1,xx2`)${}_{\\rm dst}$ on the destination grid:\n", "$$\n", "{\\rm Jac\\_dUCart\\_dDdstUD[i][j]} = \\frac{\\partial x^i_{\\rm Cart}}{\\partial x^j_{\\rm dst}},\n", "$$\n", "\n", "via exact differentiation (courtesy SymPy), and the inverse Jacobian\n", "$$\n", "{\\rm Jac\\_dUdst\\_dDCartUD[i][j]} = \\frac{\\partial x^i_{\\rm dst}}{\\partial x^j_{\\rm Cart}},\n", "$$\n", "\n", "using NRPy+'s `generic_matrix_inverter3x3()` function. In terms of these, the transformation of BSSN tensors from Cartesian to the destination grid's `\"reference_metric::CoordSystem\"` coordinates may be written:\n", "\n", "\\begin{align}\n", "\\bar{\\Lambda}^i_{\\rm dst} &= \\frac{\\partial x^i_{\\rm dst}}{\\partial x^\\ell_{\\rm Cart}} \\bar{\\Lambda}^\\ell_{\\rm Cart}\\\\\n", "\\beta^i_{\\rm dst} &= \\frac{\\partial x^i_{\\rm dst}}{\\partial x^\\ell_{\\rm Cart}} \\beta^\\ell_{\\rm Cart}\\\\\n", "B^i_{\\rm dst} &= \\frac{\\partial x^i_{\\rm dst}}{\\partial x^\\ell_{\\rm Cart}} B^\\ell_{\\rm Cart}\\\\\n", "\\bar{\\gamma}^{\\rm dst}_{ij} &= \n", "\\frac{\\partial x^\\ell_{\\rm Cart}}{\\partial x^i_{\\rm dst}}\n", "\\frac{\\partial x^m_{\\rm Cart}}{\\partial x^j_{\\rm dst}} \\bar{\\gamma}^{\\rm Cart}_{\\ell m}\\\\\n", "\\end{align}" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:20:39.861677Z", "iopub.status.busy": "2021-03-07T17:20:39.835922Z", "iopub.status.idle": "2021-03-07T17:20:41.155140Z", "shell.execute_reply": "2021-03-07T17:20:41.155679Z" }, "scrolled": true }, "outputs": [], "source": [ "# Step 3: Transform BSSN tensors in Cartesian basis to destination grid basis, using center of dest. grid as origin\n", "\n", "# Step 3.a: Set up destination grid coordinate system\n", "par.set_parval_from_str(\"reference_metric::CoordSystem\",dst_basis)\n", "rfm.reference_metric()\n", "\n", "# Step 3.b: Next construct Jacobian and inverse Jacobian matrices:\n", "Jac_dUCart_dDrfmUD,Jac_dUrfm_dDCartUD = rfm.compute_Jacobian_and_inverseJacobian_tofrom_Cartesian()\n", "\n", "# Step 3.c: Convert basis of all BSSN *vectors* from Cartesian to destination basis\n", "dst_LambdabarU = rfm.basis_transform_vectorU_from_Cartesian_to_rfmbasis(Jac_dUrfm_dDCartUD, CartLambdabarU)\n", "dst_betaU = rfm.basis_transform_vectorU_from_Cartesian_to_rfmbasis(Jac_dUrfm_dDCartUD, CartbetaU)\n", "dst_BU = rfm.basis_transform_vectorU_from_Cartesian_to_rfmbasis(Jac_dUrfm_dDCartUD, CartBU)\n", "\n", "# Step 3.d: Convert basis of all BSSN *tensors* from Cartesian to destination basis\n", "dst_gammabarDD = rfm.basis_transform_tensorDD_from_Cartesian_to_rfmbasis(Jac_dUCart_dDrfmUD, CartgammabarDD)\n", "dst_AbarDD = rfm.basis_transform_tensorDD_from_Cartesian_to_rfmbasis(Jac_dUCart_dDrfmUD, CartAbarDD)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 4: Compute rescaled BSSN quantities in destination basis \\[Back to [top](#toc)\\]\n", "$$\\label{rescaleindstbasis}$$\n", "\n", "Rescaling is documented in the [BSSN quantities tutorial notebook](Tutorial-BSSN_quantities.ipynb)." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:20:41.174297Z", "iopub.status.busy": "2021-03-07T17:20:41.164627Z", "iopub.status.idle": "2021-03-07T17:20:43.550788Z", "shell.execute_reply": "2021-03-07T17:20:43.550162Z" } }, "outputs": [], "source": [ "# Step 4: Rescale all BSSN quantities\n", "# BASED ON BSSN/BSSN_quantities.py:\n", "# Step 4.a: hDD and aDD:\n", "dst_hDD = ixp.zerorank2()\n", "dst_aDD = ixp.zerorank2()\n", "for i in range(3):\n", " for j in range(3):\n", " # gammabar_{ij} = h_{ij}*ReDD[i][j] + gammahat_{ij}\n", " # ==> h_{ij} = (gammabar_{ij} - gammahat_{ij}) / ReDD[i][j]\n", " dst_hDD[i][j] = (dst_gammabarDD[i][j] - rfm.ghatDD[i][j]) / rfm.ReDD[i][j]\n", " # Abar_{ij} = a_{ij}*ReDD[i][j]\n", " # ==> a_{ij} = Abar_{ij}/ReDD[i][j]\n", " dst_aDD[i][j] = dst_AbarDD[i][j] / rfm.ReDD[i][j]\n", "\n", "# Step 4.b: lambdaU, vetU, and betU:\n", "dst_lambdaU = ixp.zerorank1()\n", "dst_vetU = ixp.zerorank1()\n", "dst_betU = ixp.zerorank1()\n", "for i in range(3):\n", " # Lambdabar^i = \\lambda^i * ReU[i]\n", " # ==> \\lambda^i = Lambdabar^i / ReU[i]\n", " dst_lambdaU[i] = dst_LambdabarU[i] / rfm.ReU[i]\n", " dst_vetU[i] = dst_betaU[i] / rfm.ReU[i]\n", " dst_betU[i] = dst_BU[i] / rfm.ReU[i]\n", "\n", "# Step 4.c: All BSSN tensor/vector quantities are written in terms of\n", "# rescaled quantities and (xx0,xx1,xx2) on the DESTINATION grid.\n", "# To avoid confusion with (xx0,xx1,xx2) on the SOURCE grid,\n", "# we replace (xx0,xx1,xx2) with (dst_xx0,dst_xx1,dst_xx2) here:\n", "for i in range(3):\n", " for k in range(3):\n", " dst_lambdaU[i] = dst_lambdaU[i].subs(rfm.xx[k],dst_xx[k])\n", " dst_vetU[i] = dst_vetU[i].subs(rfm.xx[k],dst_xx[k])\n", " dst_betU[i] = dst_betU[i].subs(rfm.xx[k],dst_xx[k])\n", "for i in range(3):\n", " for j in range(3):\n", " for k in range(3):\n", " dst_hDD[i][j] = dst_hDD[i][j].subs(rfm.xx[k],dst_xx[k])\n", " dst_aDD[i][j] = dst_aDD[i][j].subs(rfm.xx[k],dst_xx[k])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 5: Code Validation Tests \\[Back to [top](#toc)\\] \n", "$$\\label{code_validation}$$\n", "\n", "\n", "\n", "## Step 5.a: Confirm identical output to `BSSN.BSSN_basis_transforms` NRPy+ module \\[Back to [top](#toc)\\] \n", "$$\\label{nrpy_module_validate}$$\n", "\n", "Here, as a code validation check, we verify agreement in the SymPy expressions for BrillLindquist initial data between\n", "1. this tutorial and \n", "2. the NRPy+ [BSSN.BSSN_basis_transforms](../edit/BSSN/BSSN_basis_transforms.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": { "execution": { "iopub.execute_input": "2021-03-07T17:20:43.563275Z", "iopub.status.busy": "2021-03-07T17:20:43.562638Z", "iopub.status.idle": "2021-03-07T17:20:47.458150Z", "shell.execute_reply": "2021-03-07T17:20:47.457586Z" }, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ALL TESTS PASSED!\n" ] } ], "source": [ "import BSSN.BSSN_basis_transforms as Bbt\n", "\n", "# Set up expressions from separate BSSN.BSSN_basis_transforms Python module\n", "Bbt.BSSN_basis_transform(src_basis,src_xx, dst_basis,dst_xx,\n", " src_hDD,src_aDD,src_lambdaU,src_vetU,src_betU)\n", "\n", "# Define functions for comparisons between this Jupyter notebook & associated Python module\n", "def comp_func(expr1,expr2,basename,prefixname2=\"Bq.\"):\n", " if str(expr1-expr2)!=\"0\":\n", " print(basename+\" - \"+prefixname2+basename+\" = \"+ str(expr1-expr2))\n", " return 1\n", " return 0\n", "\n", "def gfnm(basename,idx1,idx2=None,idx3=None):\n", " if idx2 is None:\n", " return basename+\"[\"+str(idx1)+\"]\"\n", " if idx3 is None:\n", " return basename+\"[\"+str(idx1)+\"][\"+str(idx2)+\"]\"\n", " return basename+\"[\"+str(idx1)+\"][\"+str(idx2)+\"][\"+str(idx3)+\"]\"\n", "\n", "expr_list = []\n", "exprcheck_list = []\n", "namecheck_list = []\n", "\n", "# Set up expression lists for comparisons between this Jupyter notebook & Python module\n", "for i in range(3):\n", " namecheck_list.extend([gfnm(\"dst_lambdaU\",i),gfnm(\"dst_vetU\",i),gfnm(\"dst_betU\",i)])\n", " exprcheck_list.extend([Bbt.dst_lambdaU[i],Bbt.dst_vetU[i],Bbt.dst_betU[i]])\n", " expr_list.extend([dst_lambdaU[i],dst_vetU[i],dst_betU[i]])\n", " for j in range(3):\n", " namecheck_list.extend([gfnm(\"dst_hDD\",i,j),gfnm(\"dst_aDD\",i,j)])\n", " exprcheck_list.extend([Bbt.dst_hDD[i][j],Bbt.dst_aDD[i][j]])\n", " expr_list.extend([dst_hDD[i][j],dst_aDD[i][j]])\n", "\n", "# Compare all SymPy expressions\n", "num_failures=0\n", "for i in range(len(expr_list)):\n", " num_failures += comp_func(expr_list[i],exprcheck_list[i],namecheck_list[i])\n", "\n", "if num_failures == 0:\n", " print(\"ALL TESTS PASSED!\")\n", "else:\n", " print(str(num_failures) + \" FAILURES.\")\n", " sys.exit(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "## Step 5.b: Confirm that if same basis chosen for input and output, at the same points `(xx0,xx1,xx2)`, the output is identical to the input \\[Back to [top](#toc)\\] \n", "$$\\label{confirm_same_basis_identity}$$\n", "\n", "Next we verify that if the same basis is chosen for input and output, at the same points `(xx0,xx1,xx2)`, the results are identical." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:20:47.533003Z", "iopub.status.busy": "2021-03-07T17:20:47.497060Z", "iopub.status.idle": "2021-03-07T17:20:55.973632Z", "shell.execute_reply": "2021-03-07T17:20:55.972974Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ALL TESTS PASSED!\n" ] } ], "source": [ "import sympy as sp # SymPy: The Python computer algebra package upon which NRPy+ depends\n", "Bbt.BSSN_basis_transform(\"Spherical\",src_xx, \"Spherical\",src_xx,\n", " src_hDD,src_aDD,src_lambdaU,src_vetU,src_betU)\n", "\n", "all_passed = True\n", "for i in range(3):\n", " if sp.simplify(Bbt.dst_lambdaU[i])-src_lambdaU[i] != 0:\n", " print(\"Error in lambdaU[\"+str(i)+\"]: \"+str(sp.simplify(Bbt.dst_lambdaU[i])-src_lambdaU[i])+\" != 0\")\n", " all_passed = False\n", " for j in range(3):\n", " if sp.simplify(Bbt.dst_hDD[i][j])-src_hDD[i][j] != 0:\n", " print(\"Error in hDD[\"+str(i)+\"][\"+str(j)+\"]: \"+sp.simplify(Bbt.dst_hDD[i][j])-src_hDD[i][j]+\" != 0\")\n", " all_passed = False\n", "if all_passed:\n", " print(\"ALL TESTS PASSED!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 6: 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 [Tutorial-BSSN-basis_transforms.pdf](Tutorial-BSSN-basis_transforms.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": 1, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:20:55.978694Z", "iopub.status.busy": "2021-03-07T17:20:55.977717Z", "iopub.status.idle": "2021-03-07T17:20:59.475388Z", "shell.execute_reply": "2021-03-07T17:20:59.475962Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created Tutorial-BSSN-basis_transforms.tex, and compiled LaTeX file to PDF\n", " file Tutorial-BSSN-basis_transforms.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-basis_transforms\")" ] } ], "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.11.1" } }, "nbformat": 4, "nbformat_minor": 4 }