{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Differential testing\n", "\n", "Test multiple different methods for implementation of finite difference differentiation.\n", "This includes using `findiff`" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import findiff as fd\n", "import numpy as np\n", "import sympy as sp\n", "from termcolor import colored\n", "\n", "import discretisedfield as df\n", "import discretisedfield.util as dfu" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create testing functions" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def test_function(fun, verbose=1):\n", " print(colored(f\"Testing {fun.__name__}...\", \"blue\"))\n", " p1 = (0.0, 0.0, 0.0)\n", " p2 = (10.0, 10.0, 10.0)\n", "\n", " def f(pos):\n", " x, y, z = pos\n", " return (x**4, y**4, z**4)\n", "\n", " total = 0\n", " success = 0\n", "\n", " for i in range(1, 7):\n", " for order in range(1, 5):\n", " total += 1\n", " print(f\"Test {i} cell(s) in z - order {order}\", end=\" \")\n", " mesh = df.Mesh(p1=p1, p2=p2, n=(10, 10, i))\n", " field = df.Field(mesh, dim=3, value=f)\n", " try:\n", " out = fun(field, \"z\", order=order)\n", " if np.allclose(out.array, 0):\n", " print(colored(\"Success with assumption\", \"yellow\"))\n", " else:\n", " print(colored(\"Success\", \"green\"))\n", " success += 1\n", " except Exception as e:\n", " if verbose:\n", " print(colored(\"Failed\", \"red\"), end=\" \")\n", " print(e)\n", " else:\n", " print(colored(\"Failed\", \"red\"))\n", "\n", " print(colored(f\"Success rate: {success}/{total}\", \"blue\"))\n", "\n", "\n", "def test_value(fun, verbose=1):\n", " # Test results against sympy\n", " print(colored(f\"Testing {fun.__name__}...\", \"blue\"))\n", " p1 = (0, 0, 0)\n", " p2 = (10, 10, 10)\n", "\n", " x = sp.symbols(\"x\")\n", " fx = sp.sqrt(x)\n", "\n", " lam_f = sp.lambdify(x, fx, \"numpy\")\n", "\n", " def value_fun(point):\n", " x, y, z = point\n", " return lam_f(x)\n", "\n", " total = 0\n", " success = 0\n", "\n", " for i in range(1, 5):\n", " for order in range(1, 5):\n", " value = float(fx.diff(x, order).subs(x, 5))\n", " total += 1\n", " print(f\"Test {i} cell(s) in x - order {order}\", end=\" \")\n", " mesh = df.Mesh(p1=p1, p2=p2, n=(i, 1, 1))\n", " field = df.Field(mesh, dim=1, value=value_fun)\n", " try:\n", " fun_value = fun(field, \"x\", order=order)((5, 5, 5))\n", " if np.allclose(fun_value, value, rtol=0.05):\n", " if verbose:\n", " print(colored(\"Success\", \"green\"), end=\" \")\n", " print(f\"Expected {value}, got {fun_value}\")\n", " else:\n", " print(colored(\"Success\", \"green\"))\n", " success += 1\n", " else:\n", " if verbose:\n", " print(colored(\"Failed\", \"red\"), end=\" \")\n", " print(f\"Expected {value}, got {fun_value}\")\n", " else:\n", " print(colored(\"Failed\", \"red\"))\n", " except:\n", " print(\"\")\n", "\n", " print(colored(f\"Success rate: {success}/{total}\", \"blue\"))\n", "\n", "\n", "def test_accuracy(fun, verbose=1):\n", " print(colored(f\"Testing {fun.__name__}...\", \"blue\"))\n", " # Test results against sympy\n", " p1 = (0, 0, 0)\n", " p2 = (10, 10, 10)\n", " n = (30, 1, 1)\n", " mesh = df.Mesh(p1=p1, p2=p2, n=n)\n", "\n", " x = sp.symbols(\"x\")\n", " fx = x**6\n", "\n", " lam_f = sp.lambdify(x, fx, \"numpy\")\n", "\n", " def value_fun(point):\n", " x, y, z = point\n", " return lam_f(x)\n", "\n", " field = df.Field(mesh, nvdim=1, value=value_fun)\n", "\n", " total = 0\n", " success = 0\n", "\n", " for order in [1, 2, 3, 4, 5]:\n", " value = float(fx.diff(x, order).integrate((x, 0, 10)) / 10)\n", " for acc in [2, 4, 6, 8, 10]:\n", " print(f\"Test {order=}, {acc=}\", end=\" \")\n", " total += 1\n", " try:\n", " fun_value = fun(field, \"x\", order=order).mean()\n", " if np.allclose(fun_value, value, rtol=0.05):\n", " if verbose:\n", " print(colored(\"Success\", \"green\"), end=\" \")\n", " print(f\"Expected {value}, got {fun_value}\")\n", " else:\n", " print(colored(\"Success\", \"green\"))\n", " success += 1\n", " else:\n", " if verbose:\n", " print(colored(\"Failed\", \"red\"), end=\" \")\n", " print(f\"Expected {value}, got {fun_value}\")\n", " else:\n", " print(colored(\"Failed\", \"red\"))\n", " except:\n", " print(\"\")\n", " print(colored(f\"Success rate: {success}/{total}\", \"blue\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Original df.Field differential" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def diff_original(self, direction, order=1):\n", " direction = dfu.axesdict[direction]\n", "\n", " # If there are no neighbouring cells in the specified direction, zero\n", " # field is returned.\n", " if self.mesh.n[direction] <= 1:\n", " return self.zero\n", "\n", " padded_array = self.array\n", "\n", " if order not in (1, 2):\n", " msg = f\"Derivative of the n={order} order is not implemented.\"\n", " raise NotImplementedError(msg)\n", "\n", " elif order == 1:\n", " if self.nvdim == 1:\n", " derivative_array = np.gradient(\n", " padded_array[..., 0], self.mesh.cell[direction], axis=direction\n", " )[..., np.newaxis]\n", " else:\n", " derivative_array = np.gradient(\n", " padded_array, self.mesh.cell[direction], axis=direction\n", " )\n", "\n", " elif order == 2:\n", " derivative_array = np.zeros_like(padded_array)\n", " for i in range(padded_array.shape[direction]):\n", " if i == 0:\n", " i1, i2, i3 = i + 2, i + 1, i\n", " elif i == padded_array.shape[direction] - 1:\n", " i1, i2, i3 = i, i - 1, i - 2\n", " else:\n", " i1, i2, i3 = i + 1, i, i - 1\n", " index1 = dfu.assemble_index(slice(None), 4, {direction: i1})\n", " index2 = dfu.assemble_index(slice(None), 4, {direction: i2})\n", " index3 = dfu.assemble_index(slice(None), 4, {direction: i3})\n", " index = dfu.assemble_index(slice(None), 4, {direction: i})\n", " derivative_array[index] = (\n", " padded_array[index1] - 2 * padded_array[index2] + padded_array[index3]\n", " ) / self.mesh.cell[direction] ** 2\n", "\n", " return self.__class__(\n", " self.mesh, dim=self.nvdim, value=derivative_array, vdims=self.vdims\n", " )" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[34mTesting diff_original...\u001b[0m\n", "Test 1 cell(s) in z - order 1 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 2 cell(s) in z - order 2 \u001b[31mFailed\u001b[0m index 2 is out of bounds for axis 2 with size 2\n", "Test 2 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 2 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Derivative of the n=4 order is not implemented.\n", "Test 3 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 3 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Derivative of the n=4 order is not implemented.\n", "Test 4 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 4 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Derivative of the n=4 order is not implemented.\n", "Test 5 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 5 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Derivative of the n=4 order is not implemented.\n", "Test 6 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 6 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Derivative of the n=4 order is not implemented.\n", "\u001b[34mSuccess rate: 13/24\u001b[0m\n" ] } ], "source": [ "test_function(diff_original)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Edit Original df.Field differential\n", "Accounts for `order=2` and number of cells `2`." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def diff_original_edit(self, direction, order=1):\n", " direction_idx = dfu.axesdict[direction]\n", "\n", " # If there are no neighbouring cells in the specified direction, zero\n", " # field is returned.\n", " if self.mesh.n[direction_idx] <= order:\n", " return self.zero\n", "\n", " padded_array = self.array\n", "\n", " if order not in (1, 2):\n", " msg = f\"Derivative of the n={order} order is not implemented.\"\n", " raise NotImplementedError(msg)\n", "\n", " elif order == 1:\n", " if self.nvdim == 1:\n", " derivative_array = np.gradient(\n", " padded_array[..., 0], self.mesh.cell[direction_idx], axis=direction_idx\n", " )[..., np.newaxis]\n", " else:\n", " derivative_array = np.gradient(\n", " padded_array, self.mesh.cell[direction_idx], axis=direction_idx\n", " )\n", "\n", " elif order == 2:\n", " derivative_array = np.zeros_like(padded_array)\n", " for i in range(padded_array.shape[direction_idx]):\n", " if i == 0:\n", " i1, i2, i3 = i + 2, i + 1, i\n", " elif i == padded_array.shape[direction_idx] - 1:\n", " i1, i2, i3 = i, i - 1, i - 2\n", " else:\n", " i1, i2, i3 = i + 1, i, i - 1\n", " index1 = dfu.assemble_index(slice(None), 4, {direction_idx: i1})\n", " index2 = dfu.assemble_index(slice(None), 4, {direction_idx: i2})\n", " index3 = dfu.assemble_index(slice(None), 4, {direction_idx: i3})\n", " index = dfu.assemble_index(slice(None), 4, {direction_idx: i})\n", " derivative_array[index] = (\n", " padded_array[index1] - 2 * padded_array[index2] + padded_array[index3]\n", " ) / self.mesh.cell[direction_idx] ** 2\n", "\n", " return self.__class__(\n", " self.mesh, dim=self.nvdim, value=derivative_array, vdims=self.vdims\n", " )" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[34mTesting diff_original_edit...\u001b[0m\n", "Test 1 cell(s) in z - order 1 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 2 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 4 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 4 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 5 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 5 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Derivative of the n=4 order is not implemented.\n", "Test 6 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 6 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Derivative of the n=4 order is not implemented.\n", "\u001b[34mSuccess rate: 19/24\u001b[0m\n" ] } ], "source": [ "test_function(diff_original_edit)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Edit Fast Original df.Field differential\n", "Accounts for `order=2` and number of cells `2` and faster implementation of `order=2`.\n", "\n", "Pad array so the same stencil can be used everywhere\n", "\\begin{align}\n", " f(1) + f(-1) - 2f(0) &= f(2) + f(0) - 2 f(1) \\\\ \n", " f(-1) &= f(2) - 3 f(1) + 3f(0)\n", "\\end{align}" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def diff_original_fast(self, direction, order=1):\n", " direction_idx = dfu.axesdict[direction]\n", "\n", " # If there are no neighbouring cells in the specified direction, zero\n", " # field is returned.\n", " if self.mesh.n[direction_idx] <= order:\n", " return self.zero\n", "\n", " padded_array = self.array\n", "\n", " if order not in (1, 2):\n", " msg = f\"Derivative of the n={order} order is not implemented.\"\n", " raise NotImplementedError(msg)\n", "\n", " elif order == 1:\n", " if self.nvdim == 1:\n", " derivative_array = np.gradient(\n", " padded_array[..., 0], self.mesh.cell[direction_idx], axis=direction_idx\n", " )[..., np.newaxis]\n", " else:\n", " derivative_array = np.gradient(\n", " padded_array, self.mesh.cell[direction_idx], axis=direction_idx\n", " )\n", "\n", " elif order == 2:\n", "\n", " def pad_fun(vector, pad_width, iaxis, kwargs):\n", " if iaxis == direction_idx:\n", " vector[0] = vector[3] - 3 * vector[2] + 3 * vector[1]\n", " vector[-1] = vector[-4] - 3 * vector[-3] + 3 * vector[-2]\n", "\n", " pad_width = [(0, 0)] * 4\n", " pad_width[direction_idx] = (1, 1)\n", " padded_array = np.pad(padded_array, pad_width, pad_fun)\n", " # padded_array = self.pad({'x': (1, 1)}, mode='constant').array\n", " # padded_array[0] = padded_array[3] - 3*padded_array[2] + 3*padded_array[1]\n", " # padded_array[-1] = padded_array[-4] - 3*padded_array[-3] + 3*padded_array[-2]\n", " # derivative_array = np.empty_like(padded_array)\n", " index_p1 = slice(2, None)\n", " index_0 = slice(1, -1)\n", " index_m1 = slice(None, -2)\n", " derivative_array = (\n", " padded_array[index_p1] - 2 * padded_array[index_0] + padded_array[index_m1]\n", " ) / self.mesh.cell[direction_idx] ** 2\n", "\n", " # derivative_array[0] = derivative_array[1]\n", " # derivative_array[-1] = derivative_array[-2]\n", "\n", " return self.__class__(\n", " self.mesh, dim=self.nvdim, value=derivative_array, vdims=self.vdims\n", " )" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 'field' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m/home/sam/repos/ubermag-devtools/repos/discretisedfield/dev/diff.ipynb Cell 13\u001b[0m in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> <a href='vscode-notebook-cell://ssh-remote%2B10.15.40.246/home/sam/repos/ubermag-devtools/repos/discretisedfield/dev/diff.ipynb#X50sdnNjb2RlLXJlbW90ZQ%3D%3D?line=0'>1</a>\u001b[0m get_ipython()\u001b[39m.\u001b[39;49mrun_cell_magic(\u001b[39m'\u001b[39;49m\u001b[39mtimeit\u001b[39;49m\u001b[39m'\u001b[39;49m, \u001b[39m'\u001b[39;49m\u001b[39m'\u001b[39;49m, \u001b[39m\"\u001b[39;49m\u001b[39mdiff_original_fast(field, \u001b[39;49m\u001b[39m'\u001b[39;49m\u001b[39mx\u001b[39;49m\u001b[39m'\u001b[39;49m\u001b[39m, order=2)\u001b[39;49m\u001b[39m\\n\u001b[39;49;00m\u001b[39m\"\u001b[39;49m)\n", "File \u001b[0;32m~/miniconda3/envs/ubermagdev/lib/python3.8/site-packages/IPython/core/interactiveshell.py:2358\u001b[0m, in \u001b[0;36mInteractiveShell.run_cell_magic\u001b[0;34m(self, magic_name, line, cell)\u001b[0m\n\u001b[1;32m 2356\u001b[0m \u001b[39mwith\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mbuiltin_trap:\n\u001b[1;32m 2357\u001b[0m args \u001b[39m=\u001b[39m (magic_arg_s, cell)\n\u001b[0;32m-> 2358\u001b[0m result \u001b[39m=\u001b[39m fn(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 2359\u001b[0m \u001b[39mreturn\u001b[39;00m result\n", "File \u001b[0;32m~/miniconda3/envs/ubermagdev/lib/python3.8/site-packages/IPython/core/magics/execution.py:1162\u001b[0m, in \u001b[0;36mExecutionMagics.timeit\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n\u001b[1;32m 1160\u001b[0m \u001b[39mfor\u001b[39;00m index \u001b[39min\u001b[39;00m \u001b[39mrange\u001b[39m(\u001b[39m0\u001b[39m, \u001b[39m10\u001b[39m):\n\u001b[1;32m 1161\u001b[0m number \u001b[39m=\u001b[39m \u001b[39m10\u001b[39m \u001b[39m*\u001b[39m\u001b[39m*\u001b[39m index\n\u001b[0;32m-> 1162\u001b[0m time_number \u001b[39m=\u001b[39m timer\u001b[39m.\u001b[39;49mtimeit(number)\n\u001b[1;32m 1163\u001b[0m \u001b[39mif\u001b[39;00m time_number \u001b[39m>\u001b[39m\u001b[39m=\u001b[39m \u001b[39m0.2\u001b[39m:\n\u001b[1;32m 1164\u001b[0m \u001b[39mbreak\u001b[39;00m\n", "File \u001b[0;32m~/miniconda3/envs/ubermagdev/lib/python3.8/site-packages/IPython/core/magics/execution.py:156\u001b[0m, in \u001b[0;36mTimer.timeit\u001b[0;34m(self, number)\u001b[0m\n\u001b[1;32m 154\u001b[0m gc\u001b[39m.\u001b[39mdisable()\n\u001b[1;32m 155\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[0;32m--> 156\u001b[0m timing \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49minner(it, \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mtimer)\n\u001b[1;32m 157\u001b[0m \u001b[39mfinally\u001b[39;00m:\n\u001b[1;32m 158\u001b[0m \u001b[39mif\u001b[39;00m gcold:\n", "File \u001b[0;32m<magic-timeit>:1\u001b[0m, in \u001b[0;36minner\u001b[0;34m(_it, _timer)\u001b[0m\n", "\u001b[0;31mNameError\u001b[0m: name 'field' is not defined" ] } ], "source": [ "%%timeit\n", "diff_original_fast(field, \"x\", order=2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5.02 ms ± 19.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%%timeit\n", "diff_original_edit(field, \"x\", order=2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[34mTesting diff_original_fast...\u001b[0m\n", "Test 1 cell(s) in z - order 1 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 2 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 4 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 4 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 5 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 5 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Derivative of the n=4 order is not implemented.\n", "Test 6 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Derivative of the n=3 order is not implemented.\n", "Test 6 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Derivative of the n=4 order is not implemented.\n", "\u001b[34mSuccess rate: 19/24\u001b[0m\n" ] } ], "source": [ "test_function(diff_original_fast)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Findiff implementation" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def diff_a(self, direction, order=1, acc=None):\n", " direction_idx = dfu.axesdict[direction]\n", "\n", " # If there are no neighbouring cells in the specified direction, zero\n", " # field is returned.\n", "\n", " # ASSUME that needs more cells than curvature!\n", " if self.mesh.n[direction_idx] <= order:\n", " return self.zero\n", "\n", " # Create FinDiff object.\n", " diff_fd = fd.FinDiff(direction_idx, self.mesh.cell[direction_idx], order, acc=acc)\n", "\n", " derivative_array = diff_fd(self.array)\n", "\n", " return self.__class__(\n", " self.mesh,\n", " nvdim=self.nvdim,\n", " value=derivative_array,\n", " vdims=self.vdims,\n", " )" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[34mTesting diff_a...\u001b[0m\n", "Test 1 cell(s) in z - order 1 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 1 \u001b[31mFailed\u001b[0m Shift slice out of bounds\n", "Test 2 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 2 \u001b[31mFailed\u001b[0m Shift slice out of bounds\n", "Test 3 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 4 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Shift slice out of bounds\n", "Test 4 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 5 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Shift slice out of bounds\n", "Test 5 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Shift slice out of bounds\n", "Test 6 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 3 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Shift slice out of bounds\n", "\u001b[34mSuccess rate: 18/24\u001b[0m\n" ] } ], "source": [ "test_function(diff_a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Findiff implementation\n", "Allowing for mixed accuracy default behaviour" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def fd_diff_edit_b(array, h, order, dim, acc=None):\n", " \"\"\"Edit of findiff.diff.diff to allow differnt accuracies\"\"\"\n", " if acc is None:\n", " coefs = {}\n", " coefs[\"center\"] = fd.coefficients(order, acc=2)[\"center\"]\n", " coefs[\"forward\"] = fd.coefficients(order, offsets=range(0, order + 1))\n", " coefs[\"backward\"] = fd.coefficients(order, offsets=range(-order, 1))\n", " else:\n", " coefs = fd.coefficients(order, acc=acc)\n", "\n", " try:\n", " npts = array.shape[dim]\n", " except AttributeError as err:\n", " raise ValueError(\n", " \"FinDiff objects can only be applied to arrays or evaluated(!) functions\"\n", " \" returning arrays\"\n", " ) from err\n", " yd = np.zeros_like(array)\n", " scheme = \"center\"\n", " weights = coefs[scheme][\"coefficients\"]\n", " offsets = coefs[scheme][\"offsets\"]\n", "\n", " num_bndry_points = len(weights) // 2\n", " ref_slice = slice(num_bndry_points, npts - num_bndry_points, 1)\n", " off_slices = [\n", " fd.diff.Diff._shift_slice(..., ref_slice, offsets[k], npts)\n", " for k in range(len(offsets))\n", " ]\n", "\n", " fd.diff.Diff._apply_to_array(..., yd, array, weights, off_slices, ref_slice, dim)\n", "\n", " scheme = \"forward\"\n", " weights = coefs[scheme][\"coefficients\"]\n", " offsets = coefs[scheme][\"offsets\"]\n", "\n", " ref_slice = slice(0, num_bndry_points, 1)\n", " off_slices = [\n", " fd.diff.Diff._shift_slice(..., ref_slice, offsets[k], npts)\n", " for k in range(len(offsets))\n", " ]\n", "\n", " fd.diff.Diff._apply_to_array(..., yd, array, weights, off_slices, ref_slice, dim)\n", "\n", " scheme = \"backward\"\n", " weights = coefs[scheme][\"coefficients\"]\n", " offsets = coefs[scheme][\"offsets\"]\n", "\n", " ref_slice = slice(npts - num_bndry_points, npts, 1)\n", " off_slices = [\n", " fd.diff.Diff._shift_slice(..., ref_slice, offsets[k], npts)\n", " for k in range(len(offsets))\n", " ]\n", "\n", " fd.diff.Diff._apply_to_array(..., yd, array, weights, off_slices, ref_slice, dim)\n", "\n", " h_inv = 1.0 / h**order\n", "\n", " return yd * h_inv" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "def diff_b(self, direction, order=1, acc=None):\n", " direction_idx = dfu.axesdict[direction]\n", "\n", " # If there are no neighbouring cells in the specified direction, zero\n", " # field is returned.\n", "\n", " # ASSUME that needs more cells than curvature!\n", " if self.mesh.n[direction_idx] <= order:\n", " return self.zero\n", "\n", " # Create FinDiff object.\n", " derivative_array = fd_diff_edit_b(\n", " self.array, self.mesh.cell[direction_idx], order, direction_idx, acc=acc\n", " )\n", "\n", " return self.__class__(\n", " self.mesh,\n", " nvdim=self.nvdim,\n", " value=derivative_array,\n", " vdims=self.vdims,\n", " )" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[34mTesting diff_b...\u001b[0m\n", "Test 1 cell(s) in z - order 1 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 2 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 4 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m Shift slice out of bounds\n", "Test 4 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 5 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 3 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m Shift slice out of bounds\n", "Test 6 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 3 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 4 \u001b[32mSuccess\u001b[0m\n", "\u001b[34mSuccess rate: 22/24\u001b[0m\n" ] } ], "source": [ "test_function(diff_b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Findiff implementation\n", "Generalise defaults to work for all orders" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "def fd_diff_edit_c(array, h, order, dim, acc=None):\n", " \"\"\"Edit of findiff.diff.diff to allow differnt accuracies\"\"\"\n", " if acc is None:\n", " coefs = {}\n", " coefs[\"center\"] = fd.coefficients(order, acc=2)[\"center\"]\n", " coefs[\"forward\"] = fd.coefficients(order, offsets=range(0, order + 1))\n", " coefs[\"backward\"] = fd.coefficients(order, offsets=range(-order, 1))\n", " else:\n", " coefs = fd.coefficients(order, acc=acc)\n", "\n", " try:\n", " npts = array.shape[dim]\n", " except AttributeError as err:\n", " raise ValueError(\n", " \"FinDiff objects can only be applied to arrays or evaluated(!) functions\"\n", " \" returning arrays\"\n", " ) from err\n", "\n", " yd = np.zeros_like(array)\n", "\n", " len_needed = len(coefs[\"center\"][\"coefficients\"]) // 2 - 1 + order\n", " if npts <= len_needed:\n", " for i in range(npts):\n", " coefs = fd.coefficients(order, offsets=(np.arange(npts) - i).tolist())\n", " weights = coefs[\"coefficients\"]\n", " offsets = coefs[\"offsets\"]\n", "\n", " ref_slice = slice(i, i + 1, 1)\n", " off_slices = [\n", " fd.diff.Diff._shift_slice(..., ref_slice, offsets[k], npts)\n", " for k in range(len(offsets))\n", " ]\n", " fd.diff.Diff._apply_to_array(\n", " ..., yd, array, weights, off_slices, ref_slice, dim\n", " )\n", "\n", " else:\n", " scheme = \"center\"\n", " weights = coefs[scheme][\"coefficients\"]\n", " offsets = coefs[scheme][\"offsets\"]\n", "\n", " num_bndry_points = len(weights) // 2\n", "\n", " ref_slice = slice(num_bndry_points, npts - num_bndry_points, 1)\n", " off_slices = [\n", " fd.diff.Diff._shift_slice(..., ref_slice, offsets[k], npts)\n", " for k in range(len(offsets))\n", " ]\n", "\n", " fd.diff.Diff._apply_to_array(\n", " ..., yd, array, weights, off_slices, ref_slice, dim\n", " )\n", "\n", " scheme = \"forward\"\n", " weights = coefs[scheme][\"coefficients\"]\n", " offsets = coefs[scheme][\"offsets\"]\n", "\n", " ref_slice = slice(0, num_bndry_points, 1)\n", " off_slices = [\n", " fd.diff.Diff._shift_slice(..., ref_slice, offsets[k], npts)\n", " for k in range(len(offsets))\n", " ]\n", "\n", " fd.diff.Diff._apply_to_array(\n", " ..., yd, array, weights, off_slices, ref_slice, dim\n", " )\n", "\n", " scheme = \"backward\"\n", " weights = coefs[scheme][\"coefficients\"]\n", " offsets = coefs[scheme][\"offsets\"]\n", "\n", " ref_slice = slice(npts - num_bndry_points, npts, 1)\n", " off_slices = [\n", " fd.diff.Diff._shift_slice(..., ref_slice, offsets[k], npts)\n", " for k in range(len(offsets))\n", " ]\n", "\n", " fd.diff.Diff._apply_to_array(\n", " ..., yd, array, weights, off_slices, ref_slice, dim\n", " )\n", "\n", " h_inv = 1.0 / h**order\n", "\n", " return yd * h_inv" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "def diff_c(self, direction, order=1, acc=None):\n", " direction_idx = dfu.axesdict[direction]\n", "\n", " # If there are no neighbouring cells in the specified direction, zero\n", " # field is returned.\n", "\n", " # ASSUME that needs more cells than curvature!\n", " if self.mesh.n[direction_idx] <= order:\n", " return self.zero\n", "\n", " # Create FinDiff object.\n", " derivative_array = fd_diff_edit_c(\n", " self.array, self.mesh.cell[direction_idx], order, direction_idx, acc=acc\n", " )\n", "\n", " return self.__class__(\n", " self.mesh,\n", " nvdim=self.nvdim,\n", " value=derivative_array,\n", " vdims=self.vdims,\n", " )" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[34mTesting diff_c...\u001b[0m\n", "Test 1 cell(s) in z - order 1 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 2 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 4 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 3 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 5 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 3 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 4 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 3 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 4 \u001b[32mSuccess\u001b[0m\n", "\u001b[34mSuccess rate: 24/24\u001b[0m\n" ] } ], "source": [ "test_function(diff_c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Mixed implementation" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "def diff_d(self, direction, order=1, acc=None):\n", " direction_idx = dfu.axesdict[direction]\n", "\n", " # If there are no neighbouring cells in the specified direction, zero\n", " # field is returned.\n", " if self.mesh.n[direction_idx] <= order:\n", " return self.zero\n", "\n", " padded_array = self.array\n", "\n", " # Only use our implimentation if we have to\n", " if order in (1, 2) and acc is None:\n", " if order == 1:\n", " if self.nvdim == 1:\n", " derivative_array = np.gradient(\n", " padded_array[..., 0],\n", " self.mesh.cell[direction_idx],\n", " axis=direction_idx,\n", " )[..., np.newaxis]\n", " else:\n", " derivative_array = np.gradient(\n", " padded_array, self.mesh.cell[direction_idx], axis=direction_idx\n", " )\n", "\n", " elif order == 2:\n", " derivative_array = np.zeros_like(padded_array)\n", " for i in range(padded_array.shape[direction_idx]):\n", " if i == 0:\n", " i1, i2, i3 = i + 2, i + 1, i\n", " elif i == padded_array.shape[direction_idx] - 1:\n", " i1, i2, i3 = i, i - 1, i - 2\n", " else:\n", " i1, i2, i3 = i + 1, i, i - 1\n", " index1 = dfu.assemble_index(slice(None), 4, {direction_idx: i1})\n", " index2 = dfu.assemble_index(slice(None), 4, {direction_idx: i2})\n", " index3 = dfu.assemble_index(slice(None), 4, {direction_idx: i3})\n", " index = dfu.assemble_index(slice(None), 4, {direction_idx: i})\n", " derivative_array[index] = (\n", " padded_array[index1]\n", " - 2 * padded_array[index2]\n", " + padded_array[index3]\n", " ) / self.mesh.cell[direction_idx] ** 2\n", " else:\n", " if acc is None:\n", " acc = 2\n", " coeffs = fd.coefficients(order, acc=acc)\n", " stencil_len_back = len(coeffs[\"backward\"][\"offsets\"]) - 1\n", " stencil_max_cent = max(coeffs[\"center\"][\"offsets\"]) - 1\n", "\n", " len_needed = stencil_len_back + stencil_max_cent\n", " if self.mesh.n[direction_idx] <= len_needed:\n", " raise ValueError(\n", " f\"The minimum size of the mesh in the direction {direction} \"\n", " f\"is {len_needed+1} for an order order {order} and acc {acc}.\"\n", " )\n", " diff_fd = fd.FinDiff(\n", " direction_idx, self.mesh.cell[direction_idx], order, acc=acc\n", " )\n", " derivative_array = diff_fd(padded_array)\n", "\n", " return self.__class__(\n", " self.mesh, dim=self.nvdim, value=derivative_array, vdims=self.vdims\n", " )" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[34mTesting diff_d...\u001b[0m\n", "Test 1 cell(s) in z - order 1 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 1 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 2 cell(s) in z - order 2 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 2 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 3 cell(s) in z - order 3 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 3 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 4 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 4 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m The minimum size of the mesh in the direction z is 6 for an order order 3 and acc 2.\n", "Test 4 cell(s) in z - order 4 \u001b[33mSuccess with assumption\u001b[0m\n", "Test 5 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 5 cell(s) in z - order 3 \u001b[31mFailed\u001b[0m The minimum size of the mesh in the direction z is 6 for an order order 3 and acc 2.\n", "Test 5 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m The minimum size of the mesh in the direction z is 7 for an order order 4 and acc 2.\n", "Test 6 cell(s) in z - order 1 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 2 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 3 \u001b[32mSuccess\u001b[0m\n", "Test 6 cell(s) in z - order 4 \u001b[31mFailed\u001b[0m The minimum size of the mesh in the direction z is 7 for an order order 4 and acc 2.\n", "\u001b[34mSuccess rate: 20/24\u001b[0m\n" ] } ], "source": [ "test_function(diff_d)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[34mTesting diff_d...\u001b[0m\n", "Test 1 cell(s) in x - order 1 \u001b[31mFailed\u001b[0m Expected 0.22360679774997896, got 0.0\n", "Test 1 cell(s) in x - order 2 \u001b[31mFailed\u001b[0m Expected -0.022360679774997897, got 0.0\n", "Test 1 cell(s) in x - order 3 \u001b[31mFailed\u001b[0m Expected 0.006708203932499369, got 0.0\n", "Test 1 cell(s) in x - order 4 \u001b[31mFailed\u001b[0m Expected -0.0033541019662496844, got 0.0\n", "Test 2 cell(s) in x - order 1 \u001b[32mSuccess\u001b[0m Expected 0.22360679774997896, got 0.23149479148832816\n", "Test 2 cell(s) in x - order 2 \u001b[31mFailed\u001b[0m Expected -0.022360679774997897, got 0.0\n", "Test 2 cell(s) in x - order 3 \u001b[31mFailed\u001b[0m Expected 0.006708203932499369, got 0.0\n", "Test 2 cell(s) in x - order 4 \u001b[31mFailed\u001b[0m Expected -0.0033541019662496844, got 0.0\n", "Test 3 cell(s) in x - order 1 \u001b[31mFailed\u001b[0m Expected 0.22360679774997896, got 0.2393635345818485\n", "Test 3 cell(s) in x - order 2 \u001b[31mFailed\u001b[0m Expected -0.022360679774997897, got -0.02649511442840804\n", "Test 3 cell(s) in x - order 3 \u001b[31mFailed\u001b[0m Expected 0.006708203932499369, got 0.0\n", "Test 3 cell(s) in x - order 4 \u001b[31mFailed\u001b[0m Expected -0.0033541019662496844, got 0.0\n", "Test 4 cell(s) in x - order 1 \u001b[31mFailed\u001b[0m Expected 0.22360679774997896, got 0.20430964368921992\n", "Test 4 cell(s) in x - order 2 \u001b[31mFailed\u001b[0m Expected -0.022360679774997897, got -0.016874949655437347\n", "Test 4 cell(s) in x - order 3 \n", "Test 4 cell(s) in x - order 4 \u001b[31mFailed\u001b[0m Expected -0.0033541019662496844, got 0.0\n", "\u001b[34mSuccess rate: 1/16\u001b[0m\n" ] } ], "source": [ "test_value(diff_d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ndimage implementation" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "from scipy import ndimage" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "p1 = (0.0, 0.0, 0.0)\n", "p2 = (10.0, 10.0, 10.0)\n", "\n", "\n", "def f(pos):\n", " x, y, z = pos\n", " return (x**4, y**4, z**4)\n", "\n", "\n", "mesh = df.Mesh(p1=p1, p2=p2, n=(10, 10, 20), bc=\"xyz\")\n", "field = df.Field(mesh, dim=3, value=f)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-4070., 0., 0.])" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "field.diff(\"x\").array[0, 5, 5]" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [], "source": [ "k = np.zeros((3, 1, 1, 1))\n", "k[0, 0, 0, 0] = 0.5\n", "k[2, 0, 0, 0] = -0.5" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-4070., 0., 0.])" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(\n", " ndimage.convolve(field.array, k, mode=\"wrap\", origin=(0, 0, 0, 0))\n", " / field.mesh.cell[0]\n", ")[0, 5, 5]" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.8.13 ('ubermagdev')", "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.13" }, "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "3ca9094a041cc4b421461943860d4006a32a83ae6de9d82790d0cc597a0ee9b5" } } }, "nbformat": 4, "nbformat_minor": 2 }