{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "# Start-to-Finish Example: Validating `GiRaFFEfood_NRPy` against original, trusted `GiRaFFEfood`: \n", "\n", "## Author: Patrick Nelson\n", "\n", "**Notebook Status:** Validated\n", "\n", "**Validation Notes:** This module validates all expressions used to set up initial data in \n", "* [Tutorial-GiRaFFEfood_NRPy_Aligned_Rotator](Tutorial-GiRaFFEfood_NRPy_Aligned_Rotator.ipynb)\n", "* [Tutorial-GiRaFFEfood_NRPy_1D_tests](Tutorial-GiRaFFEfood_NRPy_1D_tests.ipynb), \n", "* [Tutorial-GiRaFFEfood_NRPy_1D_tests-fast_wave](Tutorial-GiRaFFEfood_NRPy_1D_tests-fast_wave.ipynb), \n", "* [Tutorial-GiRaFFEfood_NRPy_1D_tests-degen_Alfven_wave](Tutorial-GiRaFFEfood_NRPy_1D_tests-degen_Alfven_wave.ipynb), \n", "* [Tutorial-GiRaFFEfood_NRPy_1D_tests-three_waves](Tutorial-GiRaFFEfood_NRPy_1D_tests-three_waves.ipynb), and\n", "* [Tutorial-GiRaFFEfood_NRPy_1D_tests-FFE_breakdown](Tutorial-GiRaFFEfood_NRPy_1D_tests-FFE_breakdown.ipynb), \n", "\n", "against the C-code implementation of these expressions found in the original (trusted) [`GiRaFFEfood` Einstein Toolkit thorn](link), and confirms roundoff-level agreement.\n", "\n", "### NRPy+ Source Code for this module: \n", "* [GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_Aligned_Rotator.py](../../edit/in_progress/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_Aligned_Rotator.py) [\\[**tutorial**\\]](Tutorial-GiRaFFEfood_NRPy_Aligned_Rotator.ipynb) Generates Aligned Rotator initial data\n", "* [GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests.py](../../edit/in_progress/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests.py) [\\[**tutorial**\\]](Tutorial-GiRaFFEfood_NRPy_1D_tests.ipynb) Generates Alfvén Wave initial data.\n", "* [GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests_fast_wave.py](../../edit/in_progress/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests_fast_wave.py) [\\[**tutorial**\\]](Tutorial-GiRaFFEfood_NRPy_1D_tests-fast_wave.ipynb) Generates Alfvén Wave initial data.\n", "* [GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests_degen_Alfven_wave.py](../../edit/in_progress/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests_degen_Alfven_wave.py) [\\[**tutorial**\\]](Tutorial-GiRaFFEfood_NRPy_1D_tests-degen_Alfven_wave.ipynb) Generates Degenerate Alfvén Wave initial data.\n", "* [GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests_three_waves.py](../../edit/in_progress/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests_three_waves.py) [\\[**tutorial**\\]](Tutorial-GiRaFFEfood_NRPy_1D_tests-three_waves.ipynb) Generates Three Waves initial data.\n", "* [GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests_FFE_breakdown.py](../../edit/in_progress/GiRaFFEfood_NRPy/GiRaFFEfood_NRPy_1D_tests_FFE_breakdown.py) [\\[**tutorial**\\]](Tutorial-GiRaFFEfood_NRPy_1D_tests-FFE_breakdown.ipynb) Generates FFE Breakdown initial data.\n", "\n", "## Introduction:\n", "\n", "This notebook validates the initial data routines that we will use for `GiRaFFE_NRPy`, collectively referred to as `GiRaFFEfood_NRPy`. To do so, we will generate the initial data with both our code and the original `GiRaFFEfood` code. Then, we will directly compare the velocities and show round-off level agreement between the two. \n", "\n", "When this notebook is run, the significant digits of agreement between the old `GiRaFFE` and new `GiRaFFE_NRPy` versions of the algorithm will be evaluated. If the agreement falls below a thresold, the point, quantity, and level of agreement are reported [here](#compile_run).\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](#setup): Set up core functions and parameters for unit testing the initial data algorithms\n", " 1. [Step 1.a](#initial_data) Generate the initial data C function\n", " 1. [Step 1.b](#download) Download original `GiRaFFE` files\n", " 1. [Step 1.c](#free_params) Output C codes needed for declaring and setting Cparameters; also set `free_parameters.h`\n", " 1. [Step 1.d](#interface) Create dummy files for the CCTK version of the code\n", "1. [Step 2](#mainc): `GiRaFFEfood_NRPy_unit_test.c`: The Main C Code\n", " 1. [Step 2.a](#compile_run): Compile and run the code to validate the output\n", "1. [Step 3](#drift_notes): Output this notebook to $\\LaTeX$-formatted PDF file\n", "1. [Step 4](#latex_pdf_output): Output this notebook to $\\LaTeX$-formatted PDF file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 1: Set up core functions and parameters for unit testing the initial data algorithms\" \\[Back to [top](#toc)\\]\n", "\n", "$$\\label{setup}$$\n", "\n", "We'll start by appending the relevant paths to `sys.path` so that we can access sympy modules in other places. Then, we'll import NRPy+ core functionality and set up a directory in which to carry out our test. We will also declare the gridfunctions that are needed for this portion of the code." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:45.645804Z", "iopub.status.busy": "2020-12-17T02:16:45.645262Z", "iopub.status.idle": "2020-12-17T02:16:45.646576Z", "shell.execute_reply": "2020-12-17T02:16:45.646936Z" } }, "outputs": [], "source": [ "# There are several initial data routines we need to test. We'll control which one we use with a string option\n", "initial_data = \"AlfvenWave\" # Valid options: \"AllTests\", \"AlignedRotator\", \"AlfvenWave\", \"FastWave\",\n", " # \"DegenAlfvenWave\", \"ThreeWaves\", \"FFE_Breakdown\"" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:45.652080Z", "iopub.status.busy": "2020-12-17T02:16:45.651624Z", "iopub.status.idle": "2020-12-17T02:16:45.848686Z", "shell.execute_reply": "2020-12-17T02:16:45.848441Z" } }, "outputs": [], "source": [ "import os, sys # Standard Python modules for multiplatform OS-level functions\n", "# First, we'll add the parent directory to the list of directories Python will check for modules.\n", "nrpy_dir_path = os.path.join(\"..\")\n", "if nrpy_dir_path not in sys.path:\n", " sys.path.append(nrpy_dir_path)\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", "from outputC import outCfunction, lhrh # NRPy+: Core C code output module\n", "import sympy as sp # SymPy: The Python computer algebra package upon which NRPy+ depends\n", "import finite_difference as fin # NRPy+: Finite difference C code generation module\n", "import NRPy_param_funcs as par # NRPy+: Parameter interface\n", "import grid as gri # NRPy+: Functions having to do with numerical grids\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 cmdline_helper as cmd # NRPy+: Multi-platform Python command-line interface\n", "\n", "out_dir = \"Validation/\"\n", "cmd.mkdir(out_dir)\n", "\n", "thismodule = \"Start_to_Finish_UnitTest-GiRaFFEfood_NRPy\"\n", "\n", "# Register the gridfunctions we need for this function\n", "AD = ixp.register_gridfunctions_for_single_rank1(\"EVOL\",\"AD\")\n", "ValenciavU = ixp.register_gridfunctions_for_single_rank1(\"AUXEVOL\",\"ValenciavU\")\n", "# gammaDD = ixp.register_gridfunctions_for_single_rank2(\"AUXEVOL\",\"gammaDD\",\"sym01\")\n", "betaU = ixp.register_gridfunctions_for_single_rank1(\"AUXEVOL\",\"betaU\")\n", "alpha = gri.register_gridfunctions(\"AUXEVOL\",\"alpha\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "## Step 1.a: Generate the initial data C function \\[Back to [top](#toc)\\]\n", "$$\\label{initial_data}$$\n", "\n", "First, we'll use NRPy+ to build the C function that will generate the initial data. There are several different cases here, one for each type of initial test data." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:46.629344Z", "iopub.status.busy": "2020-12-17T02:16:46.628795Z", "iopub.status.idle": "2020-12-17T02:16:48.744464Z", "shell.execute_reply": "2020-12-17T02:16:48.743977Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Output C function GiRaFFE_NRPy_initial_data() to file Validation/GiRaFFE_NRPy_initial_data.h\n" ] } ], "source": [ "if initial_data==\"AlfvenWave\":\n", " import GiRaFFEfood_NRPy.GiRaFFEfood_NRPy_1D_tests as gid\n", " gid.GiRaFFEfood_NRPy_1D_tests()\n", " desc = \"Generate Alfven wave 1D initial test data for GiRaFFEfood_NRPy.\"\n", "elif initial_data==\"FastWave\":\n", " import GiRaFFEfood_NRPy.GiRaFFEfood_NRPy_1D_tests_fast_wave as gid\n", " gid.GiRaFFEfood_NRPy_1D_tests_fast_wave()\n", " desc = \"Generate fast wave 1D initial test data for GiRaFFEfood_NRPy.\"\n", "elif initial_data==\"DegenAlfvenWave\":\n", " import GiRaFFEfood_NRPy.GiRaFFEfood_NRPy_1D_tests_degen_Alfven_wave as gid\n", " gid.GiRaFFEfood_NRPy_1D_tests_degen_Alfven_wave()\n", " desc = \"Generate degenerate Alfven wave 1D initial test data for GiRaFFEfood_NRPy.\"\n", "elif initial_data==\"ThreeWaves\":\n", " import GiRaFFEfood_NRPy.GiRaFFEfood_NRPy_1D_tests_three_waves as gid\n", " gid.GiRaFFEfood_NRPy_1D_tests_three_waves()\n", " desc = \"Generate three waves 1D initial test data for GiRaFFEfood_NRPy.\"\n", "elif initial_data==\"FFE_Breakdown\":\n", " import GiRaFFEfood_NRPy.GiRaFFEfood_NRPy_1D_tests_FFE_breakdown as gid\n", " gid.GiRaFFEfood_NRPy_1D_tests_FFE_breakdown()\n", " desc = \"Generate FFE breakdown 1D initial test data for GiRaFFEfood_NRPy.\"\n", "elif initial_data==\"AlignedRotator\":\n", " import GiRaFFEfood_NRPy.GiRaFFEfood_NRPy_Aligned_Rotator as gid\n", " gid.GiRaFFEfood_NRPy_Aligned_Rotator()\n", " desc = \"Generate aligned rotator initial test data for GiRaFFEfood_NRPy.\"\n", "elif initial_data==\"ExactWald\":\n", " import GiRaFFEfood_NRPy.GiRaFFEfood_NRPy_Exact_Wald as gid\n", " gid.GiRaFFEfood_NRPy_Exact_Wald(gammaDD,sks.M,sks.r0,stagger=True)\n", " desc = \"Generate exact Wald initial test data for GiRaFFEfood_NRPy.\"\n", "else:\n", " print(\"Unsupported Initial Data string \"+initial_data+\"! Supported ID: AllTests, AlfvenWave, FastWave, DegenAlfvenWave, ThreeWaves, FFE_Breakdown, AlignedRotator, or ExactWald\")\n", "\n", "name = \"GiRaFFE_NRPy_initial_data\"\n", "\n", "values_to_print = [\\\n", " lhrh(lhs=gri.gfaccess(\"out_gfs\",\"AD0\"),rhs=gid.AD[0]),\\\n", " lhrh(lhs=gri.gfaccess(\"out_gfs\",\"AD1\"),rhs=gid.AD[1]),\\\n", " lhrh(lhs=gri.gfaccess(\"out_gfs\",\"AD2\"),rhs=gid.AD[2]),\\\n", " lhrh(lhs=gri.gfaccess(\"auxevol_gfs\",\"ValenciavU0\"),rhs=gid.ValenciavU[0]),\\\n", " lhrh(lhs=gri.gfaccess(\"auxevol_gfs\",\"ValenciavU1\"),rhs=gid.ValenciavU[1]),\\\n", " lhrh(lhs=gri.gfaccess(\"auxevol_gfs\",\"ValenciavU2\"),rhs=gid.ValenciavU[2])\\\n", " ]\n", "\n", "outCfunction(\n", " outfile = os.path.join(out_dir,name+\".h\"), desc=desc, name=name,\n", " params =\"const paramstruct *params,REAL *xx[3],REAL *auxevol_gfs,REAL *out_gfs\",\n", " body = fin.FD_outputC(\"returnstring\",values_to_print,params=\"outCverbose=False\").replace(\"IDX4\",\"IDX4S\"),\n", " loopopts =\"AllPoints,Read_xxs\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "## Step 1.b: Download original `GiRaFFE` files \\[Back to [top](#toc)\\]\n", "\n", "$$\\label{download}$$\n", "\n", "Here, we download the relevant portion of the original `GiRaFFE` code from Bitbucket. " ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:48.749161Z", "iopub.status.busy": "2020-12-17T02:16:48.748605Z", "iopub.status.idle": "2020-12-17T02:16:49.948386Z", "shell.execute_reply": "2020-12-17T02:16:49.947793Z" } }, "outputs": [], "source": [ "# First download the original GiRaFFE source code\n", "import urllib\n", "\n", "original_file_url = [\n", " \"https://bitbucket.org/zach_etienne/wvuthorns/raw/231af720ccf3f1af50f7cce4a86b410fc8ea2e51/GiRaFFEfood/src/AlfvenWave.cc\",\n", " \"https://bitbucket.org/zach_etienne/wvuthorns/raw/231af720ccf3f1af50f7cce4a86b410fc8ea2e51/GiRaFFEfood/src/FastWave.cc\",\n", " \"https://bitbucket.org/zach_etienne/wvuthorns/raw/b826f6578b0c2b5a43ad9171e65a1b0af88d8b77/GiRaFFEfood/src/DegenAlfvenWave.cc\",\n", " \"https://bitbucket.org/zach_etienne/wvuthorns/raw/b826f6578b0c2b5a43ad9171e65a1b0af88d8b77/GiRaFFEfood/src/ThreeAlfvenWave.cc\",\n", " \"https://bitbucket.org/zach_etienne/wvuthorns/raw/b826f6578b0c2b5a43ad9171e65a1b0af88d8b77/GiRaFFEfood/src/FFEBreakdown.cc\",\n", " \"https://bitbucket.org/zach_etienne/wvuthorns/raw/231af720ccf3f1af50f7cce4a86b410fc8ea2e51/GiRaFFEfood/src/AlignedRotator.cc\",\n", " ]\n", "original_file_name = [\n", " \"AlfvenWave.cc\",\n", " \"FastWave.cc\",\n", " \"DegenAlfvenWave.cc\",\n", " \"ThreeAlfvenWave.cc\",\n", " \"FFEBreakdown.cc\",\n", " \"AlignedRotator.cc\",\n", " ]\n", "\n", "for i in range(len(original_file_url)):\n", " original_file_path = os.path.join(out_dir,original_file_name[i])\n", "\n", " # Then download the original GiRaFFE source code\n", " # We try it here in a couple of ways in an attempt to keep\n", " # the code more portable\n", " try:\n", " original_file_code = urllib.request.urlopen(original_file_url[i]).read().decode('utf-8')\n", " except:\n", " original_file_code = urllib.urlopen(original_file_url[i]).read().decode('utf-8')\n", "\n", " # Write down the file the original GiRaFFE source code\n", " with open(original_file_path,\"w\") as file:\n", " file.write(original_file_code)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "## Step 1.c: Output C codes needed for declaring and setting Cparameters; also set `free_parameters.h` \\[Back to [top](#toc)\\]\n", "\n", "$$\\label{free_params}$$\n", "\n", "Based on declared NRPy+ Cparameters, first we generate `declare_Cparameters_struct.h`, `set_Cparameters_default.h`, and `set_Cparameters[-SIMD].h`.\n", "\n", "Then we output `free_parameters.h`, which sets some basic grid parameters as well as the speed limit parameter we need for this function." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:49.953713Z", "iopub.status.busy": "2020-12-17T02:16:49.953168Z", "iopub.status.idle": "2020-12-17T02:16:49.956180Z", "shell.execute_reply": "2020-12-17T02:16:49.955683Z" } }, "outputs": [], "source": [ "# Step 3.d\n", "# Step 3.d.ii: Set free_parameters.h\n", "with open(os.path.join(out_dir,\"free_parameters.h\"),\"w\") as file:\n", " file.write(\"\"\"\n", "// Set free-parameter values.\n", "\n", "const int NGHOSTS = 3;\n", "\n", "// Set free-parameter values for the initial data.\n", "// Override parameter defaults with values based on command line arguments and NGHOSTS.\n", "const int Nx0x1x2 = 5;\n", "params.Nxx0 = Nx0x1x2;\n", "params.Nxx1 = Nx0x1x2;\n", "params.Nxx2 = Nx0x1x2;\n", "params.Nxx_plus_2NGHOSTS0 = params.Nxx0 + 2*NGHOSTS;\n", "params.Nxx_plus_2NGHOSTS1 = params.Nxx1 + 2*NGHOSTS;\n", "params.Nxx_plus_2NGHOSTS2 = params.Nxx2 + 2*NGHOSTS;\n", "// Step 0d: Set up space and time coordinates\n", "// Step 0d.i: Declare \\Delta x^i=dxx{0,1,2} and invdxx{0,1,2}, as well as xxmin[3] and xxmax[3]:\n", "const REAL xxmin[3] = {-1.0,-1.0,-1.0};\n", "const REAL xxmax[3] = { 1.0, 1.0, 1.0};\n", "\n", "params.dxx0 = (xxmax[0] - xxmin[0]) / ((REAL)params.Nxx0);\n", "params.dxx1 = (xxmax[1] - xxmin[1]) / ((REAL)params.Nxx1);\n", "params.dxx2 = (xxmax[2] - xxmin[2]) / ((REAL)params.Nxx2);\n", "params.invdx0 = 1.0 / params.dxx0;\n", "params.invdx1 = 1.0 / params.dxx1;\n", "params.invdx2 = 1.0 / params.dxx2;\n", "\\n\"\"\")\n", "\n", "# Generates declare_Cparameters_struct.h, set_Cparameters_default.h, and set_Cparameters[-SIMD].h\n", "par.generate_Cparameters_Ccodes(os.path.join(out_dir))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "## Step 1.d: Create dummy files for the CCTK version of the code \\[Back to [top](#toc)\\]\n", "\n", "$$\\label{interface}$$\n", "\n", "The original `GiRaFFE` code depends on some functionalities of the CCTK. Since we only care about this one small function, we can get around this by creating some nearly-empty, non-functional files that can be included to satisfy the pre-processor without changing functionality. We will later replace what little functionality we need with some basic global variables and macros." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:49.960776Z", "iopub.status.busy": "2020-12-17T02:16:49.960352Z", "iopub.status.idle": "2020-12-17T02:16:49.962693Z", "shell.execute_reply": "2020-12-17T02:16:49.962326Z" } }, "outputs": [], "source": [ "#incldue \"cctk.h\"\n", "#include \"cctk_Arguments.h\"\n", "#include \"cctk_Parameters.h\"\n", "#include \"Symmetry.h\"\n", "with open(os.path.join(out_dir,\"cctk.h\"),\"w\") as file:\n", " file.write(\"\"\"//\"\"\")\n", "\n", "with open(os.path.join(out_dir,\"cctk_Arguments.h\"),\"w\") as file:\n", " file.write(\"\"\"#define DECLARE_CCTK_ARGUMENTS //\n", "#define CCTK_ARGUMENTS void\n", "\"\"\")\n", "\n", "with open(os.path.join(out_dir,\"cctk_Parameters.h\"),\"w\") as file:\n", " file.write(\"\"\"#define DECLARE_CCTK_PARAMETERS //\n", "\"\"\")\n", "\n", "with open(os.path.join(out_dir,\"Symmetry.h\"),\"w\") as file:\n", " file.write(\"\"\"//\"\"\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 2: `GiRaFFEfood_NRPy_unit_test.c`: The Main C Code \\[Back to [top](#toc)\\]\n", "\n", "$$\\label{mainc}$$\n", "\n", "Now that we have our vector potential and analytic magnetic field to compare against, we will start writing our unit test. We'll also import common C functionality, define `REAL`, the number of ghost zones, and the faces, and set the standard macros for NRPy+ style memory access." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:49.966436Z", "iopub.status.busy": "2020-12-17T02:16:49.965950Z", "iopub.status.idle": "2020-12-17T02:16:49.968341Z", "shell.execute_reply": "2020-12-17T02:16:49.967907Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting Validation//GiRaFFEfood_NRPy_unit_test.C\n" ] } ], "source": [ "%%writefile $out_dir/GiRaFFEfood_NRPy_unit_test.C\n", "\n", "// These are common packages that we are likely to need.\n", "#include \"stdio.h\"\n", "#include \"stdlib.h\"\n", "#include \"math.h\"\n", "#include // Needed for strncmp, etc.\n", "#include \"stdint.h\" // Needed for Windows GCC 6.x compatibility\n", "#include // Needed to set a random seed.\n", "\n", "#define REAL double\n", "#include \"declare_Cparameters_struct.h\"\n", "\n", "// Standard NRPy+ memory access:\n", "#define IDX4S(g,i,j,k) \\\n", "( (i) + Nxx_plus_2NGHOSTS0 * ( (j) + Nxx_plus_2NGHOSTS1 * ( (k) + Nxx_plus_2NGHOSTS2 * (g) ) ) )\n", "\n", "// Standard formula to calculate significant digits of agreement:\n", "#define SDA(a,b) 1.0-log10(2.0*fabs(a-b)/(fabs(a)+fabs(b)))\n", "\n", "// Memory access definitions for NRPy+\n", "#define BU0GF 0\n", "#define BU1GF 1\n", "#define BU2GF 2\n", "#define VALENCIAVU0GF 3\n", "#define VALENCIAVU1GF 4\n", "#define VALENCIAVU2GF 5\n", "#define BETAU0GF 6\n", "#define BETAU1GF 7\n", "#define BETAU2GF 8\n", "#define ALPHAGF 9\n", "#define NUM_AUXEVOL_GFS 10\n", "\n", "#define AD0GF 0\n", "#define AD1GF 1\n", "#define AD2GF 2\n", "#define NUM_EVOL_GFS 3\n", "\n", "// Include the functions that we want to test:\n", "#include \"GiRaFFE_NRPy_initial_data.h\"\n", "\n", "// Define CCTK macros\n", "#define CCTK_REAL double\n", "#define CCTK_INT int\n", "struct cGH{};\n", "const cGH* cctkGH;\n", "\n", "// GiRaFFE parameters in ETK\n", "const CCTK_REAL min_radius_inside_of_which_conserv_to_prims_FFE_and_FFE_evolution_is_DISABLED = -1;\n", "const int current_sheet_null_v = 1;\n", "\n", "// More definitions to interface with ETK code:\n", "const int cctk_lsh[3] = {11,11,11};\n", "const int grid_size = cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2];\n", "CCTK_REAL Avec[3*grid_size];\n", "CCTK_REAL vel[3*grid_size];\n", "CCTK_REAL Ax[grid_size];\n", "CCTK_REAL Ay[grid_size];\n", "CCTK_REAL Az[grid_size];\n", "CCTK_REAL vx[grid_size];\n", "CCTK_REAL vy[grid_size];\n", "CCTK_REAL vz[grid_size];\n", "CCTK_REAL Bx[grid_size];\n", "CCTK_REAL By[grid_size];\n", "CCTK_REAL Bz[grid_size];\n", "CCTK_REAL x[grid_size];\n", "CCTK_REAL y[grid_size];\n", "CCTK_REAL z[grid_size];\n", "CCTK_REAL r[grid_size];\n", "CCTK_REAL *alp;\n", "CCTK_REAL *betax;\n", "CCTK_REAL *betay;\n", "CCTK_REAL *betaz;\n", "\n", "// We need to declare these to compile functions we won't call:\n", "int Compute_Exact_Every;\n", "int cctk_iteration;\n", "CCTK_REAL *delpsi6phi;\n", "CCTK_REAL *psi6phi;\n", "CCTK_REAL *delAx;\n", "CCTK_REAL *delAy;\n", "CCTK_REAL *delAz;\n", "CCTK_REAL *exactBx;\n", "CCTK_REAL *exactBy;\n", "CCTK_REAL *exactBz;\n", "CCTK_REAL *delBx;\n", "CCTK_REAL *delBy;\n", "CCTK_REAL *delBz;\n", "CCTK_REAL *exactVx;\n", "CCTK_REAL *exactVy;\n", "CCTK_REAL *exactVz;\n", "CCTK_REAL *delvx;\n", "CCTK_REAL *delvy;\n", "CCTK_REAL *delvz;\n", "CCTK_REAL cctk_time = 0.0;\n", "CCTK_REAL *exactBx_ThreeWaves;\n", "CCTK_REAL *exactBy_ThreeWaves;\n", "CCTK_REAL *exactBz_ThreeWaves;\n", "CCTK_REAL *delBx_ThreeWaves;\n", "CCTK_REAL *delBy_ThreeWaves;\n", "CCTK_REAL *delBz_ThreeWaves;\n", "CCTK_REAL *mhd_st_x;\n", "CCTK_REAL *mhd_st_y;\n", "CCTK_REAL *mhd_st_z;\n", "CCTK_REAL *Ex;\n", "CCTK_REAL *Ey;\n", "CCTK_REAL *Ez;\n", "CCTK_REAL *B2mE2;\n", "\n", "// Set constants to default for comparison\n", "CCTK_REAL wave_speed = -0.5;\n", "CCTK_REAL Omega_aligned_rotator = 1e3;\n", "CCTK_REAL R_NS_aligned_rotator = 1.0;\n", "CCTK_REAL B_p_aligned_rotator = 1e-5;\n", "CCTK_REAL Wald_B0 = 1.0;\n", "\n", "// Define dz in CCTK\n", "CCTK_REAL cactus_dxx[3];\n", "#define CCTK_DELTA_SPACE(i) cactus_dxx[i]\n", "\n", "// Dummy ETK function:\n", "#define CCTK_GFINDEX3D(cctkGH,i,j,k) (i) + cctk_lsh[0] * ( (j) + cctk_lsh[1] * (k) )\n", "#define CCTK_GFINDEX4D(cctkGH,i,j,k,g) \\\n", "( (i) + cctk_lsh[0] * ( (j) + cctk_lsh[1] * ( (k) + cctk_lsh[2] * (g) ) ) )\n", "#define CCTK_VInfo(...) //\n", "//#define CCTK_VWarn(...) //\n", "\n", "#include \"AlfvenWave.cc\"\n", "#include \"FastWave.cc\"\n", "#include \"AlignedRotator.cc\"\n", "#include \"DegenAlfvenWave.cc\"\n", "#include \"ThreeAlfvenWave.cc\"\n", "#include \"FFEBreakdown.cc\"\n", "\n", "int main(int argc, char** argv) {\n", " paramstruct params;\n", "#include \"set_Cparameters_default.h\"\n", "\n", " // Step 0c: Set free parameters, overwriting Cparameters defaults\n", " // by hand or with command-line input, as desired.\n", "#include \"free_parameters.h\"\n", "#include \"set_Cparameters-nopointer.h\"\n", "\n", " // Now that we've calculated dxx2, we can define a cactus equivalent\n", " cactus_dxx[0] = dxx0;\n", " cactus_dxx[1] = dxx1;\n", " cactus_dxx[2] = dxx2;\n", "\n", " // Step 0d.ii: Set up uniform coordinate grids\n", " REAL *xx[3];\n", " xx[0] = (REAL *)malloc(sizeof(REAL)*Nxx_plus_2NGHOSTS0);\n", " xx[1] = (REAL *)malloc(sizeof(REAL)*Nxx_plus_2NGHOSTS1);\n", " xx[2] = (REAL *)malloc(sizeof(REAL)*Nxx_plus_2NGHOSTS2);\n", " for(int j=0;j\n", "\n", "## Step 2.a: Compile and run the code to validate the output \\[Back to [top](#toc)\\]\n", "\n", "$$\\label{compile_run}$$\n", "\n", "Finally, we can compile and run the code we have written. Once run, this code will output the level of agreement between the two codes and some information to help interpret those numbers." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:49.977557Z", "iopub.status.busy": "2020-12-17T02:16:49.977031Z", "iopub.status.idle": "2020-12-17T02:16:51.081536Z", "shell.execute_reply": "2020-12-17T02:16:51.081049Z" }, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Now compiling, should take ~2 seconds...\n", "\n", "Finished in 1.2637443542480469 seconds.\n", "\n", "\n", "(EXEC): Executing `taskset -c 0,1,2,3 ./GiRaFFEfood_NRPy_unit_test 0`...\n", "(BENCH): Finished executing in 0.2098681926727295 seconds.\n" ] } ], "source": [ "import time\n", "\n", "print(\"Now compiling, should take ~2 seconds...\\n\")\n", "start = time.time()\n", "# cmd.C_compile(os.path.join(out_dir,\"GiRaFFEfood_NRPy_unit_test.C\"), os.path.join(out_dir,\"GiRaFFEfood_NRPy_unit_test\"))\n", "!g++ -Ofast -fopenmp -march=native -funroll-loops Validation/GiRaFFEfood_NRPy_unit_test.C -o Validation/GiRaFFEfood_NRPy_unit_test -lstdc++\n", "end = time.time()\n", "print(\"Finished in \"+str(end-start)+\" seconds.\\n\\n\")\n", "\n", "results_file = \"out_GiRaFFEfood_NRPy_test.txt\"\n", "\n", "# os.chdir(out_dir)\n", "os.chdir(out_dir)\n", "# cmd.Execute(os.path.join(\"GiRaFFEfood_NRPy_unit_test\"))\n", "if initial_data==\"AlfvenWave\":\n", " cmd.Execute(\"GiRaFFEfood_NRPy_unit_test\",\"0\",results_file)\n", "elif initial_data==\"AlignedRotator\":\n", " cmd.Execute(\"GiRaFFEfood_NRPy_unit_test\",\"1\",results_file)\n", "elif initial_data==\"FastWave\":\n", " cmd.Execute(\"GiRaFFEfood_NRPy_unit_test\",\"2\",results_file)\n", "elif initial_data==\"DegenAlfvenWave\":\n", " cmd.Execute(\"GiRaFFEfood_NRPy_unit_test\",\"3\",results_file)\n", "elif initial_data==\"ThreeWaves\":\n", " cmd.Execute(\"GiRaFFEfood_NRPy_unit_test\",\"4\",results_file)\n", "elif initial_data==\"FFE_Breakdown\":\n", " cmd.Execute(\"GiRaFFEfood_NRPy_unit_test\",\"5\",results_file)\n", "os.chdir(os.path.join(\"../\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we add some emergency brakes so that if the output from the test isn't good, we throw an error to stop the notebook dead in its tracks. This way, our automatic testing infrastructure can let us know if something goes wrong. We will also print the output from the test for convenience's sake." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:51.084533Z", "iopub.status.busy": "2020-12-17T02:16:51.084067Z", "iopub.status.idle": "2020-12-17T02:16:51.086330Z", "shell.execute_reply": "2020-12-17T02:16:51.085880Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "All quantities agree at all points!\n", "\n" ] } ], "source": [ "with open(os.path.join(out_dir,results_file),\"r\") as file:\n", " output = file.readline()\n", " print(output)\n", " if output!=\"All quantities agree at all points!\\n\": # If this isn't the first line of this file, something went wrong!\n", " sys.exit(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 4: 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-Start_to_Finish_UnitTest-GiRaFFEfood_NRPy.pdf](Tutorial-Start_to_Finish_UnitTest-GiRaFFEfood_NRPy.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": 10, "metadata": { "execution": { "iopub.execute_input": "2020-12-17T02:16:51.088630Z", "iopub.status.busy": "2020-12-17T02:16:51.088183Z", "iopub.status.idle": "2020-12-17T02:16:53.333184Z", "shell.execute_reply": "2020-12-17T02:16:53.333700Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[NbConvertApp] WARNING | pattern 'Tutorial-Start_to_Finish_UnitTest-GiRaFFEfood_NRPy.ipynb' matched no files\n", "Created Tutorial-Start_to_Finish_UnitTest-GiRaFFEfood_NRPy.tex, and\n", " compiled LaTeX file to PDF file Tutorial-Start_to_Finish_UnitTest-\n", " GiRaFFEfood_NRPy.pdf\n" ] } ], "source": [ "import cmdline_helper as cmd # NRPy+: Multi-platform Python command-line interface\n", "cmd.output_Jupyter_notebook_to_LaTeXed_PDF(\"Tutorial-Start_to_Finish_UnitTest-GiRaFFEfood_NRPy\")" ] } ], "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.5" } }, "nbformat": 4, "nbformat_minor": 2 }