{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# libCEED for Python examples\n", "\n", "This is a tutorial to illustrate the main feautures of the Python interface for [libCEED](https://github.com/CEED/libCEED/), the low-level API library for efficient high-order discretization methods developed by the co-design [Center for Efficient Exascale Discretizations](https://ceed.exascaleproject.org/) (CEED) of the [Exascale Computing Project](https://www.exascaleproject.org/) (ECP).\n", "\n", "While libCEED's focus is on high-order finite/spectral element method implementations, the approach is mostly algebraic and thus applicable to other discretizations in factored form, as explained in the [user manual](https://libceed.readthedocs.io/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setting up libCEED for Python\n", "\n", "Install libCEED for Python by running" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "! python -m pip install libceed" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CeedVector\n", "\n", "Here we show some basic examples to illustrate the `libceed.Vector` class. In libCEED, CeedVectors constitute the main data structure and serve as input/output for `libceed.Operator`. \n", "\n", "We illustrate the simple creation of a `libceed.Vector`, how to specify its size, and how to read or manipulate its data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import libceed\n", "\n", "ceed = libceed.Ceed()\n", "\n", "n = 10\n", "x = ceed.Vector(n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The size of the `CeedVector` can also be specified as " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = ceed.Vector(size=10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* In the following example, we associate the data stored in a `libceed.Vector` with a `numpy.array` and use it to set and read the `libceed.Vector`'s data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "ceed = libceed.Ceed()\n", "x = ceed.Vector(size=3)\n", "\n", "a = np.arange(1, 4, dtype=\"float64\")\n", "x.set_array(a, cmode=libceed.USE_POINTER)\n", "\n", "with x.array_read() as b:\n", " print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* In the following example, we set all entries to the same value and then visualize the `libceed.Vector`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ceed = libceed.Ceed()\n", "x = ceed.Vector(size=5)\n", "\n", "x.set_value(10)\n", "\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* In the following example, we set one vector from the array of another vector" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ceed = libceed.Ceed()\n", "n = 10\n", "\n", "x = ceed.Vector(n)\n", "y = ceed.Vector(n)\n", "\n", "a = np.arange(1, 1 + n, dtype=\"float64\")\n", "x.set_array(a, cmode=libceed.USE_POINTER)\n", "\n", "with x.array() as x_array:\n", " y.set_array(x_array, cmode=libceed.USE_POINTER)\n", "\n", "with y.array_read() as y_array:\n", " print(y_array)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* In the following example, we access and modify only one entry of the `libceed.Vector`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "n = 10\n", "\n", "x = ceed.Vector(n)\n", "a = np.zeros(n, dtype=\"float64\")\n", "x.set_array(a, cmode=libceed.USE_POINTER)\n", "\n", "with x.array() as b:\n", " b[3] = -3.14;\n", "a[3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* In the following example, we compute the $L_1$, $L_2$ (default), and $L_{\\infty}$ norms of a `libceed.Vector` (keeping in mind that these are local norm computations; not accurate for parallel executions with no reductions)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "n = 10\n", "x = ceed.Vector(n)\n", "\n", "a = np.arange(0, n, dtype=\"float64\")\n", "for i in range(n):\n", " if (i % 2 == 0):\n", " a[i] *= -1\n", "x.set_array(a, cmode=libceed.USE_POINTER)\n", "\n", "norm_1 = x.norm(normtype=libceed.NORM_1)\n", "print(norm_1)\n", "\n", "norm_2 = x.norm()\n", "print(norm_2)\n", "\n", "norm_max = x.norm(normtype=libceed.NORM_MAX)\n", "print(norm_max)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* If you have installed libCEED with CUDA support and Numba, you can use device memory in your `libceed.Vector`s. In the following example, we create a `libceed.Vector` with a libCEED contex that supports CUDA, associate the data stored in a CeedVector with a `numpy.array`, and get a Numba `DeviceNDArray` containing the data on the device." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ceed_gpu = libceed.Ceed('/gpu/cuda')\n", "\n", "n = 10\n", "x = ceed_gpu.Vector(n)\n", "\n", "a = np.arange(1, 1 + n, dtype=\"float64\")\n", "x.set_array(a, cmode=libceed.USE_POINTER)\n", "\n", "with x.array_read(memtype=libceed.MEM_DEVICE) as device_array:\n", " print(device_array)" ] } ], "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": 4 }