{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "# Split Monopole `GiRaFFEfood` Initial Data for `GiRaFFE`\n", "\n", "## Author: Patrick Nelson\n", "\n", "## This notebook demonstrates the generation of Split Monopole initial data, given by [Etienne *et al.*](https://arxiv.org/pdf/1704.00599.pdf), providing yet another initial data option for `GiRaFFE`.\n", "\n", "### NRPy+ Source Code for this module: [GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_Split_Monopole.py](../../edit/in_progress/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_Split_Monopole.py)\n", "\n", "**Notebook Status:** In-Progress \n", "\n", "**Validation Notes:** This tutorial notebook has been confirmed to be self-consistent with its corresponding NRPy+ module, as documented [below](#code_validation1). The initial data has validated against the original `GiRaFFE`, as documented [here](Tutorial-Start_to_Finish_UnitTest-GiRaFFEfood_NRPy.ipynb).\n", "\n", "## Introduction: \n", "We need to \"feed\" our giraffe with initial data to evolve. There are several different choices of initial data we can use here; here, we will only be implementing the \"Split Monopole\" initial data, given by Table 3 in [the original paper](https://arxiv.org/pdf/1704.00599.pdf). This solution is based on the Blandford-Znajek force-free monopole; it is an approximation for the case of small spin with the solution inverted in the lower hemisphere. The vector potential is\n", "\\begin{align}\n", "A_r &= -\\frac{aC}{8}\\cos\\theta \\left( 1 + \\frac{4M}{r} \\right), \\\\\n", "A_\\theta &= 0, \\\\\n", "A_\\phi &= M^2 C [1-\\cos \\theta + a^2 f(r) \\cos \\theta \\sin^2 \\theta],\n", "\\end{align}\n", "and the electric field is\n", "\\begin{align}\n", "E_r &= -\\frac{C a^3}{8\\alpha M^3} f'(r) \\cos \\theta \\sin^2 \\theta \\\\\n", "E_\\theta &= -\\frac{Ca}{8\\alpha}[\\sin \\theta + a^2 f(r) \\sin \\theta (2 \\cos^2 \\theta-\\sin^2 \\theta) ] - \\beta^r \\sqrt{\\gamma} \\frac{a C}{8 r^2}\\left( 1+\\frac{4M}{r}\\right) \\\\\n", "E_\\phi &= \\frac{\\beta^r}{\\alpha M} Ca^2 f'(r) \\cos \\theta \\sin^2 \\theta,\n", "\\end{align}\n", "where\n", "\\begin{align}\n", "f(r) =& \\ \\frac{r^2(2r-3M)}{8M^3} L \\left(\\frac{2M}{r}\\right) \\\\\n", "&+ \\frac{M^2+3Mr-6r^2}{12M^2} \\ln \\frac{r}{2M} \\\\\n", "&+ \\frac{11}{72} + \\frac{M}{3r} + \\frac{r}{2M} - \\frac{r^2}{M^2}, \\\\\n", "L(x) =& \\ {\\rm Li}_2(x) + \\frac{1}{2} \\ln x \\ln (1-x).\n", "\\end{align}\n", "The function ${\\rm Li}_2(x)$ is known as the dilogarithm function, defined as \n", "$$ {\\rm Li}_2(x) = -\\int_{0}^{1} \\frac{\\ln(1-tx)}{t} dt = \\sum_{k=1}^{\\infty} \\frac{x^k}{k^2}. $$\n", "Now, to use this initial data scheme, we need to transform the above into the quantities actually tracked by `GiRaFFE` and HydroBase: $A_i$, $B^i$, $\\tilde{S}_i$, $v^i$, and $\\Phi$. Of these quantities, `GiRaFFEfood` will only set $A_i$, $v^i$, and $\\Phi=0$, then call a separate function to calculate $\\tilde{S}_i$; `GiRaFFE` itself will call a function to set $B^i$ before the time-evolution begins. This can be done with eqs. 16 and 18, here given in that same order:\n", "\\begin{align}\n", "v_{(n)}^i &= \\frac{\\epsilon^{ijk} E_j B_k}{B^2} \\\\\n", "B^i &= \\frac{[ijk]}{\\sqrt{\\gamma}} \\partial_j A_k \\\\\n", "\\end{align}\n", "In the simulations, $B^i$ will be calculated numerically from $A_i$; however, it will be useful to analytically calculate $B^i$ to use calculating the initial $v^i$." ] }, { "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): Import core NRPy+ modules and set NRPy+ parameters\n", "1. [Step 2](#aux_func): Write helpful auxiliary functions\n", "1. [Step 3](#set_a_i): Set the vector $A_i$\n", "1. [Step 4](#set_vi): Calculate $v^i$ from $B_i$ and $E_i$\n", "1. [Step 5](#code_validation): Code Validation against `GiRaFFEfood_NRPy.GiRaFFEfood_NRPy` NRPy+ Module\n", "1. [Step 6](#latex_pdf_output): Output this notebook to $\\LaTeX$-formatted PDF file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 1: Import core NRPy+ modules and set NRPy+ parameters \\[Back to [top](#toc)\\]\n", "$$\\label{initializenrpy}$$\n", "\n", "Here, we will import the NRPy+ core modules after adding NRPy+ to the directory path." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Step 0: Add NRPy's directory to the path\n", "# https://stackoverflow.com/questions/16780014/import-file-from-parent-directory\n", "import os,sys\n", "nrpy_dir_path = os.path.join(\"..\")\n", "if nrpy_dir_path not in sys.path:\n", " sys.path.append(nrpy_dir_path)\n", "\n", "# Step 0.a: Import the NRPy+ core modules and set the reference metric to Cartesian\n", "from outputC import nrpyAbs\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 sympy as sp # SymPy: The Python computer algebra package upon which NRPy+ depends\n", "import GiRaFFEfood_NRPy.GiRaFFEfood_NRPy_Common_Functions as gfcf # Some useful functions for GiRaFFE initial data.\n", "import reference_metric as rfm # NRPy+: Reference metric support\n", "import Min_Max_and_Piecewise_Expressions as noif\n", "par.set_parval_from_str(\"reference_metric::CoordSystem\",\"Cartesian\")\n", "rfm.reference_metric()\n", "# Step 1a: Set commonly used parameters.\n", "thismodule = \"GiRaFFEfood_NRPy_Split_Monopole\"\n", "\n", "# The solution depends on a constant C\n", "C_SM = par.Cparameters(\"REAL\",thismodule,[\"C_SM\"], 1.0)\n", "import GiRaFFEfood_NRPy.GiRaFFEfood_NRPy as gf # Import this now to set parameters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 2: Write helpful auxiliary functions \\[Back to [top](#toc)\\]\n", "$$\\label{aux_func}$$\n", "\n", "We begin by coding the function $f(r)$ with the inputs $r$ and mass $M$. We avoid calling the function simply `f` out of an abundance of caution, as we do not want to risk overwriting an identically named function elsewhere.\n", "\\begin{align}\n", "f(r) =& \\ \\frac{r^2(2r-3M)}{8M^3} L \\left(\\frac{2M}{r}\\right) \\\\\n", "&+ \\frac{M^2+3Mr-6r^2}{12M^2} \\ln \\frac{r}{2M} \\\\\n", "&+ \\frac{11}{72} + \\frac{M}{3r} + \\frac{r}{2M} - \\frac{r^2}{2M^2}, \\\\\n", "\\end{align}\n", "where $L(x) = {\\rm Li}_2 (x) + \\frac{1}{2} \\ln x \\ln (1-x)$ and ${\\rm Li}_2 (x)$ is known as the dilogarithm function. We will use the C library `gsl` to handle this special function. In order to do so, we must tell NRPy+ that `nrpyDilog` will be our code word that means \"use the `gsl` dilogarithm function, `gsl_sf_dilog`\". This is done by simply creating a new sympy function using `Function()` and then adding the name-value pair to the dictionary `custom_functions_for_SymPy_ccode`." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "nrpyDilog = sp.Function('nrpyDilog')\n", "from outputC import custom_functions_for_SymPy_ccode\n", "custom_functions_for_SymPy_ccode[\"nrpyDilog\"] = \"gsl_sf_dilog\"\n", "\n", "def f_of_r(r,M):\n", " if par.parval_from_str(\"drop_fr\"):\n", " return sp.sympify(0)\n", " x = sp.sympify(2)*M/r\n", " L = sp.sympify(0) + \\\n", " noif.coord_greater_bound(x,sp.sympify(0))*noif.coord_less_bound(x,sp.sympify(1))*nrpyDilog(x)\\\n", " +sp.Rational(1,2)*sp.log(noif.coord_greater_bound(x,sp.sympify(0))*x + noif.coord_leq_bound(x,sp.sympify(1)))\\\n", " *sp.log(noif.coord_less_bound(x,sp.sympify(1))*(sp.sympify(1)-x) + noif.coord_geq_bound(x,sp.sympify(1)))\n", " f = r*r*(sp.sympify(2)*r-sp.sympify(3)*M)*sp.Rational(1,8)/(M**3)*L\\\n", " +(M*M+sp.sympify(3)*M*r-sp.sympify(6)*r*r)*sp.Rational(1,12)/(M*M)*sp.log(r*sp.Rational(1,2)/M)\\\n", " +sp.Rational(11,72) + M*sp.Rational(1,3)/r + r*sp.Rational(1,2)/M - r*r*sp.Rational(1,2)/(M*M)\n", " return f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will also need the derivative of $f(r)$:\n", "\\begin{align}\n", "f'(r) =& \\ \\frac{2r(2r-3M)+2r^2}{8M^3} L \\left(\\frac{2M}{r}\\right) + \\frac{r^2(2r-3M)}{8M^3} L' \\left(\\frac{2M}{r}\\right) \\left( -\\frac{2M}{r^2} \\right) \\\\\n", "&+ \\frac{3M-12r}{12M^2} \\ln \\frac{r}{2M} + \\frac{M^2+3Mr-6r^2}{12M^2} \\frac{2M}{r} \\frac{1}{2M} \\\\\n", "&- \\frac{M}{3r^2} + \\frac{1}{2M} - \\frac{2r}{M^2}. \\\\\n", "\\end{align}\n", "\n", "Because $$\\frac{\\partial {\\rm Li}_2 (x)}{\\partial x} = \\frac{{\\rm Li}_1 (x)}{x} = \\frac{-\\ln (1-x)}{x},$$\n", "we know that \n", "\\begin{align}\n", "L'(x) &= \\frac{-\\ln (1-x)}{x} + \\frac{\\ln (1-x)}{2x} - \\frac{\\ln (x)}{2-2x} \\\\\n", " &= -\\frac{1}{2} \\left( \\frac{\\ln (1-x)}{x} + \\frac{\\ln(x)}{1-x} \\right). \n", "\\end{align}\n", "We simplify this some.\n", "\\begin{align}\n", "f'(r) =& \\ \\frac{3r^2-3Mr}{4M^3} L \\left(\\frac{2M}{r}\\right) - \\frac{2r-3M}{4M^2} L' \\left(\\frac{2M}{r}\\right)\\\\\n", "&+ \\frac{3M-12r}{12M^2} \\ln \\frac{r}{2M} + \\frac{M^2+3Mr-6r^2}{12rM^2} \\\\\n", "&- \\frac{M}{3r^2} + \\frac{1}{2M} - \\frac{r}{M^2}. \\\\\n", "\\end{align}\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def fp_of_r(r,M):\n", " if par.parval_from_str(\"drop_fr\"):\n", " return sp.sympify(0)\n", " x = sp.sympify(2)*M/r\n", " L = sp.sympify(0) + \\\n", " noif.coord_greater_bound(x,sp.sympify(0))*noif.coord_less_bound(x,sp.sympify(1))*nrpyDilog(x)\\\n", " +sp.Rational(1,2)*sp.log(noif.coord_greater_bound(x,sp.sympify(0))*x + noif.coord_leq_bound(x,sp.sympify(1)))\\\n", " *sp.log(noif.coord_less_bound(x,sp.sympify(1))*(sp.sympify(1)-x) + noif.coord_geq_bound(x,sp.sympify(1)))\n", " Lp = sp.sympify(0) + noif.coord_greater_bound(x,sp.sympify(0))*noif.coord_less_bound(x,sp.sympify(1)) * -sp.Rational(1,2) *\\\n", " (sp.log(noif.coord_less_bound(x,sp.sympify(1))*(sp.sympify(1)-x) + noif.coord_geq_bound(x,sp.sympify(1)))/(x+sp.sympify(1e-100))\\\n", " +sp.log(noif.coord_greater_bound(x,sp.sympify(0))*x + noif.coord_leq_bound(x,sp.sympify(1)))/(sp.sympify(1)-x+sp.sympify(1e-100)))\n", " fp = sp.sympify(3)*r*(r-M)*sp.Rational(1,4)/(M**3)*L + (sp.sympify(2)*r-sp.sympify(3)*M)*sp.Rational(1,4)/(M*M)*Lp\\\n", " +(sp.sympify(3)*M-12*r)*sp.Rational(1,12)/(M*M)*sp.log(r*sp.Rational(1,2)/M) + (M*M+sp.sympify(3)*M*r-sp.sympify(6)*r*r)*sp.Rational(1,12)/(r*M*M)\\\n", " -M*sp.Rational(1,3)/(r*r) + sp.Rational(1,2)/M - r/(M*M)\n", " return fp\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 3: Set the vector $A_i$ \\[Back to [top](#toc)\\]\n", "$$\\label{set_a_i}$$\n", "\n", "Now, we will code the components of the vector potential $A_i$ in spherical coordinates and a spherical basis. The outputs from these functions can then be easily converted to other coordinate systems by giving the spherical coordinates as inputs in terms of the desired coordinates (e.g., if we want to use Cartesian coordinates, we pass $r = \\sqrt{x^2+y^2+z^2}$ and so on). They can also by transformed into any other basis using the appropriate Jacobian matrix. \n", "\n", "We will code each component as its own function to more easily apply the appropriate staggering.\n", "\\begin{align}\n", "A_r &= -\\frac{aC}{8} \\left| \\cos \\theta \\right| \\left( 1 + \\frac{4M}{r} \\right) \n", "\\sqrt{1 + \\frac{2M}{r}}, \\\\\n", "\\end{align}" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def Ar_SM(r,theta,phi, **params):\n", " M = params[\"M\"]\n", " a = params[\"a\"]\n", " # A_r = -aC/8 * cos \\theta ( 1 + 4M/r ) \\sqrt{1 + 2M/r}\n", " return -a*C_SM*sp.Rational(1,8)*nrpyAbs(sp.cos(theta))*(sp.sympify(1)+sp.sympify(4)*M/r)*sp.sqrt(sp.sympify(1)+sp.sympify(2)*M/r)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\\begin{align}\n", "A_\\theta &= 0, \\\\\n", "\\end{align}" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def Ath_SM(r,theta,phi, **params):\n", " # A_\\theta = 0\n", " return sp.sympify(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\\begin{align}\n", "A_\\phi &= M^2 C [1- \\left| \\cos \\theta \\right| + a^2 f(r) \\cos \\theta \\sin^2 \\theta]\n", "\\end{align}" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def Aph_SM(r,theta,phi, **params):\n", " M = params[\"M\"]\n", " a = params[\"a\"]\n", " # A_\\phi = M^2 C [1-\\cos \\theta + a^2 f(r) cos \\theta sin^2 \\theta]\n", " return M*M*C_SM*(sp.sympify(1)-nrpyAbs(sp.cos(theta))+a*a*f_of_r(r,M)*sp.cos(theta)*sp.sin(theta)**2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 4: Calculate $v^i$ from $B_i$ and $E_i$ \\[Back to [top](#toc)\\]\n", "$$\\label{set_vi}$$\n", "\n", "\n", "Next, we will code up the Valencia velocity, which will require us to first code the electric and magnetic fields. The magnetic field is simply $$B^i = \\frac{[ijk]}{\\sqrt{\\gamma}} \\partial_j A_k,$$ which gives\n", "\\begin{align}\n", "B^r &= \\frac{C \\alpha M^2}{r^2} + \\frac{C \\alpha a^2 M^2}{2r^4} \\left[ -2\\cos \\theta + \\left(\\frac{r}{M}\\right)^2 (1+3 \\cos 2\\theta) f(r) \\right], \\\\ \n", "B^\\theta &= - \\frac{C \\alpha a^2}{r^2} \\sin \\theta \\cos \\theta f'(r), \\\\ \n", "B^\\phi &= -\\frac{C \\alpha a M}{8r^2} \\left( 1 + \\frac{4M}{r}\\right) .\n", "\\end{align}\n", "\n", "The electric field is\n", "\\begin{align}\n", "E_r &= -\\frac{C a^3}{8\\alpha M^3} f'(r) \\cos \\theta \\sin^2 \\theta \\\\\n", "E_\\theta &= -\\frac{Ca}{8\\alpha}[\\sin \\theta + a^2 f(r) \\sin \\theta (2 \\cos^2 \\theta-\\sin^2 \\theta) ] - \\beta^r \\sqrt{\\gamma} \\frac{a C}{8 r^2}\\left( 1+\\frac{4M}{r}\\right) \\\\\n", "E_\\phi &= \\frac{\\beta^r}{\\alpha M} Ca^2 f'(r) \\cos \\theta \\sin^2 \\theta,\n", "\\end{align}\n", "\n", "We can then calculate the the velocity as $$v_{(n)}^i = \\frac{\\epsilon^{ijk} E_j B_k}{B^2}.$$" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def ValenciavU_func_SM(**params):\n", " M = params[\"M\"]\n", " a = params[\"a\"]\n", " alpha = params[\"alpha\"]\n", " betaU = params[\"betaU\"] # Note that this must use a spherical basis!\n", " gammaDD = params[\"gammaDD\"] # Note that this must use a Cartesian basis!\n", " sqrtgammaDET = params[\"sqrtgammaDET\"] # This must be spherical\n", " KerrSchild_radial_shift = params[\"KerrSchild_radial_shift\"]\n", " r = rfm.xxSph[0] + KerrSchild_radial_shift # We are setting the data up in Shifted Kerr-Schild coordinates\n", " theta = rfm.xxSph[1]\n", " phi = rfm.xxSph[2]\n", " z = rfm.xx_to_Cart[2]\n", "\n", " split_C_SM = noif.coord_geq_bound(z,sp.sympify(0))*C_SM - noif.coord_less_bound(z,sp.sympify(0))*C_SM\n", "\n", " BsphU = ixp.zerorank1()\n", " BsphU[0] = split_C_SM*alpha*M*M/(r*r) + \\\n", " split_C_SM*alpha*a*a*M*M*sp.Rational(1,2)/(r**4)*(-sp.sympify(2)*sp.cos(theta) + (r/M)**2*(sp.sympify(1)+sp.sympify(3)*sp.cos(sp.sympify(2)*theta))*f_of_r(r,M))\n", " BsphU[1] = -split_C_SM*alpha*a*a/(r*r) * sp.sin(theta)*sp.cos(theta)*fp_of_r(r,M)\n", " BsphU[2] = -split_C_SM*alpha*a*M*sp.Rational(1,8)/(r*r)*(sp.sympify(1)+sp.sympify(4)*M/r)\n", "\n", " EsphD = ixp.zerorank1()\n", " EsphD[0] = -split_C_SM*a**3/(sp.sympify(8)*alpha*M**3)*fp_of_r(r,M)*sp.cos(theta)*sp.sin(theta)**2\n", " EsphD[1] = -split_C_SM*a*sp.Rational(1,8)/alpha*(sp.sin(theta) + a*a*f_of_r(r,M)*sp.sin(theta)*(sp.sympify(2)*sp.cos(theta)**2-sp.sin(theta)**2)) - \\\n", " betaU[0]*sqrtgammaDET*a*split_C_SM*sp.Rational(1,8)/(r*r)*(sp.sympify(1)+sp.sympify(4)*M/r)\n", " EsphD[2] = betaU[0]/(alpha*M)*split_C_SM*a*a*fp_of_r(r,M)*sp.cos(theta)*sp.sin(theta)**2\n", "\n", " ED = rfm.basis_transform_vectorD_from_rfmbasis_to_Cartesian(gfcf.Jac_dUrfm_dDCartUD, EsphD)\n", " BU = rfm.basis_transform_vectorU_from_rfmbasis_to_Cartesian(gfcf.Jac_dUCart_dDrfmUD, BsphU)\n", "\n", " return gfcf.compute_ValenciavU_from_ED_and_BU(ED, BU, gammaDD)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 5: Code Validation against `GiRaFFEfood_NRPy.GiRaFFEfood_NRPy` NRPy+ module \\[Back to [top](#toc)\\]\n", "$$\\label{code_validation\n", "}$$\n", "\n", "Here, as a code validation check, we verify agreement in the SymPy expressions for the `GiRaFFE` Exact Wald initial data equations we intend to use between\n", "1. this tutorial and \n", "2. the NRPy+ [GiRaFFEfood_NRPy.GiRaFFEfood_NRPy-Split_Monopole](../edit/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_Split_Monopole.py) module." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ValenciavU0 is in agreement!\n", "AD0 is in agreement!\n", "ValenciavU1 is in agreement!\n", "AD1 is in agreement!\n", "ValenciavU2 is in agreement!\n", "AD2 is in agreement!\n" ] } ], "source": [ "import BSSN.ShiftedKerrSchild as sks\n", "sks.ShiftedKerrSchild(True)\n", "import reference_metric as rfm # NRPy+: Reference metric support\n", "par.set_parval_from_str(\"reference_metric::CoordSystem\",\"Cartesian\")\n", "rfm.reference_metric()\n", "\n", "gammaSphDD = ixp.zerorank2()\n", "for i in range(3):\n", " for j in range(3):\n", " gammaSphDD[i][j] += sks.gammaSphDD[i][j].subs(sks.r,rfm.xxSph[0]).subs(sks.th,rfm.xxSph[1])\n", "\n", "gammaDD = rfm.basis_transform_tensorDD_from_rfmbasis_to_Cartesian(gfcf.Jac_dUrfm_dDCartUD,gammaSphDD)\n", "unused_gammaUU,gammaDET = ixp.symm_matrix_inverter3x3(gammaDD)\n", "sqrtgammaDET = sp.sqrt(gammaDET)\n", "\n", "betaU = ixp.zerorank1()\n", "for i in range(3):\n", " betaU[i] += sks.betaSphU[i].subs(sks.r,rfm.xxSph[0]).subs(sks.th,rfm.xxSph[1])\n", "alpha = sks.alphaSph.subs(sks.r,rfm.xxSph[0]).subs(sks.th,rfm.xxSph[1])\n", "\n", "A_smD = gfcf.Axyz_func_spherical(Ar_SM,Ath_SM,Aph_SM,stagger_enable = True,M=sks.M,a=sks.a,KerrSchild_radial_shift=sks.r0)\n", "Valenciav_smD = ValenciavU_func_SM(M=sks.M,a=sks.a,KerrSchild_radial_shift=sks.r0,alpha=alpha,betaU=betaU,gammaDD=gammaDD,sqrtgammaDET=sqrtgammaDET)\n", "gf.GiRaFFEfood_NRPy_generate_initial_data(ID_type = \"SplitMonopole\", stagger_enable = True,M=sks.M,a=sks.a,KerrSchild_radial_shift=sks.r0,alpha=alpha,betaU=betaU,gammaDD=gammaDD,sqrtgammaDET=sqrtgammaDET)\n", "\n", "def consistency_check(quantity1,quantity2,string):\n", " if quantity1-quantity2==0:\n", " print(string+\" is in agreement!\")\n", " else:\n", " print(string+\" does not agree!\")\n", " sys.exit(1)\n", "\n", "for i in range(3):\n", " consistency_check(Valenciav_smD[i],gf.ValenciavU[i],\"ValenciavU\"+str(i))\n", " consistency_check(A_smD[i],gf.AD[i],\"AD\"+str(i))" ] }, { "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\n", "[Tutorial-GiRaFFEfood_NRPy-Split_Monopole.pdf](Tutorial-GiRaFFEfood_NRPy-Split_Monopole.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": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created Tutorial-GiRaFFEfood_NRPy-Split_Monopole.tex, and compiled LaTeX\n", " file to PDF file Tutorial-GiRaFFEfood_NRPy-Split_Monopole.pdf\n" ] } ], "source": [ "import cmdline_helper as cmd # NRPy+: Multi-platform Python command-line interface\n", "cmd.output_Jupyter_notebook_to_LaTeXed_PDF(\"Tutorial-GiRaFFEfood_NRPy-Split_Monopole\")" ] } ], "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 }