{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "# FFE Breakdown `GiRaFFEfood` Initial Data for `GiRaFFE`\n", "\n", "## This module provides another initial data option for `GiRaFFE`, drawn from [Paschalidis and Shapiro](https://arxiv.org/abs/1310.3274).\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). The initial data has validated against the original `GiRaFFE`, as documented [here](Tutorial-Start_to_Finish_UnitTest-GiRaFFEfood_NRPy.ipynb).\n", "\n", "### NRPy+ Source Code for this module: [GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_FFE_Breakdown.py](../../edit/in_progress/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_FFE_Breakdown.py)\n", "\n", "## Introduction:\n", "\n", "### FFE Breakdown:\n", "\n", "This is a flat-spacetime test with initial data \n", "\\begin{align}\n", "A_x &= 0, \\\\ \n", "A_y &= \\left \\{ \\begin{array}{lll} x-0.2 & \\mbox{if} & x<0 \\\\\n", " \t\t\t\t -5.0x^2 + x -0.2 & \\mbox{if} & 0 < x < 0.2 \\\\\n", " -x & \\mbox{if} & x>0.2 \n", " \\end{array} \\right. \\\\ \n", "A_z &= y - A_y\n", "\\end{align}\n", "which generates the magnetic field in the wave frame,\n", "\\begin{align}\n", "\\mathbf{B}(0,x) = \\left \\{ \\begin{array}{lll} (1.0,1.0,1.0) & \\mbox{if} & x<0 \\\\\n", "\t\t\t\t \t (1.0,z(x),z(x)) & \\mbox{if} & 0 < x < 0.2 \\\\\n", " (1.0,-1.0,-1.0) & \\mbox{if} & x>0.2 \n", " \\end{array}, \\right.\n", "\\end{align}\n", "where $z(x) = -10.0x+1.0$.\n", "\n", "The electric field is then given by\n", "$$\\mathbf{E}(0,x) = (0.0,0.5,-0.5).$$\n", "\n", "See the [Tutorial-GiRaFFEfood_NRPy](Tutorial-GiRaFFEfood_NRPy.ipynb) tutorial notebook for more general detail on how this is used.\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): Import core NRPy+ modules and set NRPy+ parameters\n", "1. [Step 2](#set_a_i): Set the vector $A_i$\n", "1. [Step 3](#set_vi): Calculate $v^i$ from $B^i$ and $E_i$\n", "1. [Step 4](#code_validation): Code Validation against `GiRaFFEfood_NRPy.GiRaFFEfood_NRPy` 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: 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 and set the reference metric to Cartesian, set commonly used NRPy+ parameters, and set C parameters that will be set from outside the code eventually generated from these expressions. We will also set up a parameter to determine what initial data is set up, although it won't do much yet." ] }, { "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", "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 GiRaFFEfood_NRPy.GiRaFFEfood_NRPy_Common_Functions as gfcf # Some useful functions for GiRaFFE initial data.\n", "\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", "# Step 1a: Set commonly used parameters.\n", "thismodule = \"GiRaFFEfood_NRPy_1D\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### \n", "\n", "# Step 2: Set the vector $A_i$ \\[Back to [top](#toc)\\]\n", "$$\\label{set_a_i}$$\n", "\n", "The vector potential is given as\n", "\\begin{align}\n", "A_x &= 0, \\\\ \n", "A_y &= \\left \\{ \\begin{array}{lll} x-0.2 & \\mbox{if} & x<0 \\\\\n", " \t\t\t\t -5.0x^2 + x -0.2 & \\mbox{if} & 0 < x < 0.2 \\\\\n", " -x & \\mbox{if} & x>0.2 \n", " \\end{array} \\right. \\\\ \n", "A_z &= y - A_y\n", "\\end{align}\n", "\n", "However, to take full advantage of NRPy+'s automated function generation capabilities, we want to write this without the `if` statements, replacing them with calls to `fabs()`. To do so, we will use the NRPy+ module `Min_Max_and_Piecewise_Expressions`.\n", "\n", "Now, we can define the vector potential. We will rewrite $A_y$ to make use of the functions provided by `Min_Max_and_Piecewise_Expressions`. As shown below, we make sure that at each boundary, each $\\leq$ is paired with a $>$. (This choice is arbitrary, we could just as easily choose $<$ and $\\geq$.) This does not change the data since the function is continuous. However, it is necessary for the functions in `Min_Max_and_Piecewise_Expressions` to output the correct results.\n", "\n", "\\begin{align}\n", "A_x &= 0, \\\\ \n", "A_y &= \\left \\{ \\begin{array}{lll} x-0.2 & \\mbox{if} & x \\leq 0 \\\\\n", " \t\t\t\t -5.0x^2 + x -0.2 & \\mbox{if} & 0 < x \\leq 0.2 \\\\\n", " -x & \\mbox{if} & x>0.2 \n", " \\end{array} \\right. \\\\ \n", "A_z &= y - A_y\n", "\\end{align}" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import Min_Max_and_Piecewise_Expressions as noif\n", "boundL = sp.sympify(0)\n", "boundR = sp.Rational(1,5)\n", "\n", "def Ax_FB(x,y,z, **params):\n", " return sp.sympify(0)\n", "\n", "def Ay_FB(x,y,z, **params):\n", " Ayleft = x - sp.Rational(1,5)\n", " Aycenter = -sp.sympify(5)*x**2 + x - sp.Rational(1,5)\n", " Ayright = -x\n", "\n", " out = noif.coord_leq_bound(x,boundL)*Ayleft\\\n", " +noif.coord_greater_bound(x,boundL)*noif.coord_leq_bound(x,boundR)*Aycenter\\\n", " +noif.coord_greater_bound(x,boundR)*Ayright\n", " return out\n", "\n", "def Az_FB(x,y,z, **params):\n", " return y - Ay_FB(x,y,z, **params)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 3: Calculate $v^i$ from $B^i$ and $E_i$ \\[Back to [top](#toc)\\]\n", "$$\\label{set_vi}$$\n", "\n", "\n", "We will start by setting the auxiliary function $z(x) = -10.0x+1.0$." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def zfunc(x):\n", " # Naming it like this to avoid any possible confusion with the coordinate.\n", " return -sp.sympify(10)*x + sp.sympify(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we will set the magnetic field\n", "\\begin{align}\n", "\\mathbf{B}(0,x) = \\left \\{ \\begin{array}{lll} (1.0,1.0,1.0) & \\mbox{if} & x<0 \\\\\n", "\t\t\t\t \t (1.0,z(x),z(x)) & \\mbox{if} & 0 < x < 0.2 \\\\\n", " (1.0,-1.0,-1.0) & \\mbox{if} & x>0.2 \n", " \\end{array}, \\right.\n", "\\end{align}\n", "where $z(x) = -10.0x+1.0$ has been set above.\n", "\n", "Our expression for the electric field is\n", "$$\\mathbf{E}(0,x) = (0.0,0.5,-0.5).$$" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "#Step 3: Compute v^i from B^i and E_i\n", "def ValenciavU_func_FB(**params):\n", " x = rfm.xx_to_Cart[0]\n", "\n", " BU = ixp.zerorank1(DIM=3)\n", " BU[0] = sp.sympify(1)\n", " BU[1] = BU[2] = noif.coord_leq_bound(x,boundL) * sp.sympify(1)\\\n", " +noif.coord_greater_bound(x,boundL)*noif.coord_leq_bound(x,boundR)* zfunc(x)\\\n", " +noif.coord_greater_bound(x,boundR) * -sp.sympify(1)\n", "\n", " EU = ixp.zerorank1()\n", " EU[0] = sp.sympify(0)\n", " EU[1] = sp.Rational(1,2)\n", " EU[2] = -sp.Rational(1,2)\n", "\n", " # In flat space, ED and EU are identical, so we can still use this function.\n", " return gfcf.compute_ValenciavU_from_ED_and_BU(EU, BU)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 4: Code Validation against `GiRaFFEfood_NRPy/GiRaFFEfood_NRPy` 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 `GiRaFFE` Aligned Rotator initial data equations we intend to use between\n", "1. this tutorial and \n", "2. the NRPy+ [`GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests.py`](../edit/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests.py) module." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Consistency check between GiRaFFEfood_NRPy tutorial and NRPy+ module:\n", "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 GiRaFFEfood_NRPy.GiRaFFEfood_NRPy as gf\n", "\n", "A_fbD = gfcf.Axyz_func_Cartesian(Ax_FB,Ay_FB,Az_FB,stagger_enable = True,)\n", "Valenciav_fbD = ValenciavU_func_FB()\n", "gf.GiRaFFEfood_NRPy_generate_initial_data(ID_type = \"FFE_Breakdown\", stagger_enable = True)\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", "print(\"Consistency check between GiRaFFEfood_NRPy tutorial and NRPy+ module:\")\n", "\n", "for i in range(3):\n", " consistency_check(Valenciav_fbD[i],gf.ValenciavU[i],\"ValenciavU\"+str(i))\n", " consistency_check(A_fbD[i],gf.AD[i],\"AD\"+str(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-GiRaFFEfood_NRPy_1D_tests.pdf](Tutorial-GiRaFFEfood_NRPy_1D_tests.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-GiRaFFEfood_NRPy-FFE_Breakdown.tex, and compiled LaTeX\n", " file to PDF file Tutorial-GiRaFFEfood_NRPy-FFE_Breakdown.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-FFE_Breakdown\")" ] } ], "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 }