{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "The first compilation pass is named _lowering_, and three main tasks are carried out: _indexification_, _substitution_, and _domain-alignment_. In this notebook, we will explore the Indexification step.\n", "\n", "\n", "# Indexification\n", "\n", "The _indexification_ consists of converting Functions into Indexeds, that is actual array accesses. An `Indexed` always keeps a reference to its originating `Function`. For instance, all accesses to `u` such as `u[t, x + 1]` and `u[t + 1, x − 2]` would store a pointer to the same, user-defined `Function` _u(t, x)_. This metadata is exploited throughout the various compilation passes. \n", "\n", "To see this, let's create a `TimeFunction` named `u`." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "u(time, x)\n" ] } ], "source": [ "from devito import Grid, TimeFunction\n", "u = TimeFunction(name='u', grid=Grid((3,)), save=1)\n", "print(u)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that `u` has one temporal dimension and one spatial dimension, that we will call `time` and `x` here, respectively." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(time, x)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "time, x = u.dimensions\n", "time, x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions (of type `Function`, `TimeFunction` and `SparseFunction`) can be indexified in two equivalent ways, either via the .indexify() method, as illustrated below, or via explicit indexing, as typically done in user code." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "u[time, x]\n" ] } ], "source": [ "u_i = u.indexify() # For more details about the method `indexify`, see `devito/symbolics/manipulation.py`\n", "print(u_i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, dimensions are interpreted as indices." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u_i.indices == u.dimensions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The explicit indexing mode is when you write" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "a = u[time,x+1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and you get exactly (representation shown below)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "u[time, x + 1]\n" ] } ], "source": [ "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ie, this is totally equivalent to indexify. Another example, you can write" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "b = u[time+1,x-2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and you get\n", "\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "u[time + 1, x - 2]\n" ] } ], "source": [ "print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Clearly, we now have that" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.indices == b.indices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Thus" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a == b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However, we can verify that these accesses still point to the very same `TimeFunction` object." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.function is b.function " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note also that there is no `data` associated with `Indexed` objects." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "devito.types.basic.Indexed" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(u_i)\n", "# u_i.data # This should return an error!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `data` representing the grid is accessed through the `Function` that the indices point to." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Data([[0., 0., 0.]], dtype=float32)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "u_i.function.data" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 2 }