diff --git a/dev/numba-value-norm.ipynb b/dev/numba-value-norm.ipynb new file mode 100644 index 000000000..f88dcbab5 --- /dev/null +++ b/dev/numba-value-norm.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "7e5e3806-3107-4b4c-9f4b-5218e0ddad1e", + "metadata": {}, + "outputs": [], + "source": [ + "import discretisedfield as df" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "216973f5-957a-46a4-b47f-8220554124c6", + "metadata": {}, + "outputs": [], + "source": [ + "p1 = (-1000e-9, -1000e-9, 0.0)\n", + "p2 = (1000e-9, 1000e-9, 1e-9)\n", + "cell = (1e-9, 1e-9, 1e-9)\n", + "\n", + "mesh = df.Mesh(p1=p1, p2=p2, cell=cell)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "acfbaf6b-22eb-4a6b-b0f9-70819fca0ba7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(2000, 2000, 1)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mesh.n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "04e43e00-8951-4555-b2da-fe0de324b3f8", + "metadata": {}, + "outputs": [], + "source": [ + "def disk(point, res):\n", + " x, y, z = point\n", + " if x**2 + y**2 <= (1000e-9) ** 2:\n", + " res[:] = 1.0\n", + " else:\n", + " res[:] = 0.0\n", + "\n", + "\n", + "def M_init(point, res):\n", + " x, y, z = point\n", + " if x**2 + y**2 <= (500e-9) ** 2:\n", + " res[:] = [0.0, 0.0, -1.0]\n", + " else:\n", + " res[:] = [0.0, 0.0, 1.0]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ad6e5fee-aaa0-4610-af5a-11352ae6d820", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 2.09 s, sys: 204 ms, total: 2.29 s\n", + "Wall time: 2.32 s\n" + ] + } + ], + "source": [ + "%%time\n", + "field = df.Field(mesh=mesh, dim=3, value=M_init, norm=disk)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "892d9150-227d-4809-819c-09bda5a46c14", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/swapneel/opt/miniconda3/envs/ubermagdev/lib/python3.8/site-packages/matplotlib/quiver.py:651: RuntimeWarning: divide by zero encountered in double_scalars\n", + " length = a * (widthu_per_lenu / (self.scale * self.width))\n", + "/Users/swapneel/opt/miniconda3/envs/ubermagdev/lib/python3.8/site-packages/matplotlib/quiver.py:651: RuntimeWarning: invalid value encountered in multiply\n", + " length = a * (widthu_per_lenu / (self.scale * self.width))\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "field.plane(\"z\").mpl()" + ] + } + ], + "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.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/discretisedfield/field.py b/discretisedfield/field.py index f3e0b50dc..eb63e9581 100644 --- a/discretisedfield/field.py +++ b/discretisedfield/field.py @@ -4,6 +4,7 @@ import pathlib import warnings +import numba as nb import numpy as np import ubermagutil.typesystem as ts import xarray as xr @@ -335,8 +336,16 @@ def value(self): @value.setter def value(self, val): - self._value = val - self.array = _as_array(val, self.mesh, self.dim, dtype=self.dtype) + if callable(val): + nb_value_func = nb.guvectorize( + [(nb.float64[:], nb.float64[:])], "(n)->(n)", nopython=True + )(val) + nb_value_array = nb_value_func(self.coordinate_field(self.mesh).array) + self._value = nb_value_array + self.array = nb_value_array + else: + self._value = val + self.array = _as_array(val, self.mesh, self.dim, dtype=self.dtype) @property def components(self): @@ -499,7 +508,7 @@ def norm(self): if self.dim == 1: res = abs(self.value) else: - res = np.linalg.norm(self.array, axis=-1)[..., np.newaxis] + res = np.linalg.norm(self.array, axis=-1, keepdims=True) return self.__class__(self.mesh, dim=1, value=res, units=self.units) @@ -516,7 +525,16 @@ def norm(self, val): out=np.zeros_like(self.array), where=self.norm.array != 0.0, ) - self.array *= _as_array(val, self.mesh, dim=1, dtype=None) + + if callable(val): + nb_norm_func = nb.guvectorize( + [(nb.float64[:], nb.float64[:])], "(n)->(n)", nopython=True + )(val) + nb_norm_array = nb_norm_func(self.coordinate_field(self.mesh).array) + + self.array *= nb_norm_array + else: + self.array *= _as_array(val, self.mesh, dim=1, dtype=None) def __abs__(self): """Field norm.