<commit_before>{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tutorial describes one particular intermediate representation used by the Devito Compiler: the Iteration/Expression Tree (IET), a special type of Abstract Syntax Tree.\n",
    "\n",
    "# Part I - Top Down\n",
    "\n",
    "Here, we investigate the IET of a simple ``Operator``.\n",
    "\n",
    "First, let's describe a $domain$, and a $Function$ that will allow us to specify how such a domain gets modified. In particular, we will look at functions that change through $time$. \n",
    "\n",
    "Thus we need a function object with which we can build a timestepping scheme. For this purpose Devito provides so-called TimeData objects that encapsulate functions that are differentiable in space and time, which are derived from basic $SymPy$ functions. \n",
    "\n",
    "With this we can derive symbolic expressions for the backward derivatives in space directly via the `u.dxl` and `u.dyl` shorthand expressions (the l indicates \"left\" or backward differences) and the shorthand notation `u.dt` provided by TimeData objects to derive the forward derivative in time.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Data([[[0., 0., 0.],\n",
       "       [0., 0., 0.],\n",
       "       [0., 0., 0.]],\n",
       "\n",
       "      [[0., 0., 0.],\n",
       "       [0., 0., 0.],\n",
       "       [0., 0., 0.]]], dtype=float32)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from devito import Eq, Grid, TimeFunction, Operator\n",
    "\n",
    "grid = Grid(shape=(3, 3))\n",
    "u = TimeFunction(name='u', grid=grid)\n",
    "u.data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here, we have just declared a two-dimensional Domain with three coordinates at each dimension ($x$ and $y$). Each coordinate of such a discrete space will be holding a $real~value$.\n",
    "\n",
    "As we can see, we can always access the values at each coordinate of the Domain. At this point, no modifications have been done to it yet. `u.data` give as a quick access over the values holded by each cell of such a Domain. `u.data[0]` holds the values in the grid at the \"current\" iteration time, given a time-step to be considered, whereas `u.data[1]` holds the values of `u` for the \"current+1\" time-step.\n",
    "\n",
    "We can now create an `Operator` that will perform modifications onto our Domain according to $differential~ equations$ through a computational stencil. \n",
    "It means that those differential equations will be translated into finite differences that will be used to update the values at each coordinate of the space.\n",
    "Such finite differences, or `expressions`, will be applied for specific ranges of `iterations` over the Domain. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Eq(u(t + dt, x, y), u(t, x, y) + 1)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eq = Eq(u.forward, u+1)\n",
    "op = Operator(eq)\n",
    "op.args['expressions']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For instance, the particular `Equation` object above allows us say that, at each time step, `1` will be added to every position of the domain.\n",
    "\n",
    "Let's take a look at the $kernel$ that will be used to compute how this equation alters the domain."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#define _POSIX_C_SOURCE 200809L\n",
      "#include \"stdlib.h\"\n",
      "#include \"math.h\"\n",
      "#include \"sys/time.h\"\n",
      "#include \"xmmintrin.h\"\n",
      "#include \"pmmintrin.h\"\n",
      "\n",
      "struct Profiler\n",
      "{\n",
      "  double section0;\n",
      "} ;\n",
      "\n",
      "\n",
      "int Kernel(float *restrict u_vec, const int time_M, const int time_m, void *_timers, const int x_M, const int x_m, const int x_size, const int y_M, const int y_m, const int y_size)\n",
      "{\n",
      "  float (*restrict u)[x_size + 1 + 1][y_size + 1 + 1] __attribute__((aligned(64))) = (float (*)[x_size + 1 + 1][y_size + 1 + 1]) u_vec;\n",
      "  struct Profiler *timers = (struct Profiler*) _timers;\n",
      "  /* Flush denormal numbers to zero in hardware */\n",
      "  _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);\n",
      "  _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);\n",
      "  for (int time = time_m, t0 = (time)%(2), t1 = (time + 1)%(2); time <= time_M; time += 1, t0 = (time)%(2), t1 = (time + 1)%(2))\n",
      "  {\n",
      "    struct timeval start_section0, end_section0;\n",
      "    gettimeofday(&start_section0, NULL);\n",
      "    for (int x = x_m; x <= x_M; x += 1)\n",
      "    {\n",
      "      #pragma omp simd\n",
      "      for (int y = y_m; y <= y_M; y += 1)\n",
      "      {\n",
      "        u[t1][x + 1][y + 1] = u[t0][x + 1][y + 1] + 1;\n",
      "      }\n",
      "    }\n",
      "    gettimeofday(&end_section0, NULL);\n",
      "    timers->section0 += (double)(end_section0.tv_sec-start_section0.tv_sec)+(double)(end_section0.tv_usec-start_section0.tv_usec)/1000000;\n",
      "  }\n",
      "  return 0;\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "print(op)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we have an `Operator` set up, we are ready to update our domain throught the apply method. Without additional parameters specified, the `Operator` runs on the same data objects used to build it. It is important to stress that, regarded that this operator is buffered by a `TimeFunction`, the maximum iteration point along the time dimension must be explicitly specified (otherwise, the `Operator` wouldn't know how many iterations to run).\n",
    "\n",
    "Notice that no modifications to the Domain have been done so far. To verify that, query for `u.data`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "CustomCompiler: compiled `/tmp/devito-jitcache-uid1000/e1da8656f159ebd000fbe95ce2da53c72ac62b84.c` [0.24 s]\n",
      "=========================================================================================\n",
      "=========================================================================================\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Data([[[2., 2., 2.],\n",
       "       [2., 2., 2.],\n",
       "       [2., 2., 2.]],\n",
       "\n",
       "      [[3., 3., 3.],\n",
       "       [3., 3., 3.],\n",
       "       [3., 3., 3.]]], dtype=float32)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "op.apply(time=2)\n",
    "u.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.5"
  }<commit_msg>includes text up to query for second TimeFunction<commit_after>{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tutorial describes one particular intermediate representation used by the Devito Compiler: the Iteration/Expression Tree (IET), a special type of Abstract Syntax Tree.\n",
    "\n",
    "# Part I - Top Down\n",
    "\n",
    "Here, we investigate the IET of a simple ``Operator``.\n",
    "\n",
    "First, let's describe a $domain$, and a $Function$ that will allow us to specify how such a domain gets modified. In particular, we will look at functions that change through $time$. \n",
    "\n",
    "Thus we need a function object with which we can build a timestepping scheme. For this purpose Devito provides so-called TimeData objects that encapsulate functions that are differentiable in space and time, which are derived from basic $SymPy$ functions. \n",
    "\n",
    "With this we can derive symbolic expressions for the backward derivatives in space directly via the `u.dxl` and `u.dyl` shorthand expressions (the l indicates \"left\" or backward differences) and the shorthand notation `u.dt` provided by TimeData objects to derive the forward derivative in time.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Data([[[0., 0., 0.],\n",
       "       [0., 0., 0.],\n",
       "       [0., 0., 0.]],\n",
       "\n",
       "      [[0., 0., 0.],\n",
       "       [0., 0., 0.],\n",
       "       [0., 0., 0.]]], dtype=float32)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from devito import Eq, Grid, TimeFunction, Operator\n",
    "\n",
    "grid = Grid(shape=(3, 3))\n",
    "u = TimeFunction(name='u', grid=grid)\n",
    "u.data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here, we have just declared a two-dimensional Domain with three coordinates at each dimension ($x$ and $y$). Each coordinate of such a discrete space will be holding a $real~value$.\n",
    "\n",
    "As we can see, we can always access the values at each coordinate of the Domain. At this point, no modifications have been done to it yet. `u.data` give as a quick access over the values holded by each cell of such a Domain. `u.data[0]` holds the values in the grid at the \"current\" iteration time, given a time-step to be considered, whereas `u.data[1]` holds the values of `u` for the \"current+1\" time-step.\n",
    "\n",
    "We can now create an `Operator` that will perform modifications onto our Domain according to $differential~ equations$ through a computational stencil. \n",
    "It means that those differential equations will be translated into finite differences that will be used to update the values at each coordinate of the space.\n",
    "Such finite differences, or `expressions`, will be applied for specific ranges of `iterations` over the Domain. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Eq(u(t + dt, x, y), u(t, x, y) + 1)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eq = Eq(u.forward, u+1)\n",
    "op = Operator(eq)\n",
    "op.args['expressions']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For instance, the particular `Equation` object above allows us say that, at each time step, `1` will be added to every position of the domain.\n",
    "\n",
    "Let's take a look at the $kernel$ that will be used to compute how this equation alters the domain."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#define _POSIX_C_SOURCE 200809L\n",
      "#include \"stdlib.h\"\n",
      "#include \"math.h\"\n",
      "#include \"sys/time.h\"\n",
      "#include \"xmmintrin.h\"\n",
      "#include \"pmmintrin.h\"\n",
      "\n",
      "struct Profiler\n",
      "{\n",
      "  double section0;\n",
      "} ;\n",
      "\n",
      "\n",
      "int Kernel(float *restrict u_vec, const int time_M, const int time_m, void *_timers, const int x_M, const int x_m, const int x_size, const int y_M, const int y_m, const int y_size)\n",
      "{\n",
      "  float (*restrict u)[x_size + 1 + 1][y_size + 1 + 1] __attribute__((aligned(64))) = (float (*)[x_size + 1 + 1][y_size + 1 + 1]) u_vec;\n",
      "  struct Profiler *timers = (struct Profiler*) _timers;\n",
      "  /* Flush denormal numbers to zero in hardware */\n",
      "  _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);\n",
      "  _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);\n",
      "  for (int time = time_m, t0 = (time)%(2), t1 = (time + 1)%(2); time <= time_M; time += 1, t0 = (time)%(2), t1 = (time + 1)%(2))\n",
      "  {\n",
      "    struct timeval start_section0, end_section0;\n",
      "    gettimeofday(&start_section0, NULL);\n",
      "    for (int x = x_m; x <= x_M; x += 1)\n",
      "    {\n",
      "      #pragma omp simd\n",
      "      for (int y = y_m; y <= y_M; y += 1)\n",
      "      {\n",
      "        u[t1][x + 1][y + 1] = u[t0][x + 1][y + 1] + 1;\n",
      "      }\n",
      "    }\n",
      "    gettimeofday(&end_section0, NULL);\n",
      "    timers->section0 += (double)(end_section0.tv_sec-start_section0.tv_sec)+(double)(end_section0.tv_usec-start_section0.tv_usec)/1000000;\n",
      "  }\n",
      "  return 0;\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "print(op)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we have an `Operator` set up, we are ready to update our domain throught the apply method. Without additional parameters specified, the `Operator` runs on the same data objects used to build it. It is important to stress that, regarded that this operator is buffered by a `TimeFunction`, the maximum iteration point along the time dimension must be explicitly specified (otherwise, the `Operator` wouldn't know how many iterations to run).\n",
    "\n",
    "Notice that no modifications to the Domain have been done so far. To verify that, query for `u.data`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "CustomCompiler: compiled `/tmp/devito-jitcache-uid1000/e1da8656f159ebd000fbe95ce2da53c72ac62b84.c` [0.24 s]\n",
      "=========================================================================================\n",
      "=========================================================================================\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Data([[[2., 2., 2.],\n",
       "       [2., 2., 2.],\n",
       "       [2., 2., 2.]],\n",
       "\n",
       "      [[3., 3., 3.],\n",
       "       [3., 3., 3.],\n",
       "       [3., 3., 3.]]], dtype=float32)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "op.apply(time=2)\n",
    "u.data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is the first time that we are invoking the method `apply` from `Operator`. Therefore, the $kernel$ that we saw will get written in a `.c` file, and compiled into a `.so` lib if `DEVITO_BACKEND` is set to `core`.\n",
    "\n",
    "Then, as no key-value parameters are specified, the `Operator` runs with its default arguments, namely `u=u, x_m=0, x_M=2, y_m=0, y_M=2,` and `time_m=0`. The subindexes `m` and `M` stands for the minimum and the maximum at those specific Dimensions, respectivelly. Thus `time_M` will be set to `2`, here.\n",
    "\n",
    "At this point, the same `Operator` can be used for a completely different run. Let's create another `TimeFunction` for governing a similar $domain$. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.5"
  }
{'fraction_non_alphanumeric': 0.1896614488532945, 'fraction_numerical': 0.018080330057031913, 'mean_word_length': 2.5996942563878576, 'pattern_counts': {'":': 151, '<': 9, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1530421', 'n_tokens_mistral': 5812, 'n_tokens_neox': 5511, 'n_words': 1720}