{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "# Finite-Difference Playground: Using NRPy+-Generated C Codes in a Larger Project\n", "\n", "## Author: Zach Etienne\n", "### Formatting improvements courtesy Brandon Clark\n", "\n", "## Introduction: \n", "To illustrate how NRPy+-based codes can be used, we write a C code that makes use of the NRPy+-generated C code from the [previous module](Tutorial-Finite_Difference_Derivatives.ipynb). This is a rather silly example, as the C code generated by NRPy+ could be easily generated by hand. However, as we will see in later modules, NRPy+'s true strengths lie in its automatic handling of far more complex and generic expressions, in higher dimensions. For the time being, bear with NRPy+; its true powers will become clear soon!" ] }, { "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](#outputc): Output the C file `finite_diff_tutorial-second_deriv.h`\n", "1. [Step 2](#fdplayground): Finite-Difference Playground: A Complete C Code for Analyzing Finite-Difference Expressions Output by NRPy+\n", "1. [Step 3](#exercise): Exercises\n", "1. [Step 4](#latex_pdf_output): Output this notebook to $\\LaTeX$-formatted PDF file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 1: Output the C file `finite_diff_tutorial-second_deriv.h` \\[Back to [top](#toc)\\]\n", "$$\\label{outputc}$$\n", "\n", "We start with the NRPy+ code from the [previous module](Tutorial-Finite_Difference_Derivatives.ipynb), and output it to the C file `finite_diff_tutorial-second_deriv.h`." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:32:17.521891Z", "iopub.status.busy": "2021-03-07T17:32:17.520599Z", "iopub.status.idle": "2021-03-07T17:32:17.976712Z", "shell.execute_reply": "2021-03-07T17:32:17.975986Z" }, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " /*\n", " * NRPy+ Finite Difference Code Generation, Step 1 of 2: Read from main memory and compute finite difference stencils:\n", " */\n", " /*\n", " * Original SymPy expression:\n", " * \"const double phi_dDD00 = invdx0**2*(-5*phi/2 + 4*phi_i0m1/3 - phi_i0m2/12 + 4*phi_i0p1/3 - phi_i0p2/12)\"\n", " */\n", " const double phi_i0m2 = aux_gfs[IDX2S(PHIGF, i0-2)];\n", " const double phi_i0m1 = aux_gfs[IDX2S(PHIGF, i0-1)];\n", " const double phi = aux_gfs[IDX2S(PHIGF, i0)];\n", " const double phi_i0p1 = aux_gfs[IDX2S(PHIGF, i0+1)];\n", " const double phi_i0p2 = aux_gfs[IDX2S(PHIGF, i0+2)];\n", " const double FDPart1_Rational_5_2 = 5.0/2.0;\n", " const double FDPart1_Rational_1_12 = 1.0/12.0;\n", " const double FDPart1_Rational_4_3 = 4.0/3.0;\n", " const double phi_dDD00 = ((invdx0)*(invdx0))*(FDPart1_Rational_1_12*(-phi_i0m2 - phi_i0p2) + FDPart1_Rational_4_3*(phi_i0m1 + phi_i0p1) - FDPart1_Rational_5_2*phi);\n", " /*\n", " * NRPy+ Finite Difference Code Generation, Step 2 of 2: Evaluate SymPy expressions and write to main memory:\n", " */\n", " /*\n", " * Original SymPy expression:\n", " * \"aux_gfs[IDX2S(OUTPUTGF, i0)] = phi_dDD00\"\n", " */\n", " aux_gfs[IDX2S(OUTPUTGF, i0)] = phi_dDD00;\n", "}\n", "Wrote to file \"finite_diff_tutorial-second_deriv.h\"\n" ] } ], "source": [ "# Step P1: Import needed NRPy+ core modules:\n", "from outputC import lhrh # NRPy+: Core C code output module\n", "import NRPy_param_funcs as par # NRPy+: Parameter interface\n", "import finite_difference as fin # NRPy+: Finite difference C code generation module\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", "\n", "# Set the spatial dimension to 1\n", "par.set_paramsvals_value(\"grid::DIM = 1\")\n", "\n", "# Register the input gridfunction \"phi\" and the gridfunction to which data are output, \"output\":\n", "phi, output = gri.register_gridfunctions(\"AUX\",[\"phi\",\"output\"])\n", "\n", "# Declare phi_dDD as a rank-2 indexed expression: phi_dDD[i][j] = \\partial_i \\partial_j phi\n", "phi_dDD = ixp.declarerank2(\"phi_dDD\",\"nosym\")\n", "\n", "# Set output to \\partial_0^2 phi\n", "output = phi_dDD[0][0]\n", "\n", "# Output to the screen the core C code for evaluating the finite difference derivative\n", "fin.FD_outputC(\"stdout\",lhrh(lhs=gri.gfaccess(\"out_gf\",\"output\"),rhs=output))\n", "\n", "# Now, output the above C code to a file named \"finite_diff_tutorial-second_deriv.h\".\n", "fin.FD_outputC(\"finite_diff_tutorial-second_deriv.h\",lhrh(lhs=gri.gfaccess(\"aux_gfs\",\"output\"),rhs=output))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 2: Finite-Difference Playground: A Complete C Code for Analyzing Finite-Difference Expressions Output by NRPy+ \\[Back to [top](#toc)\\]\n", "$$\\label{fdplayground}$$\n", "\n", "NRPy+ is designed to generate C code \"kernels\" at the heart of more advanced projects. As an example of its utility, let's now write a simple C code that imports the above file `finite_diff_tutorial-second_deriv.h` to evaluate the finite-difference second derivative of\n", "\n", "$$f(x) = \\sin(x)$$\n", "\n", "at fourth-order accuracy. Let's call the finite-difference second derivative of $f$ evaluated at a point $x$ $f''(x)_{\\rm FD}$. A fourth-order-accurate $f''(x)_{\\rm FD}$ will, in the truncation-error-dominated regime, satisfy the equation\n", "\n", "$$f''(x)_{\\rm FD} = f''(x)_{\\rm exact} + \\mathcal{O}(\\Delta x^4).$$\n", "\n", "Therefore, the [relative error](https://en.wikipedia.org/wiki/Approximation_error) between the finite-difference derivative and the exact value should be given to good approximation by\n", "\n", "$$E_{\\rm Rel} = \\left| \\frac{f''(x)_{\\rm FD} - f''(x)_{\\rm exact}}{f''(x)_{\\rm exact}}\\right| \\propto \\Delta x^4,$$\n", "\n", "so that (taking the logarithm of both sides of the equation):\n", "\n", "$$\\log_{10} E_{\\rm Rel} = 4 \\log_{10} (\\Delta x) + \\log_{10} (k),$$\n", "\n", "where $k$ is the proportionality constant, divided by $f''(x)_{\\rm exact}$.\n", "\n", "Let's confirm this is true using our finite-difference playground code, which imports the NRPy+-generated C code generated above for evaluating $f''(x)_{\\rm FD}$ at fourth-order accuracy, and outputs $\\log_{10} (\\Delta x)$ and $\\log_{10} E_{\\rm Rel}$ in a range of $\\Delta x$ that is truncation-error dominated." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:32:17.983163Z", "iopub.status.busy": "2021-03-07T17:32:17.982187Z", "iopub.status.idle": "2021-03-07T17:32:17.986485Z", "shell.execute_reply": "2021-03-07T17:32:17.985840Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting finite_difference_playground.c\n" ] } ], "source": [ "%%writefile finite_difference_playground.c\n", "\n", "// Part P1: Import needed header files\n", "#include \"stdio.h\" // Provides printf()\n", "#include \"stdlib.h\" // Provides malloc() and free()\n", "#include \"math.h\" // Provides sin()\n", "\n", "// Part P2: Declare the IDX2S(gf,i) macro, which enables us to store 2-dimensions of\n", "// data in a 1D array. In this case, consecutive values of \"i\"\n", "// (\"gf\" held to a fixed value) are consecutive in memory, where\n", "// consecutive values of \"gf\" (fixing \"i\") are separated by N elements in\n", "// memory.\n", "#define IDX2S(gf, i) ( (i) + Npts_in_stencil * (gf) )\n", "\n", "// Part P3: Set PHIGF and OUTPUTGF macros\n", "#define PHIGF 0\n", "#define OUTPUTGF 1\n", "\n", "// Part P4: Import code generated by NRPy+ to compute f''(x)\n", "// as a finite difference derivative.\n", "void f_dDD_FD(double *in_gfs,double *aux_gfs,const int i0,const int Npts_in_stencil,const double invdx0) {\n", "#include \"finite_diff_tutorial-second_deriv.h\"\n", "}\n", "\n", "// Part P5: Define the function we wish to differentiate, as well as its exact second derivative:\n", "double f(const double x) { return sin(x); } // f(x)\n", "double f_dDD_exact(const double x) { return -sin(x); } // f''(x)\n", "\n", "// Part P6: Define x_i = (x_0 + i*Delta_x)\n", "double x_i(const double x_0,const int i,const double Delta_x) {\n", " return (x_0 + (double)i*Delta_x);\n", "}\n", "\n", "\n", "// main() function\n", "int main(int argc,char *argv[]) {\n", " // Step 0: Read command-line arguments (TODO)\n", "\n", " // Step 1: Set some needed constants\n", " const int Npts_in_stencil = 5; // Equal to the finite difference order, plus one. '+str(par.parval_from_str(\"finite_difference::FD_CENTDERIVS_ORDER\"))+'+1;\n", " const double PI = 3.14159265358979323846264338327950288; // The scale over which the sine function varies.\n", " const double x_eval = PI/4.0; // x_0 = desired x at which we wish to compute f(x)\n", "\n", " // Step 2: Evaluate f''(x_eval) using the exact expression:\n", " double EX = f_dDD_exact(x_eval);\n", "\n", " // Step 3: Allocate space for two gridfunctions\n", " double *in_gfs = (double *)malloc(sizeof(double)*Npts_in_stencil*2);\n", "\n", " // Step 4: Loop over grid spacings\n", " for(double Delta_x = 1e-3*(2*PI);Delta_x<=1.5e-1*(2*PI);Delta_x*=1.1) {\n", "\n", " // Step 4a: x_eval is the center point of the finite differencing stencil,\n", " // thus x_0 = x_eval - 2*dx for fourth-order-accurate first & second finite difference derivs,\n", " // and x_0 = x_eval - 3*dx for sixth-order-accurate first & second finite difference derivs, etc.\n", " // In general, for the integer Npts_in_stencil, we have\n", " // x_0 = x_eval - (double)(Npts_in_stencil/2)*Delta_x,\n", " // where we rely upon integer arithmetic (which always rounds down) to ensure\n", " // Npts_in_stencil/2 = 5/2 = 2 for fourth-order-accurate first & second finite difference derivs:\n", " const double x_0 = x_eval - (double)(Npts_in_stencil/2)*Delta_x;\n", "\n", " // Step 4b: Set \\phi=PHIGF to be f(x) as defined in the\n", " // f(const double x) function above, where x_i = stencil_start_x + i*Delta_x:\n", " for(int ii=0;ii]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYcAAAEHCAYAAABFroqmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAjr0lEQVR4nO3debzWc/7/8cfL2oQiskeLNVE4lkn8QoxthLGMGbsRYsgWpsHYxlC+srZQZBmRRJTUUSQqTrTbEiGlbIVSOuf1++P9OePonHOdq7o+1+danvfb7dzOdX0+13V9Xn1uF6/z3l5vc3dERESqWivpAEREJPcoOYiISDVKDiIiUo2Sg4iIVKPkICIi1ayTdACZsNlmm3nTpk2TDkNEJK9MmjTpa3dvXNO5gkgOTZs2paysLOkwRETyipnNqe2cupVERKSanEsOZtbdzN43s6lmNsTMNk46JhGRYpNzyQEYBbRy9z2AD4FrE45HRKTo5FxycPeR7r4iejoB2DbJeEREilHOJYeVnAO8VNMJM+tkZmVmVrZw4cIshyUiUtgSma1kZqXAljWc6ubuz0ev6QasAJ6o6TPcvS/QF6CkpETVA0VEMiiR5ODuHVKdN7OzgGOAQ11lY0VEsi7nupXM7AigK3Csuy9JOh4RkVzkDo88AjNnxvP5OZccgPuAjYBRZjbZzHonHZCISC756CM49FA4+2zo0yeea+TcCml33yHpGEREctHy5dC9O9x8M9SrFxLD3/4Wz7VyLjmIiEh1b74JnTrBjBlw0klw992w1VbxXS8Xu5VERCSyaBF07gwHHACLF8MLL8DTT8ebGEDJQUQkZw0ZAi1bhu6jSy8Ng8/HHJOdays5iIjkmLlz4fjj4YQToHFjmDABevaEDTfMXgxKDiIiOaKiAh54AHbdFUaMgNtvh7ffhn32yX4sGpAWEckBM2fCeeeFgecOHaB3b2jRIrl41HIQEUnQsmXwr39Bmzbw/vswYACMHJlsYgC1HEREEvPGG6G18N578Ne/wl13hTGGXKCWg4hIli1eHKantmsHS5bA8OHw+OO5kxhAyUFEJKuGDv11emqXLjB9Ohx5ZNJRVafkICKSBfPnw8knQ8eO0KgRjB8fupGyOT11VSg5iIjEyB369w/TU4cOhVtvhUmTYN99k44sNQ1Ii4jE5OOPQz2k0aPhoIOgb1/Yeeeko0qPWg4iIhm2YkWontqqFZSVhfGFMWPyJzGAWg4iIhn17ruhjPY774Txhfvvh222STqqVaeWg4hIBixdCtdcE0pdzJ0LzzwTCuflY2IAtRxERNbYa6+FxWwffQTnnAM9esAmmyQd1ZpRy0FEZDV9/30YcG7fHsrLobQU+vXL/8QASg4iIqvluefCYrZ+/eDKK2HatLCvc6FQchARWQXz54dtOo8/PpS7mDgxzEyqXz/pyDJLyUFEJA3u8MgjobXwwgthMVtZGZSUJB1ZPDQgLSJSh08+gfPPh1GjQrG8Bx+EXXZJOqp4qeUgIlKL8vJQ/6hVq1AL6YEHwsykQk8MoJaDiEiNpk8Pi9kmToSjj4ZevaBJk6Sjyh61HEREqqjcmW2vvUJtpCeeCGMMxZQYQC0HEZH/mTABzj037Of8l79Az565tQFPNqnlICJF76ef4LLLoG3bsEvbiy+GFkOxJgZQy0FEilxpaSh98emnYevO226DBg2Sjip5ajmISFH67rvQhXTYYbDeejB2bKigqsQQKDmISNF59tmwmG3AALj2WpgyBQ48MOmocou6lUSkaMyfDxdfDIMHw557wvDh4bdUp5aDiBS8ytIXu+4aBpv/85+wfkGJoXZqOYhIQfv001BWu7L0xUMP5dd2nUlRy0FEClJ5OdxzT/XSF0oM6VHLQUQKznvvhZlI48fDkUdC796w3XZJR5Vf1HIQkYLxyy9wyy3Qpg18+CE89hgMG6bEsDrUchCRgjBpUti/eepUOPlkuPde2HzzpKPKXznbcjCzK8zMzWyzpGMRkdy1dClcfTXsuy98/XXYvvOpp5QY1lROthzMrAlwOPBZ0rGISO567bVQVnvWrFAC4447YOONk46qMORqy+EuoCvgSQciIrln8eJQB6l9e6iogFdegb59lRgyKeeSg5l1BOa6+5Q6XtfJzMrMrGzhwoVZik5EkjZ8OOy2G/TpEyqpTp0KhxySdFSFJ5FuJTMrBbas4VQ34B+ELqWU3L0v0BegpKRELQyRAvf11yEZPP54qIv0zDOw335JR1W4EkkO7t6hpuNmtjvQDJhiZgDbAu+Y2b7uPj+LIYpIjnCHQYNCTaTvvoMbbgjF8tZfP+nICludycHM1gJaA1sDS4Hp7r4gjmDcfRrwvzkGZvYpUOLuX8dxPRHJbV9+GcYWnn8eSkrC2MLuuycdVXGoNTmYWQvgaqAD8BGwEKgH7GRmS4A+wAB3r8hGoCJSPNyhf3+44oqwp/Mdd4QupXVycn5lYUp1q28BegHnu/tv+vTNbHPgL8DpwIC4gnP3pnF9tojkptmzQ6G8V16Bgw4KhfJ23DHpqIpPrcnB3U9NcW4B0DOOgESkOJWXh1XN3brB2mtDr14hSayVc3Mqi0OqbqXL03j/T+7eJ4PxiEgRmjkzLGarLJTXpw80aZJ0VMUtVU6+Ctiojp8r4g5QRApXZaG8PfeEDz74tVCeEkPyUo05PObuN6Z6s5ltkOF4RKRIvPNOKJQ3ZYoK5eWiWlsO7t7VzNYys5NTvSaesESkUC1dCtdcEwrlLVgAQ4aoUF4uSjnUE01TVQIQkYx4/fWw18Ltt8OZZ4axhuOOSzoqqUk68wBKzexKM2tiZo0qf2KPTEQKxg8/hBXOBx0Ey5eH/Zz79VOhvFyWzpKSU6LfF1U55kDzzIcjIoXm5ZfDlNTPP4dLLw0D0BtumHRUUpc6k4O7N8tGICJSWL79Fi6/HAYMgF12gXHjoG3bpKOSdKVTW2ld4ELgoOjQq0Afd/8lxrhEJI8NHgwXXRQqqXbrBv/8J9Srl3RUsirS6VbqBawLPBA9Pz069re4ghKR/DR/fhhbGDw4rF0YMSIMQEv+SSc57OPuras8H21mKTfiEZHi4g6PPhqK4y1ZArfdFormrbtu0pHJ6kpntlJ5VKEVADNrDpTHF5KI5JPPPoOjjoKzzgqb8EyZEtYxKDHkt3RaDlcCY8xsNmDA9sDZsUYlIjmvogJ694arrw4th3vuCeMMKpRXGFImBzNbm7DRz47AztHhD9x9WdyBiUju+vDDUCjv9dfhsMOgb19o2jTpqCST6lohXQ6c6u7L3H1q9KPEIFKkVqwIG++0bg3TpsHDD4d1DEoMhSedbqU3zOw+4Cngp8qD7v5ObFGJSM6ZOhXOPRfKyuD44+H++2GrrZKOSuKSTnJoE/2+qcoxBw7JeDQiknOWLYN//zv8NGoETz8NJ54IZklHJnFKZ8xhqLvflaV4RCSHTJwYWgszZsBpp0HPnrDppklHJdmQ1phDlmIRkRyxZElYp9C2LSxaFDbgeewxJYZiojEHEfmNV18NM5E+/hjOPz8MQDdokHRUkm0acxARABYvhq5dw/7NLVrA6NFw8MFJRyVJSacqq74eIgVu+PDQSvjyy9CddNNNUL9+0lFJkmodczCznlUeX7rSuUfiC0lEsuWbb+D00+Hoo6FhQ3jzTejRQ4lBUg9IH1Tl8ZkrndsjhlhEJEvcw5TUXXeFgQPh+uth0iTYb7+kI5NckapbyWp5LCJ5bN486NwZnnsO9t4bSkthD/25JytJlRzWMrNNCK2LyseVSWLt2CMTkYxyh0ceCbuz/fwz3H57eLxOOtNSpOik+lo0BCbxa0KoOnXVY4tIRDLu00/DgPPIkdCuHfTrBzvtlHRUkstqTQ7u3jSLcYhIDCoq4IEHwv4KZnDffXDhhSqrLXVTg1KkQH3wQVjMNm4cHH54KKu9/fZJRyX5Qn8/iBSYFSvCeELr1jB9eiirPWKEEoOsGrUcRArIlCmhUN6kSSqrLWsmrZaDmbUzs7Ojx43NrFm8YYnIqli2DK67DkpK4PPPwxqGwYOVGGT11dlyMLMbgBLCNqEPA+sCjwMHxBuaiKRjwoTQWpg5M6x2vusuVU+VNZdOy+F44Fiiiqzu/iWwUZxBiUjdfvoprFNo2zYUzRs2DB59VIlBMiOdMYfl7u5m5gBmtkHMMYlIHcaMCTORZs+GCy4IA9Aqqy2ZlE7L4Wkz6wNsbGbnAaXAg/GGJSI1WbQoLGY75JCwbmHMGOjVS4lBMi+dkt09zOwwYDFh3OF6dx8VZ1Bm9nfgIqAcGObuXeO8nkg+GDYsJIZ58+DKK+HGG1U9VeKTzoD05cBTcSeEKtc7GOgItHb3ZWa2eTauK5KrvvkGunSBxx+H3XaDZ5+FffdNOiopdOl0K20EjDSz183sYjPbIuaYLgT+4+7LANx9QczXE8lJK5fVvuEGeOcdJQbJjjqTg7vf6O67Ebp5tgJeM7PSGGPaCTjQzCaa2Wtmtk9NLzKzTmZWZmZlCxcujDEckeybNw9OOAFOOQW22y4savvXv2C99ZKOTIrFqqyQXgDMB74B1qirJ0ouW9ZwqlsUUyNgf2AfwoB4c3f/TSVYd+8L9AUoKSlRlVgpCCuX1b7jDrjsMpXVluxLZ8yhM3Ay0BgYBJzn7jPX5KLu3iHF9S4Eno2SwVtmVgFsBqh5IAVtzhzo1CmU1T7wQHjoIZXVluSk8/dIE6CLu0+OOZZKzwEHA2PMbCdgPeDrLF1bJOuqltWGUA/pggtUVluSVWtyMLMG7r4Y6B49b1T1vLt/G1NM/YH+ZjYdWA6cuXKXkkihqFpW+w9/gD59VD1VckOqlsN/gWMIu8E5v91H2oHmcQTk7suB0+L4bJFcsWIF3HlnmIH0u9+FcYYzzggL20RyQaqd4I6JfqsCq0gGVS2rfcIJoRtpy5qmZ4gkqM5eTTN7JZ1jIpLasmVw/fW/ltUeNCiU1VZikFyUasyhHlAf2MzMNuHXbqUGwDZZiE2kYEycCOeco7Lakj9SjTmcD3QBtiaMO1Qmh8XAffGGJVIYliwJm/D07Albbx3qIx11VNJRidQt1ZjD3cDdZvZ3d783izGJFIRXXw0zkT7+WGW1Jf+kU5X1XjNrBbQE6lU5/micgYnkq8WLoWvXMC21RYtQVrt9+6SjElk16W4T2p6QHIYDRwLjACUHkZUMHx7Kan/5JVxxBdx0k8pqS35KZw3micChwHx3PxtoDTSMNSqRPPPNN3DaaXD00dCwIYwfDz16KDFI/konOSx19wpghZk1IBTgaxJvWCL5wT1MSW3ZEp56KkxVnTRJZbUl/6VTW6nMzDYmbA06CfgRGB9nUCL5YN486NwZnnsO9t47FMxr3TrpqEQyI50B6c7Rw95mNgJo4O5T4w1LJHe5w4ABoZT20qVhFtLll6usthSWVIvg9kp1zt3fiSckkdw1Z04YcH75ZWjXDvr1U1ltKUyp/ta5M8U5Bw7JcCwiOauiAnr1CmW13eHee0OXkspqS6FKtQju4GwGIpKrPvwwLGZ7/XU47DDo2xeaNk06KpF4pVN4r76Z/dPM+kbPdzSzY+IPTSRZK1aEbTpbt4Zp06B//9CdpMQgxSCdRvHDhE132kbP5wK3xBaRSA6YNg1+/3u4+mo44ohQMO/ss7XfghSPdJJDC3e/A/gFwN2X8NuNf0QKxvLlYQOevfaCzz6Dp5+GZ5+FrbZKOjKR7Epn8t1yM/sdYRAaM2sBLIs1KpEEvPVWKKs9Y0ZY7dyzp8pqS/FKp+VwAzACaGJmTwCvAF1jjUoki5YsgSuvDN1I338PL74Ijz2mxCDFLZ1FcKPM7B1gf0J30qWETYBE8t5rr4WZSLNmQadOYQC6oSqHiaRuOZjZ783sRGBtdx8GfAbcA7yRjeBE4rJ4MVx4YSilXVEBo0eHEttKDCJBrcnBzLoD/YE/AcPM7BZgJDAR2DE74Ylk3ksvQatWIRlcdhlMnQoHa1WPyG+k6lY6GtjT3X+O9pD+HGjl7p9mJTKRDPv2W+jSJYwn7LorvPkm7L9/0lGJ5KZU3Uo/u/vPAO7+HfCREoPkq8GDQ1ntJ5+Ef/4T3n1XiUEklVQth+ZmNrTK82ZVn7v7sfGFJZIZ8+fDxReH5LDnnjBiBLRpk3RUIrkvVXLouNLzVIX4RHKKe+g+6tIlTFW97bYwXVVltUXSk6rw3mvZDEQkUz77LJTVHjECDjgAHnoIdtkl6ahE8kuq2Up963pzOq8RyZbKstqtWoUKqvfcA2PHKjGIrI5UjezjzOznFOcN0ARAyQkffRQWs40dCx06wIMPqnqqyJpIlRyuSuP9r2cqEJHVsWJFqIF03XWw/vphZzZVTxVZc6nGHAZkMxCRVTV9eiiU9/bb0LEjPPAAbL110lGJFIZUYw4vmNkfzWzdGs41N7ObzOyceMMTqW75crjxxlBW+5NPYOBAGDJEiUEkk1J1K50HXA70NLNvgYVAPaAZMAu4z92fjz9EkV+9/Tace27YjOfUU+Huu6Fx46SjEik8qbqV5hNKc3c1s6bAVsBS4MNowx+RrFm6NGzCc+edsOWWMHQo/PGPSUclUrjqXBJkZlsAjQgb/MxTYpBse/310FqonJHUvTtsvHHSUYkUtlqTg5m1AXoDDQn7RgNsa2bfA53d/Z3Yo5Oi9sMPcM01YaC5WTMoLYVDD006KpHikKrl8AhwvrtPrHrQzPYHHgZaxxiXFLmXXw6b73z+OVx6Kdx6K2ywQdJRiRSPVFVZN1g5MQC4+wQgtv9MzayNmU0ws8lmVmZm+8Z1Lck9334LZ50FRxwB9evDuHFhHYMSg0h2pWo5vGRmw4BHCXs5ADQBziDsKR2XO4Ab3f0lMzsqet4+xutJjhgyBDp3hoULoVu3UFq7Xr2koxIpTqlmK11iZkcSqrNuEx2eC9zv7sNjjMmBBtHjhsCXMV5LcsBXX8Hf/w6DBoVy2sOHh/LaIpKclLOV3P0l4KUsxVKpC/CymfUgdHu1zfL1JUvc4YknwpjCjz/Cv/8dymqvW23ZpYhkW6oxh1qtaTVWMys1s+k1/HQELgQuc/cmwGVAv1o+o1M0JlG2cOHCNQlHEvD553DMMXD66bDzzjB5Mlx7rRKDSK4wd6/5hFmj2t4DTHH3bWMJyGwRsLG7u5kZsMjdG6R6T0lJiZeVlcURjmRYRUWomHrVVVBeHloLF18Ma6+ddGQixcfMJrl7SU3nUnUrLQTmEJJBJY+eb5658Kr5Evh/wKvAIcBHMV5LsmjWLDjvPHj1VTjkkJAkmjdPOioRqUmq5DAbONTdP1v5hJl9XsPrM+U84G4zWwf4GegU47UkC8rLfy2rve66ISmce67KaovkslTJoSewCVAtORCml8bC3ccBe8f1+ZJdM2aERDBxYqiF1KsXbLNN3e8TkWTVOiDt7ve7+5Razt0bX0hSCJYvh5tvDlNSZ82C//4Xnn9eiUEkX6RTeO+EGg4vAqa5+4LMhyT5btKksAnP1KlwyilhL+fN4xylEpGMqzM5AOcCvwfGRM/bA5OAZmZ2k7s/FlNskmeWLg2b8PToEZLBc8+FHdpEJP+kkxzWAXZ196/gfyW8HwX2A8YCSg7CuHFhbOHDD0Or4c47VVZbJJ+lswiuSWViiCyIjn0L/BJPWJIvfvwRLrkEDjoIli2DkSOhXz8lBpF8l07L4VUzexEYFD0/MTq2AfB9XIFJ7hs1Kqxb+OwzuOgiuO022HDDpKMSkUxIJzlcBJwAtIueDwAGe1hafXBcgUnu+u47uOIKePhh2GknGDsW2rWr+30ikj/qTA5RGYtxwHLCCum3vLaaG1Lwnn8eLrwQFiwIu7Rdfz387ndJRyUimVbnmIOZnQy8RehOOhmYaGYnxh2Y5JYFC+DPf4bjjoPGjcOitttuU2IQKVTpdCt1A/apXNNgZo2BUuCZOAOT3OAOTz4ZBp1/+AFuugmuvhrWWy/pyEQkTukkh7VWWuz2DatZ6lvyyxdfhC6kF1+E/faD/v2hZcukoxKRbEgnOYwws5eBJ6PnpwBx7gQnCXOHhx4KG+/88gv83/+FloPKaosUj3QGpK8ysz8BB0SH+rr7kHjDkqTMnh2mp44eDQcfHCqotmiRdFQikm3ptBxw98HA4JhjkQSVl8O990K3bqGF0Lt3SBJrqQNRpCjVmhzM7AfC1NVqpwgzXFPuzib54733QumL8ePhqKNCYmjSJOmoRCRJtSYHd98om4FI9v3yC3TvHorlbbghPPYY/PWv2oRHRNLsVpLCM3kynH12+H3iiXDffbDFFklHJSK5Qj3KRWbZsrBd5z77wLx58MwzMGiQEoOI/JZaDkVk4sRQTnvmTDjjDLjrLmjUKOmoRCQXqeVQBJYsgauugrZtYfFiGDYMBgxQYhCR2qnlUOBefRX+9jf4+GPo1CkMQDfQPDMRqYNaDgVq0SK44IKwkA3CorY+fZQYRCQ9Sg4FaNgw2G23sLr5yith6tRfk4SISDqUHArI11+HdQrHHAObbBIWtXXvDvXrJx2ZiOQbJYcC4A4DB8Kuu4ZpqTfcAJMmwb77Jh2ZiOQrDUjnublzoXNnGDo0rF3o3x9atUo6KhHJd2o55KnKstq77QajRkGPHqEbSYlBRDJBLYc89OmnoWJqaSm0bx8GnnfYIemoRKSQqOWQRyoqQsXU3XeHCROgVy945RUlBhHJPLUc8sQnn4TFbKNHQ4cOoUtp++2TjkpECpVaDjmuogIeeCC0Ft5+G/r2hZEjlRhEJF5qOeSwWbNCa+G11+Dww8PYwnbbJR2ViBQDtRxyUHl5qJi6xx7w7ruhC2nECCUGEcketRxyzPvvh7La48eHlc69e8M22yQdlYgUG7UccsQvv8B//gNt2sAHH8Djj4eFbUoMIpIEtRxyQGkpXHIJvPeetuwUkdyglkOC5swJyeCww8L2nUOHastOEckNiSQHMzvJzGaYWYWZlax07lozm2VmH5jZH5KIL24//ww33xwK5Q0fDrfcAjNmwB//mHRkIiJBUt1K04ETgD5VD5pZS+DPwG7A1kCpme3k7uXZDzEe48fD6aeHndlOOinURNIsJBHJNYm0HNz9PXf/oIZTHYGB7r7M3T8BZgEFUXi6vDy0Fg48MDwuLYWnn1ZiEJHclGsD0tsAE6o8/yI6ltfmzIHTToNx48JmPPffDw0bJh2ViEjtYksOZlYKbFnDqW7u/nwGPr8T0Alguxz+83vgwLCXc0UFPPZYSBIiIrkutuTg7h1W421zgSZVnm8bHavp8/sCfQFKSkp8Na4Vq7lz4eqr4YknYP/9w+/mzZOOSkQkPbk2lXUo8GczW9/MmgE7Am8lHNMqWbQI/vEP2HHHMKZw3XUwdqwSg4jkl0TGHMzseOBeoDEwzMwmu/sf3H2GmT0NzARWABfly0yl5cvD/go33wzffAN/+UuYotqsWdKRiYisukSSg7sPAYbUcu5W4NbsRrRmXngBunSB2bPhkEPgjjtg772TjkpEZPXlWrdSXnGHm26CY4+F+vXhpZfCFFUlBhHJd7k2lTVvLF0aqqcOHAhnnBE24Vl//aSjEhHJDCWH1TBvHnTsCGVloZJq165glnRUIiKZo+Swit59N3QjffcdPPssHHdc0hGJiGSexhxWwcCB0K5daCWMG6fEICKFS8khDV9/DaecAqeeCq1bw1tvhU15REQKlZJDHYYOhVatYMgQuPXWsKBty5qKgoiIFBCNOdTi++/h0kvh0UdDK2HkSNhjj6SjEhHJDrUcVlJeHsYWWrUK9ZCuuw4mTlRiEJHiopZDpDIp3HILvP8+7L47PPcclJTU+VYRkYJT9C2HFStCKe2WLUM57XXWCQXzJk9WYhCR4lXULYcxY6BTJ5g1K8xCGjw4TE9dq+hTpogUu6JODo0aQYMGYSbSsccqKYiIVCrq5NC6dSiBodIXIiK/VfR/KysxiIhUV/TJQUREqlNyEBGRapQcRESkGiUHERGpRslBRESqUXIQEZFqlBxERKQac/ekY1hjZrYQmJN0HKtgM+DrpIPIUbo3NdN9qZ3uTe3qujfbu3vjmk4URHLIN2ZW5u4q61cD3Zua6b7UTvemdmtyb9StJCIi1Sg5iIhINUoOyeibdAA5TPemZrovtdO9qd1q3xuNOYiISDVqOYiISDVKDiIiUo2SQxaYWXcze9/MpprZEDPbuJbXHWFmH5jZLDO7JsthJsLMTjKzGWZWYWa1Trkzs0/NbJqZTTazsmzGmIRVuC/F+J1pZGajzOyj6PcmtbyuPPq+TDazodmOM5vq+h6Y2fpm9lR0fqKZNa3rM5UcsmMU0Mrd9wA+BK5d+QVmtjZwP3Ak0BI41cxaZjXKZEwHTgDGpvHag929TZHMaa/zvhTxd+Ya4BV33xF4JXpek6XR96WNux+bvfCyK83vwbnAd+6+A3AXcHtdn6vkkAXuPtLdV0RPJwDb1vCyfYFZ7j7b3ZcDA4GO2YoxKe7+nrt/kHQcuSbN+1KU3xnCv3FA9HgAcFxyoeSEdL4HVe/ZM8ChZqn3wVRyyL5zgJdqOL4N8HmV519ExyRwYKSZTTKzTkkHkyOK9TuzhbvPix7PB7ao5XX1zKzMzCaY2XHZCS0R6XwP/vea6A/VRcCmqT50nQwGWNTMrBTYsoZT3dz9+eg13YAVwBPZjC1p6dybNLRz97lmtjkwyszed/d0uqJyVobuS0FKdW+qPnF3N7Pa5uNvH31nmgOjzWyau3+c6VgLlZJDhrh7h1Tnzews4BjgUK95cclcoEmV59tGx/JeXfcmzc+YG/1eYGZDCE3pvE4OGbgvRfmdMbOvzGwrd59nZlsBC2r5jMrvzGwzexXYEyjE5JDO96DyNV+Y2TpAQ+CbVB+qbqUsMLMjgK7Ase6+pJaXvQ3saGbNzGw94M9AQc+wSJeZbWBmG1U+Bg4nDNgWu2L9zgwFzowenwlUa2WZ2SZmtn70eDPgAGBm1iLMrnS+B1Xv2YnA6Fr+SP2Vu+sn5h9gFqG/b3L00zs6vjUwvMrrjiLMZvqY0LWQeOxZuDfHE/pIlwFfAS+vfG+A5sCU6GdGMdybdO5LEX9nNiXMUvoIKAUaRcdLgIeix22BadF3ZhpwbtJxx3xPqn0PgJsIf5AC1AMGRf8vegtoXtdnqnyGiIhUo24lERGpRslBRESqUXIQEZFqlBxERKQaJQcREalGyUFERKpRcpCCY2Y/rsF7L47KGnu0eKryuJnZPdG5qWa2V5VzW5nZi9Hj9ma2yMzejUoojzWzY9K47llmdl/0+LhMV1c1sx5mdkgmP1MKm5KDyG+9AXQA5qx0/Ehgx+inE9CryrnLgQerPH/d3fd0952BS4D7zOzQVYjhOELp5Uy6l9pLW4tUo+QgBSv6a7+7mU2PNgo6JTq+lpk9EG3ANMrMhpvZiQDu/q67f1rDx3UEHvVgArBxVNcH4E/AiJpicPfJhJWqF0fXbmxmg83s7ejngJVibgscC3SPNqlpYWbnRa+dEr23fop/8/Nmdkb0+HwzeyKKYw6wqZnVVMxOpBoV3pNCdgLQBmgNbAa8bWZjCXV2mhL+Ot8ceA/oX8dn1VgW2czqETZRWZbive8AV0WP7wbucvdxZrYd8DKwa+UL3f3NaNeyF939GQAz+97dH4we30LYuOXeWq7VCXjDzD4BrgD2XymOA4DBdfxbRZQcpKC1A55093LgKzN7DdgnOj7I3SuA+WY2Zg2usRWwsI7XVN1UpQPQsso+Kw3MbMM63t8qSgobAxsSEkqN3P0rM7seGAMc7+7fVjm9gFCbSaROSg4i6amtLPKWhKJmqexJaJ1A6Mrd391/rvqCOjblegQ4zt2nRKXf29dxvd0J5ZhXTgT1gKV1vFcE0JiDFLbXgVPMbG0zawwcRKhI+Qbwp2jsYQvq/p8thJLHZ0TjGPsDizzsRvYhoYuqRma2B3AdYY9fgJHA36ucb1PD234ANqryfCNgnpmtC/w1VZBmti9h8HxP4Eoza1bl9E6o1LmkSclBCtkQYCqhbPNooKu7zyf0uX9BqO//OKEvfhGAmV1iZl8QWgZTzeyh6LOGA7MJJY8fBDoDuPtPwMdmtkOV6x5YOZWVkBQucfdXonOXACXRdNiZwAU1xD0QuCr6jBaE5DKRkNTer+0fG+1f8CBwjrt/SRhz6B8ltHWBHYCydG6ciEp2S1Eysw3d/Ucz25TQmjggShyr81nHA3u7+z8zGmQGRTHu5e7XJR2L5AeNOUixetHMNgbWA25e3cQA4O5DoiSTy9YB7kw6CMkfajmI5CEz6wactNLhQe5+axLxSOFRchARkWo0IC0iItUoOYiISDVKDiIiUo2Sg4iIVPP/AQeMvCGghbBOAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "\n", "# from https://stackoverflow.com/questions/52386747/matplotlib-check-for-empty-plot\n", "import numpy\n", "x, y = numpy.loadtxt(fname='data.txt', delimiter='\\t', unpack=True)\n", "fig, ax = plt.subplots()\n", "ax.set_xlabel('log10(Delta_x)')\n", "ax.set_ylabel('log10([Relative Error])')\n", "ax.plot(x, y, color='b')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A quick glance at the above plot indicates that between $\\log_{10}(\\Delta x) \\approx -2.0$ and $\\log_{10}(\\Delta x) \\approx -1.0$, the logarithmic relative error $\\log_{10} E_{\\rm Rel}$ increases by about 4, indicating a positive slope of approximately 4. Thus we have confirmed fourth-order convergence." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Step 3: Exercises \\[Back to [top](#toc)\\]\n", "$$\\label{exercise}$$\n", "\n", "1. Use NumPy's [`polyfit()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.polyfit.html) function to evaluate the least-squares slope of the above line.\n", "2. Explore $\\log_{10}(\\Delta x)$ outside the above (truncation-error-dominated) range. What other errors dominate outside the truncation-error-dominated regime?\n", "3. Adjust the above NRPy+ and C codes to support 6th-order-accurate finite differencing. What should the slope of the resulting plot of $\\log_{10} E_{\\rm Rel}$ versus $\\log_{10}(\\Delta x)$ be? Explain why this case does not provide as clean a slope as the 4th-order case." ] }, { "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-Finite_Difference_Playground.pdf](Tutorial-Start_to_Finish-Finite_Difference_Playground.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": 5, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:32:18.967244Z", "iopub.status.busy": "2021-03-07T17:32:18.966638Z", "iopub.status.idle": "2021-03-07T17:32:22.469505Z", "shell.execute_reply": "2021-03-07T17:32:22.468459Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created Tutorial-Start_to_Finish-Finite_Difference_Playground.tex, and\n", " compiled LaTeX file to PDF file Tutorial-Start_to_Finish-\n", " Finite_Difference_Playground.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-Finite_Difference_Playground\")" ] } ], "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.0rc2" } }, "nbformat": 4, "nbformat_minor": 2 }