diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..7266c6d7 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,148 @@ +ARG BASE=mcr.microsoft.com/devcontainers/base:ubuntu-20.04 + +ARG LLVM_VERSION=15.0.7 +ARG HETEROCL_VERSION=69181b080c8cf7d9fab0a6b2ae3511923274b32e +ARG HCL_DIALECT_VERSION=f2f5e43a93173f9a86671c8f5004d5fb21cb329b + +FROM $BASE AS build + +ARG LLVM_VERSION +ARG HETEROCL_VERSION +ARG HCL_DIALECT_VERSION +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && \ + apt-get install -y \ + apt-transport-https \ + ca-certificates \ + g++ \ + gcc \ + git \ + gnupg \ + make \ + python3-dev \ + python3-pip \ + python3-venv \ + python3-virtualenv \ + software-properties-common \ + wget \ + xz-utils + +RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | apt-key add - && \ + apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main' && \ + apt-get update -y && \ + apt-get install -y cmake + +RUN pip install -U \ + pip \ + build \ + patchelf \ + auditwheel + +# Download LLVM +ARG LLVM_DIR=/opt/llvm-project +ADD "https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVM_VERSION/llvm-project-$LLVM_VERSION.src.tar.xz" /tmp/ +RUN cd /tmp && \ + tar -xf llvm-project-$LLVM_VERSION.src.tar.xz && \ + mv llvm-project-$LLVM_VERSION.src $LLVM_DIR && \ + rm llvm-project-$LLVM_VERSION.src.tar.xz + +# Build LLVM & MLIR +WORKDIR $LLVM_DIR/build +RUN pip install -r ../mlir/python/requirements.txt +RUN cmake ../llvm \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_PROJECTS=mlir \ + -DLLVM_TARGETS_TO_BUILD=Native \ + -DLLVM_ENABLE_ASSERTIONS=ON \ + -DLLVM_INSTALL_UTILS=ON \ + -DMLIR_ENABLE_BINDINGS_PYTHON=ON \ + && \ + make -j`nproc` + +# Download HeteroCL +ARG HETEROCL_DIR=/opt/heterocl +ARG HCL_DIALECT_DIR=$HETEROCL_DIR/hcl-dialect +RUN git clone https://github.com/cornell-zhang/heterocl.git $HETEROCL_DIR && \ + cd $HETEROCL_DIR && \ + git checkout $HETEROCL_VERSION +RUN git clone https://github.com/cornell-zhang/hcl-dialect.git $HCL_DIALECT_DIR && \ + cd $HCL_DIALECT_DIR && \ + git checkout $HCL_DIALECT_VERSION + +# Build hcl-dialect +WORKDIR $HCL_DIALECT_DIR/build +RUN cmake .. \ + -DMLIR_DIR=$LLVM_DIR/build/lib/cmake/mlir \ + -DLLVM_EXTERNAL_LIT=$LLVM_DIR/build/bin/llvm-lit \ + -DPYTHON_BINDING=ON \ + -DOPENSCOP=OFF \ + && \ + make -j`nproc` + +RUN pip install hatch && \ + mkdir -p /opt/wheelhouse + +# Package hcl-dialect +WORKDIR $HCL_DIALECT_DIR/build/tools/hcl/python_packages/hcl_core +RUN rm setup.py && \ + cat < pyproject.toml +[project] +name = "hcl_mlir" +requires-python = ">= 3.6" +version = "0.1" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build] +ignore-vcs = true + +[tool.hatch.build.targets.wheel] +pure_python = false +packages = ["hcl_mlir"] +EOF +RUN hatch build && \ + mv dist/*.whl /opt/wheelhouse + +# Package HeteroCL +WORKDIR $HETEROCL_DIR +RUN rm setup.py && \ + cat < pyproject.toml +[project] +name = "heterocl" +requires-python = ">= 3.6" +version = "0.5" +dynamic = ["dependencies"] + +[build-system] +requires = ["hatchling", "hatch-requirements-txt"] +build-backend = "hatchling.build" + +[tool.hatch.build] +ignore-vcs = true + +[tool.hatch.build.targets.wheel] +pure_python = false +packages = ["heterocl"] + +[tool.hatch.metadata.hooks.requirements_txt] +files = ["requirements.txt"] +EOF +RUN hatch build && \ + mv dist/*.whl /opt/wheelhouse + + +FROM $BASE + +ARG DEBIAN_FRONTEND=noninteractive + +COPY --from=build /opt/wheelhouse /opt/wheelhouse + +RUN apt-get update && \ + apt-get install -y \ + python3-pip \ + && \ + pip install attrs /opt/wheelhouse/*.whl && \ + rm -r /var/lib/apt/lists/* /opt/wheelhouse diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..2d9f535d --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,24 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/miniconda +{ + "name": "Ubuntu", + "build": { + "context": "..", + "dockerfile": "Dockerfile" + } + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "python --version", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/examples/odp2_simple_example.ipynb b/examples/odp2_simple_example.ipynb new file mode 100644 index 00000000..5d61f113 --- /dev/null +++ b/examples/odp2_simple_example.ipynb @@ -0,0 +1,276 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "# odp2: Simple Backward Reachability Examples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from math import pi\n", + "\n", + "import numpy as np\n", + "from ipywidgets import interact, fixed\n", + "import heterocl as hcl\n", + "\n", + "from odp2.model import Model\n", + "from odp2.shapes import *\n", + "from odp2.solver import HJSolver\n", + "from odp2.plot import hj_plot, xy_plot" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class SVEA5D(Model):\n", + " \"\"\"\n", + " Model for Small Vehicle for Autonomy (SVEA), our hardware platform.\n", + " \n", + " The dynamics are as follows:\n", + " \n", + " x_dot = v * cos(yaw) + d_1\n", + " y_dot = v * sin(yaw) + d_2\n", + " yaw_dot = (v * tan(delta))/L + d3\n", + " delta_dot = u1 + d4\n", + " vel_dot = u2 + d5\n", + " \"\"\"\n", + "\n", + " state_dims = 5\n", + " ctrl_dims = 2\n", + " dstb_dims = state_dims\n", + "\n", + " wheelbase = 0.32\n", + "\n", + " X, Y, YAW, DELTA, VEL = range(state_dims)\n", + " STEERING, ACCELERATION = range(ctrl_dims)\n", + "\n", + " def __init__(self, ctrl_range, dstb_range, mode='reach') -> None:\n", + "\n", + " self.ctrl_range = np.asarray(ctrl_range)\n", + " assert self.ctrl_range.shape[1] == self.ctrl_dims\n", + "\n", + " self.dstb_range = np.asarray(dstb_range)\n", + " assert self.dstb_range.shape[1] == self.dstb_dims\n", + "\n", + " modes = {'reach': {\"uMode\": \"min\", \"dMode\": \"max\"},\n", + " 'avoid': {\"uMode\": \"max\", \"dMode\": \"min\"}}\n", + " self.mode = modes[mode]\n", + "\n", + " def dynamics(self, dx, t, x, u, d):\n", + "\n", + " # x_dot = v * cos(yaw) + d_1\n", + " dx[self.X] = (x[self.VEL] * hcl.cos(x[self.YAW]) \n", + " + d[self.X])\n", + "\n", + " # y_dot = v * sin(yaw) + d_2\n", + " dx[self.Y] = (x[self.VEL] * hcl.sin(x[self.YAW])\n", + " + d[self.Y])\n", + "\n", + " # yaw_dot = (v * tan(delta))/L + d3\n", + " hcl_tan = lambda a: hcl.sin(a) / hcl.cos(a)\n", + " dx[self.YAW] = (x[self.VEL] * hcl_tan(x[self.DELTA])/self.wheelbase\n", + " + d[self.YAW])\n", + "\n", + " # delta_dot = u1 + d4\n", + " dx[self.DELTA] = u[self.STEERING] + d[self.DELTA]\n", + "\n", + " # vel_dot = u2 + d5\n", + " dx[self.VEL] = u[self.ACCELERATION] + d[self.VEL]\n", + "\n", + " def opt_ctrl(self, u, dv, t, x):\n", + "\n", + " uMin, uMax = self.ctrl_range\n", + " \n", + " if self.mode['uMode'] == \"max\":\n", + " # Steering\n", + " with hcl.if_(0 <= x[self.VEL]):\n", + " with hcl.if_(0 <= dv[self.YAW]):\n", + " u[self.STEERING] = uMax[self.STEERING]\n", + " with hcl.else_():\n", + " u[self.STEERING] = uMin[self.STEERING]\n", + " with hcl.else_():\n", + " with hcl.if_(0 <= dv[self.YAW]):\n", + " u[self.STEERING] = uMin[self.STEERING]\n", + " with hcl.else_():\n", + " u[self.STEERING] = uMax[self.STEERING]\n", + " # Velocity\n", + " with hcl.if_(0 <= dv[self.VEL]):\n", + " u[self.ACCELERATION] = uMax[self.ACCELERATION]\n", + " with hcl.else_():\n", + " u[self.ACCELERATION] = uMin[self.ACCELERATION] \n", + " else:\n", + " # Steering\n", + " with hcl.if_(0 <= x[self.VEL]):\n", + " with hcl.if_(0 <= dv[self.YAW]):\n", + " u[self.STEERING] = uMin[self.STEERING]\n", + " with hcl.else_():\n", + " u[self.STEERING] = uMax[self.STEERING]\n", + " with hcl.else_():\n", + " with hcl.if_(0 <= dv[self.YAW]):\n", + " u[self.STEERING] = uMax[self.STEERING]\n", + " with hcl.else_():\n", + " u[self.STEERING] = uMin[self.STEERING]\n", + " # Velocity\n", + " with hcl.if_(0 <= dv[self.VEL]):\n", + " u[self.ACCELERATION] = uMin[self.ACCELERATION]\n", + " with hcl.else_():\n", + " u[self.ACCELERATION] = uMax[self.ACCELERATION]\n", + "\n", + " def opt_dstb(self, d, dv, t, x):\n", + "\n", + " dMin, dMax = self.dstb_range\n", + "\n", + " for i in range(self.dstb_dims):\n", + " if self.mode['dMode'] == \"max\":\n", + " with hcl.if_(0 <= dv[i]):\n", + " d[i] = dMax[i]\n", + " with hcl.else_():\n", + " d[i] = dMin[i]\n", + " else:\n", + " with hcl.if_(0 <= dv[i]):\n", + " d[i] = dMin[i]\n", + " with hcl.else_():\n", + " d[i] = dMax[i]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Global Parameters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create model object\n", + "model = SVEA5D(ctrl_range=[[-pi/5, -0.5], # uMin\n", + " [+pi/5, +0.5]], # uMax\n", + " dstb_range=[[-0.05, -0.05, -pi/20, 0, 0], # dMin\n", + " [+0.05, +0.05, +pi/20, 0, 0]], # dMax\n", + " mode='reach')\n", + "\n", + "# Create time vector\n", + "horizon = 5.0\n", + "t_step = 0.2\n", + "small_number = 1e-5\n", + "tau = np.arange(start=0,\n", + " stop=horizon + small_number,\n", + " step=t_step)\n", + "\n", + "# Create grid object\n", + "# Dimensions: X, Y, YAW, DELTA, VEL\n", + "grid = Grid([41, 41, 31, 11, 11],\n", + " [+4.0, +4.0, +pi, +pi/5, +1],\n", + " [-4.0, -4.0, -pi, -pi/5, -1],\n", + " [False, False, True, False, False])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Reach Computation Example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Initial value function / Goal region\n", + "goal = cylinder(grid, np.zeros(5), [model.YAW, model.DELTA, model.VEL], 1)\n", + "\n", + "# Extend goal over time axis\n", + "# goal = np.concatenate([goal[..., np.newaxis]] * len(tau), axis=-1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create solver object and compute result\n", + "solver = HJSolver(grid, tau, model, interactive=True)\n", + "result = solver(target=goal, target_mode='min')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "interact(xy_plot,\n", + " val_func = fixed(result),\n", + " grid = fixed(grid),\n", + " heading_idx = (0, grid.shape[model.YAW]-1),\n", + " steer_idx = (0, grid.shape[model.DELTA]-1),\n", + " vel_idx = (0, grid.shape[model.VEL]-1),\n", + " time_idx = (0, len(tau)-1))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "interact(hj_plot,\n", + " val_func = fixed(result),\n", + " grid = fixed(grid),\n", + " steer_idx = (0, grid.shape[model.DELTA]-1),\n", + " vel_idx = (0, grid.shape[model.VEL]-1),\n", + " time_idx = (0, len(tau)-1))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "odp", + "language": "python", + "name": "odp" + }, + "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.16" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/odp_simple_example.ipynb b/examples/odp_simple_example.ipynb new file mode 100644 index 00000000..24f1c657 --- /dev/null +++ b/examples/odp_simple_example.ipynb @@ -0,0 +1,312 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "# odp: Simple Backward Reachability Examples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from math import pi\n", + "\n", + "import numpy as np\n", + "from ipywidgets import interact, fixed\n", + "import heterocl as hcl\n", + "\n", + "from odp.Grid import Grid\n", + "from odp.Shapes import *\n", + "from odp.Plots import PlotOptions\n", + "from odp.solver import HJSolver, computeSpatDerivArray\n", + "\n", + "from dev.utilities import hj_plot, xy_plot" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class SVEA5D:\n", + " \n", + " def __init__(self, x, uMin, uMax, dMin, dMax, uMode=\"min\", dMode=\"max\"):\n", + " \"\"\"Creates a SVEA Car with the following states:\n", + " X position, Y position, speed, heading\n", + " The controls are the acceleration and turn rate (angular speed)\n", + " The disturbances are the noise in the velocity components.\n", + " Args:\n", + " x (list): Initial state.\n", + " uMin (list): Lowerbound of user control.\n", + " uMax (list): Upperbound of user control.\n", + " dMin (list): Lowerbound of disturbance to user control.\n", + " dMax (list): Upperbound of disturbance to user control.\n", + " uMode (str, optional): Accepts either \"min\" or \"max\".\n", + " * \"min\" : have optimal control reach goal\n", + " * \"max\" : have optimal control avoid goal\n", + " Defaults to \"min\".\n", + " dMode (str, optional): Accepts whether \"min\" or \"max\" and should be opposite of uMode.\n", + " Defaults to \"max\".\n", + " \"\"\"\n", + " self.x = x\n", + " self.uMin = uMin\n", + " self.uMax = uMax\n", + " self.dMin = dMin\n", + " self.dMax = dMax\n", + " assert(uMode in [\"min\", \"max\"])\n", + " self.uMode = uMode\n", + " if uMode == \"min\":\n", + " assert(dMode == \"max\")\n", + " else:\n", + " assert(dMode == \"min\")\n", + " self.dMode = dMode\n", + "\n", + " # Wheelbase of SVEA\n", + " self.L = 0.32\n", + " \n", + " def dynamics(self, t, state, uOpt, dOpt):\n", + " x_dot = hcl.scalar(0, \"x_dot\")\n", + " y_dot = hcl.scalar(0, \"y_dot\")\n", + " theta_dot = hcl.scalar(0, \"theta_dot\")\n", + " delta_dot = hcl.scalar(0, \"delta_dot\")\n", + " v_dot = hcl.scalar(0, \"v_dot\")\n", + "\n", + " x_dot[0] = state[4] * hcl.cos(state[2]) + dOpt[0]\n", + " y_dot[0] = state[4] * hcl.sin(state[2]) + dOpt[1]\n", + " theta_dot[0] = (state[4] * hcl.sin(state[3])/hcl.cos(state[3]))/self.L + dOpt[2]\n", + " delta_dot[0] = uOpt[0]\n", + " v_dot[0] = uOpt[1]\n", + "\n", + " return (x_dot[0], y_dot[0] ,theta_dot[0], delta_dot[0], v_dot[0])\n", + " def opt_ctrl(self, t, state, spat_deriv):\n", + " \"\"\"\n", + " :param t: time t\n", + " :param state: tuple of coordinates\n", + " :param spat_deriv: tuple of spatial derivative in all dimensions\n", + " :return:\n", + " \"\"\"\n", + " # System dynamics\n", + " # x_dot = v * cos(theta) + d_1\n", + " # y_dot = v * sin(theta) + d_2\n", + " # theta_dot = (v * tan(delta))/L + d3\n", + " # delta_dot = u1 + d4\n", + " # v_dot = u2 + d5\n", + "\n", + " # Graph takes in 4 possible inputs, by default, for now\n", + " opt_u1 = hcl.scalar(self.uMax[0], \"opt_u1\")\n", + " opt_u2 = hcl.scalar(self.uMax[1], \"opt_u2\")\n", + " # Just create and pass back, even though they're not used\n", + " in3 = hcl.scalar(0, \"in3\")\n", + " in4 = hcl.scalar(0, \"in4\")\n", + " in5 = hcl.scalar(0, \"in5\")\n", + "\n", + " if self.uMode == \"min\":\n", + " with hcl.if_(spat_deriv[3] >= 0):\n", + " opt_u1[0] = self.uMin[0]\n", + " with hcl.if_(spat_deriv[4] >= 0):\n", + " opt_u2[0] = self.uMin[1]\n", + " else:\n", + " with hcl.if_(spat_deriv[3] < 0):\n", + " opt_u1[0] = self.uMin[0]\n", + " with hcl.if_(spat_deriv[4] < 0):\n", + " opt_u2[0] = self.uMin[1]\n", + " # return 3, 4 even if you don't use them\n", + " return (opt_u1[0] ,opt_u2[0], in3, in4, in5)\n", + "\n", + " def opt_dstb(self, t, state, spat_deriv):\n", + " \"\"\"\n", + " :param spat_deriv: tuple of spatial derivative in all dimensions\n", + " :return: a tuple of optimal disturbances\n", + " \"\"\"\n", + " # System dynamics\n", + " # x_dot = v * cos(theta) + d_1\n", + " # y_dot = v * sin(theta) + d_2\n", + " # theta_dot = (v * tan(delta))/L + d_3\n", + " # delta_dot = u1\n", + " # v_dot = u2\n", + "\n", + " # Graph takes in 4 possible inputs, by default, for now\n", + " d1 = hcl.scalar(0, \"d1\")\n", + " d2 = hcl.scalar(0, \"d2\")\n", + " d3 = hcl.scalar(0, \"d3\")\n", + " # Just create and pass back, even though they're not used\n", + " d4 = hcl.scalar(0, \"d4\")\n", + " d5 = hcl.scalar(0, \"d5\")\n", + "\n", + " #with hcl.if_(self.dMode == \"max\"):\n", + " if self.dMode == \"max\":\n", + " with hcl.if_(spat_deriv[0] >= 0):\n", + " d1[0] = self.dMax[0]\n", + " with hcl.elif_(spat_deriv[0] < 0):\n", + " d1[0] = self.dMin[0]\n", + " with hcl.if_(spat_deriv[1] >= 0):\n", + " d2[0] = self.dMax[1]\n", + " with hcl.elif_(spat_deriv[1] < 0):\n", + " d2[0] = self.dMin[1]\n", + " with hcl.if_(spat_deriv[2] >= 0):\n", + " d3[0] = self.dMax[2]\n", + " with hcl.elif_(spat_deriv[2] < 0):\n", + " d3[0] = self.dMin[2]\n", + " else:\n", + " with hcl.if_(spat_deriv[0] >= 0):\n", + " d1[0] = self.dMin[0]\n", + " with hcl.elif_(spat_deriv[0] < 0):\n", + " d1[0] = self.dMax[0]\n", + " with hcl.if_(spat_deriv[1] >= 0):\n", + " d2[0] = self.dMin[1]\n", + " with hcl.elif_(spat_deriv[1] < 0):\n", + " d2[0] = self.dMax[1]\n", + " with hcl.if_(spat_deriv[2] >= 0):\n", + " d3[0] = self.dMin[2]\n", + " with hcl.elif_(spat_deriv[2] < 0):\n", + " d3[0] = self.dMax[2]\n", + "\n", + " return (d1[0], d2[0], d3[0], d4, d5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Global Parameters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X, Y, HEAD, STEER, VEL = 0, 1, 2, 3, 4\n", + "\n", + "# Create model object\n", + "model_settings = {\"x\": [0, 0, 0, 0, 0],\n", + " \"uMin\": [-pi/5, -0.5],\n", + " \"uMax\": [+pi/5, +0.5],\n", + " \"dMin\": [-0.05, -0.05, -pi/20], # disturb x,y,theta\n", + " \"dMax\": [+0.05, +0.05, +pi/20]}\n", + "reach_settings = {\"uMode\": \"min\", \"dMode\": \"max\"}\n", + "reach_settings.update(model_settings)\n", + "my_car = SVEA5D(**reach_settings)\n", + "\n", + "# Create time vector\n", + "horizon = 5.0\n", + "t_step = 0.2\n", + "small_number = 1e-5\n", + "tau = np.arange(start=0,\n", + " stop=horizon + small_number,\n", + " step=t_step)\n", + "\n", + "# Create grid object\n", + "# Dimensions: X, Y, YAW, DELTA, VEL\n", + "g_min = np.array([-4.0, -4.0, -pi, -pi/5, -1])\n", + "g_max = np.array([4.0, 4.0, pi, pi/5, 1])\n", + "g_res = np.array([41, 41, 31, 11, 11])\n", + "num_dims = 5\n", + "periodic_dims = [HEAD]\n", + "g = Grid(g_min, g_max, num_dims, g_res, periodic_dims)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Reach Computation Example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Initial value function / Goal region\n", + "infinite_dims = [HEAD, STEER, VEL]\n", + "Initial_value_f = CylinderShape(g, infinite_dims, np.zeros(5), 1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create solver object and compute result\n", + "compMethods = { \"TargetSetMode\": \"minVWithVInit\"}\n", + "reach_result = HJSolver(my_car, g, Initial_value_f,\n", + " tau, compMethods,\n", + " PlotOptions(do_plot=False, plot_type=\"3d_plot\",\n", + " plotDims=[X, Y, HEAD], slicesCut=[STEER, VEL]), \n", + " saveAllTimeSteps=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "interact(xy_plot,\n", + " val_func = fixed(reach_result),\n", + " g=fixed(g),\n", + " heading_idx = (0, g_res[HEAD]-1),\n", + " steer_idx = (0, g_res[STEER]-1),\n", + " vel_idx = (0, g_res[VEL]-1),\n", + " time_idx = (0, len(tau)-1)) # Note: this is a BACKWARD reachable set, so time_idx is going backwards in time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "interact(hj_plot,\n", + " val_func = fixed(reach_result),\n", + " g = fixed(g),\n", + " steer_idx = (0, g_res[STEER]-1),\n", + " vel_idx = (0, g_res[VEL]-1),\n", + " time_idx = (0, len(tau)-1))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "odp", + "language": "python", + "name": "odp" + }, + "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.16" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/odp/Grid/GridProcessing.py b/odp/Grid/GridProcessing.py deleted file mode 100644 index 5a18155e..00000000 --- a/odp/Grid/GridProcessing.py +++ /dev/null @@ -1,87 +0,0 @@ -import numpy as np -import math - - -class Grid: - def __init__(self, minBounds, maxBounds, dims, pts_each_dim, periodicDims=[]): - """ - - Args: - minBounds (list): The lower bounds of each dimension in the grid - maxBounds (list): The upper bounds of each dimension in the grid - dims (int): The dimension of grid - pts_each_dim (list): The number of points for each dimension in the grid - periodicDim (list, optional): A list of periodic dimentions (0-indexed). Defaults to []. - """ - self.max = maxBounds - self.min = minBounds - self.dims = len(pts_each_dim) - self.pts_each_dim = pts_each_dim - self.pDim = periodicDims - - # Exclude the upper bounds for periodic dimensions is not included - # e.g. [-pi, pi) - for dim in self.pDim: - self.max[dim] = self.min[dim] + \ - (self.max[dim] - self.min[dim]) * \ - (1 - 1/self.pts_each_dim[dim]) - self.dx = (self.max - self.min) / (self.pts_each_dim - 1.0) - - """ - Below is re-shaping the self.vs so that we can make use of broadcasting - self.vs[i] is reshape into (1,1, ... , pts_each_dim[i], ..., 1) such that pts_each_dim[i] is used in ith position - """ - self.vs = [] - """ - self.grid_points is same as self.vs; however, it is not reshaped. - self.grid_points[i] is a numpy array with length pts_each_dim[i] - """ - self.grid_points = [] - for i in range(dims): - tmp = np.linspace(self.min[i], self.max[i], - num=self.pts_each_dim[i]) - broadcast_map = np.ones(self.dims, dtype=int) - broadcast_map[i] = self.pts_each_dim[i] - self.grid_points.append(tmp) - - # in order to add our range of points to our grid - # we need to modify the shape of tmp in order to match - # the size of the grid for one of the axis - tmp = np.reshape(tmp, tuple(broadcast_map)) - self.vs.append(tmp) - - def get_index(self, state): - """ Returns a tuple of the closest index of each state in the grid - - Args: - state (tuple): state of dynamic object - """ - index = [] - - for i, s in enumerate(state): - idx = np.searchsorted(self.grid_points[i], s) - if idx > 0 and ( - idx == len(self.grid_points[i]) - or math.fabs(s - self.grid_points[i][idx - 1]) - < math.fabs(s - self.grid_points[i][idx]) - ): - index.append(idx - 1) - else: - index.append(idx) - - return tuple(index) - - def get_value(self, V, state): - """Obtain the approximate value of a state - - Assumes that the state is within the bounds of the grid - - Args: - V (np.array): value function of solved HJ PDE - state (tuple): state of dynamic object - - Returns: - [float]: V(state) - """ - index = self.get_index(state) - return V[index] diff --git a/odp/Grid/__init__.py b/odp/Grid/__init__.py deleted file mode 100644 index 62995791..00000000 --- a/odp/Grid/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from odp.Grid.GridProcessing import Grid \ No newline at end of file diff --git a/odp/MDP_example/Example_3D.py b/odp/MDP_example/Example_3D.py deleted file mode 100644 index 9671d86e..00000000 --- a/odp/MDP_example/Example_3D.py +++ /dev/null @@ -1,174 +0,0 @@ -import numpy as np -import heterocl as hcl -import os - -#################################################################################################### -# # -# VALUE ITERATION DOCUMENTATION # -# # -# # -# 1. REQUIRED FUNCTIONS # -# The user is required to provide implementations of the following state transition and reward # -# functions: # -# # -# transition(sVals, action, bounds, trans, goal) # -# reward(sVals, action, bounds, goal, trans) # -# # -# 1.1 PARAMETERS # -# sVals: a vector containing state values # -# Format: sVals[0] = state dimension 1, sVals[1] = state dimension 2, ..... # -# action: the action taken from the state specified by sVals # -# Format: user-specified. This is used exclusively in user-defined functions # -# bounds: the lower and upper limits of the state space in each dimension # -# Format: bounds[i,0] is the lower bound of dimension i, bounds[i,1] is the upper # -# trans: a matrix containing the possible successor states when taking action from the # -# state defined by sVals. # -# Format: the size of this vector must be: # -# maximum number of possible transitions x number of state dimensions + 1 # -# The first element of each row of trans will be a probability, and the # -# remaining elements will be the state values of that transition state # -# ex. trans[i, 0] is the probability of making transition i, # -# trans[i, 1] is the first state dimension of transition i # -# goal: a vector defining the goal region # -# Format: user-specified. This is used exclusively in user-defined functions # -# # -# 2. PROBLEM DECLARATION # -# The user is required to provide declarations of a series of variables that define the value # -# iteration problem: # -# # -# 2.1 VARIABLE DECLARATIONS # -# _bounds: a matrix defining the state space boundaries # -# Format: np.array([[iMin, iMax], [jMin, jMax], ... , [nMin, nMax]) # -# _ptsEachDim: the number of grid spaces for each dimension # -# Format: np.array([ptsDimension1, ptsDimension2, ... , ptsDimensionN]) # -# _actions: The set of actions that can be taken from any state # -# Format: np.array([action1, action2, ... , actionN]) # -# _gamma: the discount factor # -# Format: np.array([value]) # -# _epsilon: the convergence number. The algorithm is considered to have converged to the # -# optimal value function when the largest difference between values is less # -# than _epsilon. # -# Format: np.array([value]) # -# _maxIters: the maximum number of iterations that will be performed without convergence # -# Format: np.array([value]) # -# _trans: a placeholder matrix containing possible successor states. # -# Format: np.zeros([maximumNumberOfTransitionStates, 1 + numberOfDimensions]) # -# Usage: The first value of each row is the probability of the transition. The # -# remaining n values of that row are the n values of the state space # -# _useNN: a flag for choosing between Nearest Neighbour and Linear Interpolation modes # -# Format: np.array([0]) to use Linear Interpolation # -# np.array([1]) to use Nearest Neighbour # -# _fillVal the fill value for the Linear Interpolation method. This value is assigned to # -# states that are out of the state space bounds. # -# Format: np.array([value]) # -# Usage: this variable must be declared, even if using the Nearest Neighbour # -# method. In this case, the value assigned is of no significance. # -# # -# # -# # -#################################################################################################### - -class MDP_3D_example: - - _bounds = np.array([[-5.0, 5.0],[-5.0, 5.0],[-3.141592653589793, 3.141592653589793]]) - _ptsEachDim = np.array([25, 25, 9]) - _goal = np.array([[3.5, 3.5], [1.5707, 2.3562]]) - - # set _actions based on ranges and number of steps - # format: range(lower bound, upper bound, number of steps) - vValues = np.linspace(-2, 2, 9) - wValues = np.linspace(-1, 1, 9) - _actions = [] - for i in vValues: - for j in wValues: - _actions.append((i,j)) - _actions = np.array(_actions) - - _gamma = np.array([0.93]) - _epsilon = np.array([.3]) - _maxIters = np.array([500]) - _trans = np.zeros([1, 4]) # size: [maximum number of transition states available x 4] - _useNN = np.array([0]) - _fillVal = np.array([-400]) - - # Given state and action, return successor states and their probabilities - # sVals: the coordinates of state - # bounds: the lower and upper limits of the state space in each dimension - # trans: holds each successor state and the probability of reaching that state - def transition(self, sVals, action, bounds, trans, goal): - dx = hcl.scalar(0, "dx") - dy = hcl.scalar(0, "dy") - mag = hcl.scalar(0, "mag") - - # Check if moving from a goal state - dx[0] = sVals[0] - goal[0,0] - dy[0] = sVals[1] - goal[0,1] - mag[0] = hcl.sqrt((dx[0] * dx[0]) + (dy[0] * dy[0])) - with hcl.if_(hcl.and_(mag[0] <= 1.0, sVals[2] <= goal[1,1], sVals[2] >= goal[1,0])): - trans[0, 0] = 0 - # Check if moving from an obstacle - with hcl.elif_(hcl.or_(sVals[0] < bounds[0,0] + 0.2, sVals[0] > bounds[0,1] - 0.2)): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[1] < bounds[1,0] + 0.2, sVals[1] > bounds[1,1] - 0.2)): - trans[0, 0] = 0 - # Standard move - with hcl.else_(): - trans[0, 0] = 1.0 - trans[0, 1] = sVals[0] + (0.6 * action[0] * hcl.cos(sVals[2])) - trans[0, 2] = sVals[1] + (0.6 * action[0] * hcl.sin(sVals[2])) - trans[0, 3] = sVals[2] + (0.6 * action[1]) - # Adjust for periodic dimension - with hcl.while_(trans[0, 3] > 3.141592653589793): - trans[0, 3] -= 6.283185307179586 - with hcl.while_(trans[0, 3] < -3.141592653589793): - trans[0, 3] += 6.283185307179586 - - # Return the reward for taking action from state - def reward(self, sVals, action, bounds, goal, trans): - dx = hcl.scalar(0, "dx") - dy = hcl.scalar(0, "dy") - mag = hcl.scalar(0, "mag") - rwd = hcl.scalar(0, "rwd") - - # Check if moving from a collision state, if so, assign a penalty - with hcl.if_(hcl.or_(sVals[0] < bounds[0,0] + 0.2, sVals[0] > bounds[0,1] - 0.2)): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[1] < bounds[1,0] + 0.2, sVals[1] > bounds[1,1] - 0.2)): - rwd[0] = -400 - with hcl.else_(): - # Check if moving from a goal state - dx[0] = sVals[0] - goal[0,0] - dy[0] = sVals[1] - goal[0,1] - mag[0] = hcl.sqrt((dx[0] * dx[0]) + (dy[0] * dy[0])) - with hcl.if_(hcl.and_(mag[0] <= 1.0, sVals[2] <= goal[1,1], sVals[2] >= goal[1,0])): - rwd[0] = 1000 - # Standard move - with hcl.else_(): - rwd[0] = 0 - return rwd[0] - - # Provide a print function - def writeResults(self, V, dir_path, file_name, just_values=False): - # Create directory for results if one does not exist - print("\nRecording results") - try: - os.mkdir(dir_path) - print("Created directory: ", dir_path) - except: - print("Writing to: '", dir_path, "'") - # Open file and write results - f = open(dir_path + file_name, "w") - for k in range(V.shape[2]): - for i in range(V.shape[0]): - for j in range(V.shape[1]): - s = "" - if not just_values: - si = ((i / (self._ptsEachDim[0] - 1)) * (self._bounds[0, 1] - self._bounds[0, 0])) + self._bounds[0, 0] - sj = ((j / (self._ptsEachDim[1] - 1)) * (self._bounds[1, 1] - self._bounds[1, 0])) + self._bounds[1, 0] - sk = ((k / (self._ptsEachDim[2] - 1)) * (self._bounds[2, 1] - self._bounds[2, 0])) + self._bounds[2, 0] - state = ("{:.4f}".format(si), "{:.4f}".format(sj), "{:.4f}".format(sk)) - s = str(state) + " " + str("{:.4f}".format(V[(i, j, k)])) + '\n' - else: - s = str("{:.4f}".format(V[(i, j, k)])) + ',\n' - f.write(s) - print("Finished recording results") \ No newline at end of file diff --git a/odp/MDP_example/Example_4D.py b/odp/MDP_example/Example_4D.py deleted file mode 100644 index 05b5f38c..00000000 --- a/odp/MDP_example/Example_4D.py +++ /dev/null @@ -1,131 +0,0 @@ -import numpy as np -import heterocl as hcl -import os - - - -class MDP_4D_example: - - _bounds = np.array([[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5]]) - _ptsEachDim = np.array([15, 15, 15, 15]) - _goal = np.array([1.5, 1.5, 1.5, 1.5]) - - # set _actions based on ranges and number of steps - # format: range(lower bound, upper bound, number of steps) - iValues = np.linspace(-0.5, 0.5, 5) - jValues = np.linspace(-0.5, 0.5, 5) - kValues = np.linspace(-0.5, 0.5, 5) - lValues = np.linspace(-0.5, 0.5, 5) - _actions = [] - for i in iValues: - for j in jValues: - for k in kValues: - for l in lValues: - _actions.append((i,j,k,l)) - _actions = np.array(_actions) - - _gamma = np.array([0.93]) - _epsilon = np.array([.3]) - _maxIters = np.array([30]) - _trans = np.zeros([1, 7]) # size: [maximum number of transition states available x 4] - _useNN = np.array([1]) - - - # Given state and action, return successor states and their probabilities - # sVals: the coordinates of state - # bounds: the lower and upper limits of the state space in each dimension - # trans: holds each successor state and the probability of reaching that state - def transition(self, sVals, action, bounds, trans, goal): - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - dl = hcl.scalar(0, "dl") - mag = hcl.scalar(0, "mag") - - # Check if moving from a goal state - di[0] = (sVals[0] - goal[0]) * (sVals[0] - goal[0]) - dj[0] = (sVals[1] - goal[1]) * (sVals[1] - goal[1]) - dk[0] = (sVals[2] - goal[2]) * (sVals[2] - goal[2]) - dl[0] = (sVals[3] - goal[3]) * (sVals[3] - goal[3]) - mag[0] = hcl.sqrt(di[0] + dj[0] + dk[0] + dl[0]) - - # Check if moving from an obstacle - with hcl.if_(mag[0] <= 5.0): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[0] <= bounds[0,0], sVals[0] >= bounds[0,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[1] <= bounds[1,0], sVals[1] >= bounds[1,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[2] <= bounds[2,0], sVals[2] >= bounds[2,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[3] <= bounds[3,0], sVals[3] >= bounds[3,1])): - trans[0, 0] = 0 - - # Standard move - with hcl.else_(): - trans[0, 0] = 1.0 - trans[0, 1] = sVals[0] + action[0] - trans[0, 2] = sVals[1] + action[1] - trans[0, 3] = sVals[2] + action[2] - trans[0, 4] = sVals[3] + action[3] - - # Return the reward for taking action from state - def reward(self, sVals, action, bounds, goal, trans): - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - dl = hcl.scalar(0, "dl") - mag = hcl.scalar(0, "mag") - rwd = hcl.scalar(0, "rwd") - - # Check if moving from a collision state, if so, assign a penalty - with hcl.if_(hcl.or_(sVals[0] <= bounds[0,0], sVals[0] >= bounds[0,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[1] <= bounds[1,0], sVals[1] >= bounds[1,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[2] <= bounds[2,0], sVals[2] >= bounds[2,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[3] <= bounds[3,0], sVals[3] >= bounds[3,1])): - rwd[0] = -400 - - with hcl.else_(): - # Check if moving from a goal state - di[0] = (sVals[0] - goal[0]) * (sVals[0] - goal[0]) - dj[0] = (sVals[1] - goal[1]) * (sVals[1] - goal[1]) - dk[0] = (sVals[2] - goal[2]) * (sVals[2] - goal[2]) - dl[0] = (sVals[3] - goal[3]) * (sVals[3] - goal[3]) - mag[0] = hcl.sqrt(di[0] + dj[0] + dk[0] + dl[0]) - with hcl.if_(mag[0] <= 5.0): - rwd[0] = 1000 - # Standard move - with hcl.else_(): - rwd[0] = 0 - return rwd[0] - - def writeResults(self, V, dir_path, file_name, just_values=False): - # Create directory for results if one does not exist - print("\nRecording results") - try: - os.mkdir(dir_path) - print("Created directory: ", dir_path) - except: - print("Writing to: '", dir_path, "'") - # Open file and write results - f = open(dir_path + file_name, "w") - for i in range(V.shape[0]): - for j in range(V.shape[1]): - for k in range(V.shape[2]): - for l in range(V.shape[3]): - s = "" - if not just_values: - si = ((i / (self._ptsEachDim[0] - 1)) * (self._bounds[0, 1] - self._bounds[0, 0])) + self._bounds[0, 0] - sj = ((j / (self._ptsEachDim[1] - 1)) * (self._bounds[1, 1] - self._bounds[1, 0])) + self._bounds[1, 0] - sk = ((k / (self._ptsEachDim[2] - 1)) * (self._bounds[2, 1] - self._bounds[2, 0])) + self._bounds[2, 0] - sl = ((l / (self._ptsEachDim[3] - 1)) * (self._bounds[3, 1] - self._bounds[3, 0])) + self._bounds[3, 0] - - state = ("{:.4f}".format(si), "{:.4f}".format(sj), "{:.4f}".format(sk), "{:.4f}".format(sl)) - s = str(state) + " " + str("{:.4f}".format(V[(i, j, k, l)])) + '\n' - else: - s = str("{:.4f}".format(V[(i, j, k, l)])) + ',\n' - f.write(s) - print("Finished recording results") diff --git a/odp/MDP_example/Example_5D.py b/odp/MDP_example/Example_5D.py deleted file mode 100644 index 500e299a..00000000 --- a/odp/MDP_example/Example_5D.py +++ /dev/null @@ -1,145 +0,0 @@ -import numpy as np -import heterocl as hcl -import os - - - -class MDP_5D_example: - - _bounds = np.array([[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5]]) - _ptsEachDim = np.array([10, 10, 10, 10, 10]) - _goal = np.array([1.5, 1.5, 1.5, 1.5, 1.5]) - - # set _actions based on ranges and number of steps - # format: range(lower bound, upper bound, number of steps) - iValues = np.linspace(-0.5, 0.5, 3) - jValues = np.linspace(-0.5, 0.5, 3) - kValues = np.linspace(-0.5, 0.5, 3) - lValues = np.linspace(-0.5, 0.5, 3) - mValues = np.linspace(-0.5, 0.5, 3) - _actions = [] - for i in iValues: - for j in jValues: - for k in kValues: - for l in lValues: - for m in mValues: - _actions.append((i,j,k,l,m)) - _actions = np.array(_actions) - - _gamma = np.array([0.93]) - _epsilon = np.array([.3]) - _maxIters = np.array([30]) - _trans = np.zeros([1, 7]) # size: [maximum number of transition states available x 4] - _useNN = np.array([1]) - - - # Given state and action, return successor states and their probabilities - # sVals: the coordinates of state - # bounds: the lower and upper limits of the state space in each dimension - # trans: holds each successor state and the probability of reaching that state - def transition(self, sVals, action, bounds, trans, goal): - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - dl = hcl.scalar(0, "dl") - dm = hcl.scalar(0, "dm") - mag = hcl.scalar(0, "mag") - - # Check if moving from a goal state - di[0] = (sVals[0] - goal[0]) * (sVals[0] - goal[0]) - dj[0] = (sVals[1] - goal[1]) * (sVals[1] - goal[1]) - dk[0] = (sVals[2] - goal[2]) * (sVals[2] - goal[2]) - dl[0] = (sVals[3] - goal[3]) * (sVals[3] - goal[3]) - dm[0] = (sVals[4] - goal[4]) * (sVals[4] - goal[4]) - mag[0] = hcl.sqrt(di[0] + dj[0] + dk[0] + dl[0] + dm[0]) - - # Check if moving from an obstacle - with hcl.if_(mag[0] <= 5.0): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[0] <= bounds[0,0], sVals[0] >= bounds[0,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[1] <= bounds[1,0], sVals[1] >= bounds[1,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[2] <= bounds[2,0], sVals[2] >= bounds[2,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[3] <= bounds[3,0], sVals[3] >= bounds[3,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[4] <= bounds[4,0], sVals[4] >= bounds[4,1])): - trans[0, 0] = 0 - - # Standard move - with hcl.else_(): - trans[0, 0] = 1.0 - trans[0, 1] = sVals[0] + action[0] - trans[0, 2] = sVals[1] + action[1] - trans[0, 3] = sVals[2] + action[2] - trans[0, 4] = sVals[3] + action[3] - trans[0, 5] = sVals[4] + action[4] - - # Return the reward for taking action from state - def reward(self, sVals, action, bounds, goal, trans): - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - dl = hcl.scalar(0, "dl") - dm = hcl.scalar(0, "dm") - mag = hcl.scalar(0, "mag") - rwd = hcl.scalar(0, "rwd") - - # Check if moving from a collision state, if so, assign a penalty - with hcl.if_(hcl.or_(sVals[0] <= bounds[0,0], sVals[0] >= bounds[0,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[1] <= bounds[1,0], sVals[1] >= bounds[1,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[2] <= bounds[2,0], sVals[2] >= bounds[2,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[3] <= bounds[3,0], sVals[3] >= bounds[3,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[4] <= bounds[4,0], sVals[4] >= bounds[4,1])): - rwd[0] = -400 - - with hcl.else_(): - # Check if moving from a goal state - di[0] = (sVals[0] - goal[0]) * (sVals[0] - goal[0]) - dj[0] = (sVals[1] - goal[1]) * (sVals[1] - goal[1]) - dk[0] = (sVals[2] - goal[2]) * (sVals[2] - goal[2]) - dl[0] = (sVals[3] - goal[3]) * (sVals[3] - goal[3]) - dm[0] = (sVals[4] - goal[4]) * (sVals[4] - goal[4]) - mag[0] = hcl.sqrt(di[0] + dj[0] + dk[0] + dl[0] + dm[0]) - with hcl.if_(mag[0] <= 5.0): - rwd[0] = 1000 - # Standard move - with hcl.else_(): - rwd[0] = 0 - return rwd[0] - - def writeResults(self, V, dir_path, file_name, just_values=False): - # Create directory for results if one does not exist - print("\nRecording results") - try: - os.mkdir(dir_path) - print("Created directory: ", dir_path) - except: - print("Writing to: '", dir_path, "'") - # Open file and write results - f = open(dir_path + file_name, "w") - for i in range(V.shape[0]): - for j in range(V.shape[1]): - for k in range(V.shape[2]): - for l in range(V.shape[3]): - for m in range(V.shape[4]): - s = "" - if not just_values: - si = ((i / (self._ptsEachDim[0] - 1)) * (self._bounds[0, 1] - self._bounds[0, 0])) + self._bounds[0, 0] - sj = ((j / (self._ptsEachDim[1] - 1)) * (self._bounds[1, 1] - self._bounds[1, 0])) + self._bounds[1, 0] - sk = ((k / (self._ptsEachDim[2] - 1)) * (self._bounds[2, 1] - self._bounds[2, 0])) + self._bounds[2, 0] - sl = ((l / (self._ptsEachDim[3] - 1)) * (self._bounds[3, 1] - self._bounds[3, 0])) + self._bounds[3, 0] - sm = ((m / (self._ptsEachDim[4] - 1)) * (self._bounds[4, 1] - self._bounds[4, 0])) + self._bounds[4, 0] - - state = ("{:.4f}".format(si), "{:.4f}".format(sj), "{:.4f}".format(sk), - "{:.4f}".format(sl), "{:.4f}".format(sm)) - s = str(state) + " " + str("{:.4f}".format(V[(i, j, k, l, m)])) + '\n' - else: - s = str("{:.4f}".format(V[(i, j, k, l, m)])) + ',\n' - f.write(s) - print("Finished recording results") diff --git a/odp/MDP_example/Example_6D.py b/odp/MDP_example/Example_6D.py deleted file mode 100644 index efb44e50..00000000 --- a/odp/MDP_example/Example_6D.py +++ /dev/null @@ -1,158 +0,0 @@ -import numpy as np -import heterocl as hcl -import os - - - -class MDP_6D_example: - - _bounds = np.array([[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5]]) - _ptsEachDim = np.array([10, 10, 10, 10, 10, 10]) - _goal = np.array([1.5, 1.5, 1.5, 1.5, 1.5, 1.5]) - - # set _actions based on ranges and number of steps - # format: range(lower bound, upper bound, number of steps) - iValues = np.linspace(-0.5, 0.5, 3) - jValues = np.linspace(-0.5, 0.5, 3) - kValues = np.linspace(-0.5, 0.5, 3) - lValues = np.linspace(-0.5, 0.5, 3) - mValues = np.linspace(-0.5, 0.5, 3) - nValues = np.linspace(-0.5, 0.5, 3) - _actions = [] - for i in iValues: - for j in jValues: - for k in kValues: - for l in lValues: - for m in mValues: - for n in nValues: - _actions.append((i,j,k,l,m,n)) - _actions = np.array(_actions) - - _gamma = np.array([0.93]) - _epsilon = np.array([.3]) - _maxIters = np.array([30]) - _trans = np.zeros([1, 7]) # size: [maximum number of transition states available x 4] - _useNN = np.array([1]) - - - # Given state and action, return successor states and their probabilities - # sVals: the coordinates of state - # bounds: the lower and upper limits of the state space in each dimension - # trans: holds each successor state and the probability of reaching that state - def transition(self, sVals, action, bounds, trans, goal): - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - dl = hcl.scalar(0, "dl") - dm = hcl.scalar(0, "dm") - dn = hcl.scalar(0, "dn") - mag = hcl.scalar(0, "mag") - - # Check if moving from a goal state - di[0] = (sVals[0] - goal[0]) * (sVals[0] - goal[0]) - dj[0] = (sVals[1] - goal[1]) * (sVals[1] - goal[1]) - dk[0] = (sVals[2] - goal[2]) * (sVals[2] - goal[2]) - dl[0] = (sVals[3] - goal[3]) * (sVals[3] - goal[3]) - dm[0] = (sVals[4] - goal[4]) * (sVals[4] - goal[4]) - dn[0] = (sVals[5] - goal[5]) * (sVals[5] - goal[5]) - mag[0] = hcl.sqrt(di[0] + dj[0] + dk[0] + dl[0] + dm[0] + dn[0]) - - # Check if moving from an obstacle - with hcl.if_(mag[0] <= 5.0): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[0] <= bounds[0,0], sVals[0] >= bounds[0,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[1] <= bounds[1,0], sVals[1] >= bounds[1,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[2] <= bounds[2,0], sVals[2] >= bounds[2,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[3] <= bounds[3,0], sVals[3] >= bounds[3,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[4] <= bounds[4,0], sVals[4] >= bounds[4,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[5] <= bounds[5,0], sVals[5] >= bounds[5,1])): - trans[0, 0] = 0 - - # Standard move - with hcl.else_(): - trans[0, 0] = 1.0 - trans[0, 1] = sVals[0] + action[0] - trans[0, 2] = sVals[1] + action[1] - trans[0, 3] = sVals[2] + action[2] - trans[0, 4] = sVals[3] + action[3] - trans[0, 5] = sVals[4] + action[4] - trans[0, 6] = sVals[5] + action[5] - - # Return the reward for taking action from state - def reward(self, sVals, action, bounds, goal, trans): - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - dl = hcl.scalar(0, "dl") - dm = hcl.scalar(0, "dm") - dn = hcl.scalar(0, "dn") - mag = hcl.scalar(0, "mag") - rwd = hcl.scalar(0, "rwd") - - # Check if moving from a collision state, if so, assign a penalty - with hcl.if_(hcl.or_(sVals[0] <= bounds[0,0], sVals[0] >= bounds[0,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[1] <= bounds[1,0], sVals[1] >= bounds[1,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[2] <= bounds[2,0], sVals[2] >= bounds[2,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[3] <= bounds[3,0], sVals[3] >= bounds[3,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[4] <= bounds[4,0], sVals[4] >= bounds[4,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[5] <= bounds[5,0], sVals[5] >= bounds[5,1])): - rwd[0] = -400 - - with hcl.else_(): - # Check if moving from a goal state - di[0] = (sVals[0] - goal[0]) * (sVals[0] - goal[0]) - dj[0] = (sVals[1] - goal[1]) * (sVals[1] - goal[1]) - dk[0] = (sVals[2] - goal[2]) * (sVals[2] - goal[2]) - dl[0] = (sVals[3] - goal[3]) * (sVals[3] - goal[3]) - dm[0] = (sVals[4] - goal[4]) * (sVals[4] - goal[4]) - dn[0] = (sVals[5] - goal[5]) * (sVals[5] - goal[5]) - mag[0] = hcl.sqrt(di[0] + dj[0] + dk[0] + dl[0] + dm[0] + dn[0]) - with hcl.if_(mag[0] <= 5.0): - rwd[0] = 1000 - # Standard move - with hcl.else_(): - rwd[0] = 0 - return rwd[0] - - def writeResults(self, V, dir_path, file_name, just_values=False): - # Create directory for results if one does not exist - print("\nRecording results") - try: - os.mkdir(dir_path) - print("Created directory: ", dir_path) - except: - print("Writing to: '", dir_path, "'") - # Open file and write results - f = open(dir_path + file_name, "w") - for i in range(V.shape[0]): - for j in range(V.shape[1]): - for k in range(V.shape[2]): - for l in range(V.shape[3]): - for m in range(V.shape[4]): - for n in range(V.shape[5]): - s = "" - if not just_values: - si = ((i / (self._ptsEachDim[0] - 1)) * (self._bounds[0, 1] - self._bounds[0, 0])) + self._bounds[0, 0] - sj = ((j / (self._ptsEachDim[1] - 1)) * (self._bounds[1, 1] - self._bounds[1, 0])) + self._bounds[1, 0] - sk = ((k / (self._ptsEachDim[2] - 1)) * (self._bounds[2, 1] - self._bounds[2, 0])) + self._bounds[2, 0] - sl = ((l / (self._ptsEachDim[3] - 1)) * (self._bounds[3, 1] - self._bounds[3, 0])) + self._bounds[3, 0] - sm = ((m / (self._ptsEachDim[4] - 1)) * (self._bounds[4, 1] - self._bounds[4, 0])) + self._bounds[4, 0] - sn = ((n / (self._ptsEachDim[5] - 1)) * (self._bounds[5, 1] - self._bounds[5, 0])) + self._bounds[5, 0] - - state = ("{:.4f}".format(si), "{:.4f}".format(sj), "{:.4f}".format(sk), - "{:.4f}".format(sl), "{:.4f}".format(sm), "{:.4f}".format(sn)) - s = str(state) + " " + str("{:.4f}".format(V[(i, j, k, l, m, n)])) + '\n' - else: - s = str("{:.4f}".format(V[(i, j, k, l, m, n)])) + ',\n' - f.write(s) - print("Finished recording results") \ No newline at end of file diff --git a/odp/MDP_example/Example_7D.py b/odp/MDP_example/Example_7D.py deleted file mode 100644 index 318e382a..00000000 --- a/odp/MDP_example/Example_7D.py +++ /dev/null @@ -1,135 +0,0 @@ -import numpy as np -import heterocl as hcl - - - -class MDP_7D_example: - - _bounds = np.array([[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5],[-2.5, 2.5]]) - _ptsEachDim = np.array([10, 10, 10, 10, 10, 10, 10]) - _goal = np.array([1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5]) - - # set _actions based on ranges and number of steps - # format: range(lower bound, upper bound, number of steps) - iValues = np.linspace(-0.5, 0.5, 3) - jValues = np.linspace(-0.5, 0.5, 3) - kValues = np.linspace(-0.5, 0.5, 3) - lValues = np.linspace(-0.5, 0.5, 3) - mValues = np.linspace(-0.5, 0.5, 3) - nValues = np.linspace(-0.5, 0.5, 3) - oValues = np.linspace(-0.5, 0.5, 3) - _actions = [] - for i in iValues: - for j in jValues: - for k in kValues: - for l in lValues: - for m in mValues: - for n in nValues: - for o in oValues: - _actions.append((i,j,k,l,m,n,o)) - _actions = np.array(_actions) - - _gamma = np.array([0.93]) - _epsilon = np.array([.3]) - _maxIters = np.array([30]) - _trans = np.zeros([1, 7]) # size: [maximum number of transition states available x 4] - _useNN = np.array([1]) - - - # Given state and action, return successor states and their probabilities - # sVals: the coordinates of state - # bounds: the lower and upper limits of the state space in each dimension - # trans: holds each successor state and the probability of reaching that state - def transition(self, sVals, action, bounds, trans, goal): - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - dl = hcl.scalar(0, "dl") - dm = hcl.scalar(0, "dm") - dn = hcl.scalar(0, "dn") - do = hcl.scalar(0, "do") - mag = hcl.scalar(0, "mag") - - # Check if moving from a goal state - di[0] = (sVals[0] - goal[0]) * (sVals[0] - goal[0]) - dj[0] = (sVals[1] - goal[1]) * (sVals[1] - goal[1]) - dk[0] = (sVals[2] - goal[2]) * (sVals[2] - goal[2]) - dl[0] = (sVals[3] - goal[3]) * (sVals[3] - goal[3]) - dm[0] = (sVals[4] - goal[4]) * (sVals[4] - goal[4]) - dn[0] = (sVals[5] - goal[5]) * (sVals[5] - goal[5]) - do[0] = (sVals[6] - goal[6]) * (sVals[6] - goal[6]) - mag[0] = hcl.sqrt(di[0] + dj[0] + dk[0] + dl[0] + dm[0] + dn[0] + do[0]) - - # Check if moving from an obstacle - with hcl.if_(mag[0] <= 5.0): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[0] <= bounds[0,0], sVals[0] >= bounds[0,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[1] <= bounds[1,0], sVals[1] >= bounds[1,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[2] <= bounds[2,0], sVals[2] >= bounds[2,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[3] <= bounds[3,0], sVals[3] >= bounds[3,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[4] <= bounds[4,0], sVals[4] >= bounds[4,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[5] <= bounds[5,0], sVals[5] >= bounds[5,1])): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[6] <= bounds[6,0], sVals[6] >= bounds[6,1])): - trans[0, 0] = 0 - - # Standard move - with hcl.else_(): - trans[0, 0] = 1.0 - trans[0, 1] = sVals[0] + action[0] - trans[0, 2] = sVals[1] + action[1] - trans[0, 3] = sVals[2] + action[2] - trans[0, 4] = sVals[3] + action[3] - trans[0, 5] = sVals[4] + action[4] - trans[0, 6] = sVals[5] + action[5] - trans[0, 7] = sVals[6] + action[6] - - # Return the reward for taking action from state - def reward(self, sVals, action, bounds, goal, trans): - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - dl = hcl.scalar(0, "dl") - dm = hcl.scalar(0, "dm") - dn = hcl.scalar(0, "dn") - do = hcl.scalar(0, "do") - mag = hcl.scalar(0, "mag") - rwd = hcl.scalar(0, "rwd") - - # Check if moving from a collision state, if so, assign a penalty - with hcl.if_(hcl.or_(sVals[0] <= bounds[0,0], sVals[0] >= bounds[0,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[1] <= bounds[1,0], sVals[1] >= bounds[1,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[2] <= bounds[2,0], sVals[2] >= bounds[2,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[3] <= bounds[3,0], sVals[3] >= bounds[3,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[4] <= bounds[4,0], sVals[4] >= bounds[4,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[5] <= bounds[5,0], sVals[5] >= bounds[5,1])): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[6] <= bounds[6,0], sVals[6] >= bounds[6,1])): - rwd[0] = -400 - - with hcl.else_(): - # Check if moving from a goal state - di[0] = (sVals[0] - goal[0]) * (sVals[0] - goal[0]) - dj[0] = (sVals[1] - goal[1]) * (sVals[1] - goal[1]) - dk[0] = (sVals[2] - goal[2]) * (sVals[2] - goal[2]) - dl[0] = (sVals[3] - goal[3]) * (sVals[3] - goal[3]) - dm[0] = (sVals[4] - goal[4]) * (sVals[4] - goal[4]) - dn[0] = (sVals[5] - goal[5]) * (sVals[5] - goal[5]) - do[0] = (sVals[6] - goal[6]) * (sVals[6] - goal[6]) - mag[0] = hcl.sqrt(di[0] + dj[0] + dk[0] + dl[0] + dm[0] + dn[0] + do[0]) - with hcl.if_(mag[0] <= 5.0): - rwd[0] = 1000 - # Standard move - with hcl.else_(): - rwd[0] = 0 - return rwd[0] \ No newline at end of file diff --git a/odp/Plots/__init__.py b/odp/Plots/__init__.py deleted file mode 100644 index 825b7e96..00000000 --- a/odp/Plots/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from odp.Plots.plotting_utilities import plot_isosurface -from odp.Plots.plot_options import PlotOptions \ No newline at end of file diff --git a/odp/Plots/plot_options.py b/odp/Plots/plot_options.py deleted file mode 100644 index fbd58937..00000000 --- a/odp/Plots/plot_options.py +++ /dev/null @@ -1,22 +0,0 @@ - -class PlotOptions: - def __init__(self, do_plot=True, plot_type="3d_plot", plotDims=[], - slicesCut=[], min_isosurface = 0, max_isosurface = 0): - if plot_type not in ["2d_plot", "3d_plot"]: - raise Exception("Illegal plot type !") - - if plot_type == "2d_plot" : - if len(plotDims) != 2: - raise Exception("Make sure that dim_plot size is 2 !!") - - if plot_type == "3d_plot" : - if len(plotDims) != 3: - raise Exception("Make sure that dim_plot size is 3 !!") - - self.do_plot = do_plot - self.dims_plot = plotDims - self.plot_type = plot_type - self.slices = slicesCut - self.min_isosurface = min_isosurface - self.max_isosurface = max_isosurface - diff --git a/odp/Plots/plotting_utilities.py b/odp/Plots/plotting_utilities.py deleted file mode 100644 index b0723092..00000000 --- a/odp/Plots/plotting_utilities.py +++ /dev/null @@ -1,78 +0,0 @@ -import plotly.graph_objects as go -import numpy as np - - -def plot_isosurface(grid, V, plot_option): - dims_plot = plot_option.dims_plot - idx = [slice(None)] * grid.dims - slice_idx = 0 - - dims_list = list(range(grid.dims)) - for i in dims_list: - if i not in dims_plot: - idx[i] = plot_option.slices[slice_idx] - slice_idx += 1 - - if len(dims_plot) != 3 and len(dims_plot) != 2: - raise Exception('dims_plot length should be equal to 3\n') - - if len(dims_plot) == 3: - # Plot 3D isosurface - dim1, dim2, dim3 = dims_plot[0], dims_plot[1], dims_plot[2] - complex_x = complex(0, grid.pts_each_dim[dim1]) - complex_y = complex(0, grid.pts_each_dim[dim2]) - complex_z = complex(0, grid.pts_each_dim[dim3]) - mg_X, mg_Y, mg_Z = np.mgrid[grid.min[dim1]:grid.max[dim1]: complex_x, grid.min[dim2]:grid.max[dim2]: complex_y, - grid.min[dim3]:grid.max[dim3]: complex_z] - - my_V = V[tuple(idx)] - - if (my_V > 0.0).all(): - print("Implicit surface will not be shown since all values are positive ") - if (my_V < 0.0).all(): - print("Implicit surface will not be shown since all values are negative ") - - print("Plotting beautiful plots. Please wait\n") - fig = go.Figure(data=go.Isosurface( - x=mg_X.flatten(), - y=mg_Y.flatten(), - z=mg_Z.flatten(), - value=my_V.flatten(), - colorscale='jet', - isomin=plot_option.min_isosurface, - surface_count=1, - isomax=plot_option.max_isosurface, - caps=dict(x_show=True, y_show=True) - )) - fig.show() - print("Please check the plot on your browser.") - - if len(dims_plot) == 2: - dim1, dim2 = dims_plot[0], dims_plot[1] - complex_x = complex(0, grid.pts_each_dim[dim1]) - complex_y = complex(0, grid.pts_each_dim[dim2]) - mg_X, mg_Y = np.mgrid[grid.min[dim1]:grid.max[dim1]: complex_x, grid.min[dim2]:grid.max[dim2]: complex_y] - - my_V = V[tuple(idx)] - - if (my_V > 0.0).all(): - print("Implicit surface will not be shown since all values are positive ") - if (my_V < 0.0).all(): - print("Implicit surface will not be shown since all values are negative ") - - print("Plotting beautiful 2D plots. Please wait\n") - fig = go.Figure(data=go.Contour( - x=mg_X.flatten(), - y=mg_Y.flatten(), - z=my_V.flatten(), - zmin=0.0, - ncontours=1, - contours_coloring='none', # former: lines - name="Reachable Set", # zero level - line_width=1.5, - line_color='magenta', - zmax=0.0, - ), layout=go.Layout(plot_bgcolor='rgba(0,0,0,0)')) # ,paper_bgcolor='rgba(0,0,0,0)' - - fig.show() - print("Please check the plot on your browser.") \ No newline at end of file diff --git a/odp/Shapes/__init__.py b/odp/Shapes/__init__.py deleted file mode 100644 index c8bee3f5..00000000 --- a/odp/Shapes/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from odp.Shapes.ShapesFunctions import CylinderShape -from odp.Shapes.ShapesFunctions import ShapeRectangle -from odp.Shapes.ShapesFunctions import Rect_Around_Point -from odp.Shapes.ShapesFunctions import Lower_Half_Space -from odp.Shapes.ShapesFunctions import Upper_Half_Space -from odp.Shapes.ShapesFunctions import Intersection -from odp.Shapes.ShapesFunctions import Union \ No newline at end of file diff --git a/odp/TimeToReach/TimeToReach_3D.py b/odp/TimeToReach/TimeToReach_3D.py deleted file mode 100644 index be34651b..00000000 --- a/odp/TimeToReach/TimeToReach_3D.py +++ /dev/null @@ -1,241 +0,0 @@ -import heterocl as hcl -import numpy as np -from odp.computeGraphs.graph_3D import * - -# Update the phi function at position (i,j,k) -def updatePhi(i, j, k, my_object, phi, g, x1, x2, x3): - dV_dx1_L = hcl.scalar(0, "dV_dx1_L") - dV_dx1_R = hcl.scalar(0, "dV_dx1_R") - dV_dx1 = hcl.scalar(0, "dV_dx1") - dV_dx2_L = hcl.scalar(0, "dV_dx2_L") - dV_dx2_R = hcl.scalar(0, "dV_dx2_R") - dV_dx2 = hcl.scalar(0, "dV_dx2") - dV_dx3_L = hcl.scalar(0, "dV_dx3_L") - dV_dx3_R = hcl.scalar(0, "dV_dx3_R") - dV_dx3 = hcl.scalar(0, "dV_dx3") - - sigma1 = hcl.scalar(0, "sigma1") - sigma2 = hcl.scalar(0, "sigma2") - sigma3 = hcl.scalar(0, "sigma3") - - # dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - dV_dx1_L[0], dV_dx1_R[0] = spa_derivX(i, j, k, phi, g) - dV_dx2_L[0], dV_dx2_R[0] = spa_derivY(i, j, k, phi, g) - dV_dx3_L[0], dV_dx3_R[0] = spa_derivT(i, j, k, phi, g) - - # Calculate average gradient - dV_dx1[0] = (dV_dx1_L[0] + dV_dx1_R[0]) / 2 - dV_dx2[0] = (dV_dx2_L[0] + dV_dx2_R[0]) / 2 - dV_dx3[0] = (dV_dx3_L[0] + dV_dx3_R[0]) / 2 - - # Find the optimal control through my_object's API - uOpt = my_object.opt_ctrl(0, (x1[i], x2[j], x3[k]), - (dV_dx1[0], dV_dx2[0], dV_dx3[0])) - dOpt = my_object.opt_dstb(0, (x1[i], x2[j], x3[k]), - (dV_dx1[0], dV_dx2[0], dV_dx3[0])) - - # Calculate dynamical rates of changes - dx1_dt, dx2_dt, dx3_dt = my_object.dynamics(0, (x1[i], x2[j], x3[k]), uOpt, dOpt) - - H = hcl.scalar(0, "H") - phiNew = hcl.scalar(0, "phiNew") - diss1 = hcl.scalar(0, "diss1") - diss2 = hcl.scalar(0, "diss2") - diss3 = hcl.scalar(0, "diss3") - - # Calculate Hamiltonian terms: - H[0] = (-(dx1_dt * dV_dx1[0] + dx2_dt * dV_dx2[0] + dx3_dt * dV_dx3[0] + 1)) - - # Calculate the "dissipation" - sigma1[0] = my_abs(dx1_dt) - sigma2[0] = my_abs(dx2_dt) - sigma3[0] = my_abs(dx3_dt) - c = hcl.scalar(0, "c") - c[0] = sigma1[0] / g.dx[0] + sigma2[0] / g.dx[1] + sigma3[0] / g.dx[2] - - diss1[0] = sigma1[0] * ((dV_dx1_R[0] - dV_dx1_L[0]) / 2 + phi[i, j, k] / g.dx[0]) - diss2[0] = sigma2[0] * ((dV_dx2_R[0] - dV_dx2_L[0]) / 2 + phi[i, j, k] / g.dx[1]) - diss3[0] = sigma3[0] * ((dV_dx3_R[0] - dV_dx3_L[0]) / 2 + phi[i, j, k] / g.dx[2]) - - # New phi - phiNew[0] = (-H[0] + diss1[0] + diss2[0] + diss3[0]) / c[0] - #debugger[i,j,k] = phiNew[0] - phi[i, j, k] = my_min(phi[i, j ,k], phiNew[0]) - -def EvalBoundary(phi, g): - if 0 not in g.pDim: - with hcl.for_(0, phi.shape[1], name="j") as j: - with hcl.for_(0, phi.shape[2], name="k") as k: - #debug2[0] = j - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[1, j, k] - phi[2, j, k] - tmp1[0] = my_max(tmp1[0], phi[2, j, k]) - phi[0, j, k] = my_min(tmp1[0], phi[0, j, k]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[phi.shape[0] - 2, j, k] - phi[phi.shape[0] - 3, j, k] - tmp2[0] = my_max(tmp2[0], phi[phi.shape[0] - 3, j, k]) - phi[phi.shape[0] - 1, j, k] = my_min(tmp2[0], phi[phi.shape[0] - 1, j, k]) - - if 1 not in g.pDim: - with hcl.for_(0, phi.shape[0], name="i2") as i2: - with hcl.for_(0, phi.shape[2], name="k") as k: - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[i2, 1, k] - phi[i2, 2, k] - tmp1[0] = my_max(tmp1[0], phi[i2, 2, k]) - phi[i2, 0, k] = my_min(tmp1[0], phi[i2, 0, k]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[i2, phi.shape[1] - 2, k] - phi[i2, phi.shape[1] - 3, k] - tmp2[0] = my_max(tmp2[0], phi[i2, phi.shape[1] - 3, k]) - phi[i2, phi.shape[1] - 1, k] = my_min(tmp2[0], phi[i2, phi.shape[1] - 1, k]) - - if 2 not in g.pDim: - with hcl.for_(0, phi.shape[0], name="i2") as i2: - with hcl.for_(0, phi.shape[1], name="j") as j: - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[i2, j, 1] - phi[i2, j, 2] - tmp1[0] = my_max(tmp1[0], phi[i2, j, 2]) - phi[i2, j, 0] = my_min(tmp1[0], phi[i2, j, 0]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[i2, j, phi.shape[2] - 2] - phi[i2, j, phi.shape[2] - 3] - tmp2[0] = my_max(tmp2[0], phi[i2, j, phi.shape[2] - 3]) - phi[i2, j, phi.shape[2] - 1] = my_min(tmp2[0], phi[i2, j, phi.shape[2] - 1]) - - -# Returns 0 if convergence has been reached -def evaluateConvergence(newV, oldV, epsilon, reSweep): - delta = hcl.scalar(0, "delta") - # Calculate the difference, if it's negative, make it positive - delta[0] = newV[0] - oldV[0] - with hcl.if_(delta[0] < 0): - delta[0] = delta[0] * -1 - with hcl.if_(delta[0] > epsilon[0]): - reSweep[0] = 1 - -######################################### TIME-TO-REACH COMPUTATION ########################################## - -def TTR_3D(my_object, g): - def solve_phiNew(phi, x1, x2, x3): - l_i = 0 if 0 in g.pDim else 1 - h_i = phi.shape[0] if 0 in g.pDim else phi.shape[0] - 1 - l_j = 0 if 1 in g.pDim else 1 - h_j = phi.shape[1] if 1 in g.pDim else phi.shape[1] - 1 - l_k = 0 if 2 in g.pDim else 1 - h_k = phi.shape[2] if 2 in g.pDim else phi.shape[2] - 1 - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - updatePhi(i, j, k, my_object, phi, g, x1, x2, x3) - # debug2[0] = j - EvalBoundary(phi, g) - - #Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - i2 = phi.shape[0] - i - 1 - j2 = phi.shape[1] - j - 1 - k2 = phi.shape[2] - k - 1 - updatePhi(i2, j2, k2, my_object, phi, g, x1, x2, x3) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - j2 = phi.shape[1] - j - 1 - k2 = phi.shape[2] - k - 1 - updatePhi(i, j2, k2, my_object, phi, g, x1, x2, x3) - EvalBoundary(phi, g) - - - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - i2 = phi.shape[0] - i - 1 - j2 = phi.shape[1] - j - 1 - updatePhi(i2, j2, k, my_object, phi, g, x1, x2, x3) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - i2 = phi.shape[0] - i - 1 - k2 = phi.shape[2] - k - 1 - updatePhi(i2, j, k2, my_object, phi, g, x1, x2, x3) - EvalBoundary(phi, g) - - - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - i2 = phi.shape[0] - i - 1 - updatePhi(i2, j, k, my_object, phi, g, x1, x2, x3) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - j2 = phi.shape[1] - j - 1 - updatePhi(i, j2, k, my_object, phi, g, x1, x2, x3) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - k2 = phi.shape[2] - k - 1 - updatePhi(i, j, k2, my_object, phi, g, x1, x2, x3) - EvalBoundary(phi, g) - - ###################################### SETUP PLACEHOLDERS ###################################### - - # Initialize the HCL environment - hcl.init() - hcl.config.init_dtype = hcl.Float() - - # Positions vector - x1 = hcl.placeholder((g.pts_each_dim[0],), name="x1", dtype=hcl.Float()) - x2 = hcl.placeholder((g.pts_each_dim[1],), name="x2", dtype=hcl.Float()) - x3 = hcl.placeholder((g.pts_each_dim[2],), name="x3", dtype=hcl.Float()) - phi = hcl.placeholder(tuple(g.pts_each_dim), name="phi", dtype=hcl.Float()) - #debugger = hcl.placeholder(tuple(g.pts_each_dim), name="debugger", dtype=hcl.Float()) - #debug2 = hcl.placeholder((0,), "debug2") - - # Create a static schedule -- graph - s = hcl.create_schedule([phi, x1, x2, x3], solve_phiNew) - sweep_1 = solve_phiNew.Sweep_1 - sweep_2 = solve_phiNew.Sweep_2 - sweep_3 = solve_phiNew.Sweep_3 - sweep_4 = solve_phiNew.Sweep_4 - sweep_5 = solve_phiNew.Sweep_5 - sweep_6 = solve_phiNew.Sweep_6 - sweep_7 = solve_phiNew.Sweep_7 - sweep_8 = solve_phiNew.Sweep_8 - - s[sweep_1].parallel(sweep_1.i) - s[sweep_2].parallel(sweep_2.i) - s[sweep_3].parallel(sweep_3.i) - s[sweep_4].parallel(sweep_4.i) - s[sweep_5].parallel(sweep_5.i) - s[sweep_6].parallel(sweep_6.i) - s[sweep_7].parallel(sweep_7.i) - s[sweep_8].parallel(sweep_8.i) - - # Build an executable and return - return hcl.build(s) diff --git a/odp/TimeToReach/TimeToReach_4D.py b/odp/TimeToReach/TimeToReach_4D.py deleted file mode 100644 index 8afdfa91..00000000 --- a/odp/TimeToReach/TimeToReach_4D.py +++ /dev/null @@ -1,272 +0,0 @@ -import heterocl as hcl -import numpy as np -from odp.computeGraphs.graph_4D import * - - -# Update the phi function at position (i,j,k) -def updatePhi(i, j, k, l, my_object, phi, g, x1, x2, x3, x4): - dV_dx1_L = hcl.scalar(0, "dV_dx1_L") - dV_dx1_R = hcl.scalar(0, "dV_dx1_R") - dV_dx1 = hcl.scalar(0, "dV_dx1") - dV_dx2_L = hcl.scalar(0, "dV_dx2_L") - dV_dx2_R = hcl.scalar(0, "dV_dx2_R") - dV_dx2 = hcl.scalar(0, "dV_dx2") - dV_dx3_L = hcl.scalar(0, "dV_dx3_L") - dV_dx3_R = hcl.scalar(0, "dV_dx3_R") - dV_dx3 = hcl.scalar(0, "dV_dx3") - dV_dx4_L = hcl.scalar(0, "dV_dx4_L") - dV_dx4_R = hcl.scalar(0, "dV_dx4_R") - dV_dx4 = hcl.scalar(0, "dV_dx4") - - sigma1 = hcl.scalar(0, "sigma1") - sigma2 = hcl.scalar(0, "sigma2") - sigma3 = hcl.scalar(0, "sigma3") - sigma4 = hcl.scalar(0, "sigma4") - - # dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - dV_dx1_L[0], dV_dx1_R[0] = spa_derivX1_4d(i, j, k, l, phi, g) - dV_dx2_L[0], dV_dx2_R[0] = spa_derivX2_4d(i, j, k, l, phi, g) - dV_dx3_L[0], dV_dx3_R[0] = spa_derivX3_4d(i, j, k, l, phi, g) - dV_dx4_L[0], dV_dx4_R[0] = spa_derivX4_4d(i, j, k, l, phi, g) - - # Calculate average gradient - dV_dx1[0] = (dV_dx1_L[0] + dV_dx1_R[0]) / 2 - dV_dx2[0] = (dV_dx2_L[0] + dV_dx2_R[0]) / 2 - dV_dx3[0] = (dV_dx3_L[0] + dV_dx3_R[0]) / 2 - dV_dx4[0] = (dV_dx4_L[0] + dV_dx4_R[0]) / 2 - - # Find the optimal control through my_object's API - uOpt = my_object.opt_ctrl(0, (x1[i], x2[j], x3[k], x4[l]), - (dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0])) - # Find optimal disturbance - dOpt = my_object.opt_dstb(0, (x1[i], x2[j], x3[k], x4[l]), - (dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0])) - - # Find rates of changes based on dynamics equation - dx1_dt, dx2_dt, dx3_dt, dx4_dt = my_object.dynamics(0, (x1[i], x2[j], x3[k], x4[l]), uOpt, dOpt) - - H = hcl.scalar(0, "H") - phiNew = hcl.scalar(0, "phiNew") - diss1 = hcl.scalar(0, "diss1") - diss2 = hcl.scalar(0, "diss2") - diss3 = hcl.scalar(0, "diss3") - diss4 = hcl.scalar(0, "diss4") - - # Calculate Hamiltonian terms: - H[0] = (-(dx1_dt * dV_dx1[0] + dx2_dt * dV_dx2[0] + dx3_dt * dV_dx3[0] + dx4_dt * dV_dx4[0] + 1)) - - # Calculate the "dissipation" - sigma1[0] = my_abs(dx1_dt) - sigma2[0] = my_abs(dx2_dt) - sigma3[0] = my_abs(dx3_dt) - sigma4[0] = my_abs(dx4_dt) - c = hcl.scalar(0, "c") - c[0] = sigma1[0] / g.dx[0] + sigma2[0] / g.dx[1] + sigma3[0] / g.dx[2] + sigma4[0] / g.dx[3] - - diss1[0] = sigma1[0] * ((dV_dx1_R[0] - dV_dx1_L[0]) / 2 + phi[i, j, k, l] / g.dx[0]) - diss2[0] = sigma2[0] * ((dV_dx2_R[0] - dV_dx2_L[0]) / 2 + phi[i, j, k, l] / g.dx[1]) - diss3[0] = sigma3[0] * ((dV_dx3_R[0] - dV_dx3_L[0]) / 2 + phi[i, j, k, l] / g.dx[2]) - diss4[0] = sigma4[0] * ((dV_dx4_R[0] - dV_dx4_L[0]) / 2 + phi[i, j, k, l] / g.dx[3]) - - # New phi - phiNew[0] = (-H[0] + diss1[0] + diss2[0] + diss3[0] + diss4[0]) / c[0] - # debugger[i, j, k, l] = phiNew[0] - phi[i, j, k, l] = my_min(phi[i, j, k, l], phiNew[0]) - -def EvalBoundary(phi, g): - if 0 not in g.pDim: - with hcl.for_(0, phi.shape[1], name="j") as j: - with hcl.for_(0, phi.shape[2], name="k") as k: - with hcl.for_(0, phi.shape[3], name="l") as l: - # debug2[0] = j - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[1, j, k, l] - phi[2, j, k, l] - tmp1[0] = my_max(tmp1[0], phi[2, j, k, l]) - phi[0, j, k, l] = my_min(tmp1[0], phi[0, j, k, l]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[phi.shape[0] - 2, j, k, l] - phi[phi.shape[0] - 3, j, k, l] - tmp2[0] = my_max(tmp2[0], phi[phi.shape[0] - 3, j, k, l]) - phi[phi.shape[0] - 1, j, k, l] = my_min(tmp2[0], phi[phi.shape[0] - 1, j, k, l]) - - if 1 not in g.pDim: - with hcl.for_(0, phi.shape[0], name="i3") as i3: - with hcl.for_(0, phi.shape[2], name="k") as k: - with hcl.for_(0, phi.shape[3], name="l") as l: - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[i3, 1, k, l] - phi[i3, 2, k, l] - tmp1[0] = my_max(tmp1[0], phi[i3, 2, k, l ]) - phi[i3, 0, k, l] = my_min(tmp1[0], phi[i3, 0, k, l]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[i3, phi.shape[1] - 2, k, l] - phi[i3, phi.shape[1] - 3, k, l] - tmp2[0] = my_max(tmp2[0], phi[i3, phi.shape[1] - 3, k, l]) - phi[i3, phi.shape[1] - 1, k, l] = my_min(tmp2[0], phi[i3, phi.shape[1] - 1, k, l]) - - if 2 not in g.pDim: - with hcl.for_(0, phi.shape[0], name="i3") as i3: - with hcl.for_(0, phi.shape[1], name="j") as j: - with hcl.for_(0, phi.shape[3], name="l") as l: - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[i3, j, 1, l] - phi[i3, j, 2, l] - tmp1[0] = my_max(tmp1[0], phi[i3, j, 2, l]) - phi[i3, j, 0, l] = my_min(tmp1[0], phi[i3, j, 0, l]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[i3, j, phi.shape[2] - 2, l] - phi[i3, j, phi.shape[2] - 3, l] - tmp2[0] = my_max(tmp2[0], phi[i3, j, phi.shape[2] - 3, l]) - phi[i3, j, phi.shape[2] - 1, l] = my_min(tmp2[0], phi[i3, j, phi.shape[2] - 1, l]) - - if 3 not in g.pDim: - with hcl.for_(0, phi.shape[0], name="i3") as i3: - with hcl.for_(0, phi.shape[1], name="j") as j: - with hcl.for_(0, phi.shape[2], name="k") as k: - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[i3, j, k, 1] - phi[i3, j, k, 2] - tmp1[0] = my_max(tmp1[0], phi[i3, j, k, 2]) - phi[i3, j, k, 0] = my_min(tmp1[0], phi[i3, j, k, 0]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[i3, j, k, phi.shape[2] - 2] - phi[i3, j, k, phi.shape[2] - 3] - tmp2[0] = my_max(tmp2[0], phi[i3, j, k, phi.shape[2] - 3]) - phi[i3, j, k, phi.shape[2] - 1] = my_min(tmp2[0], phi[i3, j, k, phi.shape[2] - 1]) - - - -######################################### VALUE ITERATION ########################################## - -def TTR_4D(my_object, g): - def solve_phiNew(phi, x1, x2, x3, x4): - l_i = 0 if 0 in g.pDim else 1 - h_i = phi.shape[0] if 0 in g.pDim else phi.shape[0] - 1 - l_j = 0 if 1 in g.pDim else 1 - h_j = phi.shape[1] if 1 in g.pDim else phi.shape[1] - 1 - l_k = 0 if 2 in g.pDim else 1 - h_k = phi.shape[2] if 2 in g.pDim else phi.shape[2] - 1 - l_l = 0 if 3 in g.pDim else 1 - h_l = phi.shape[3] if 3 in g.pDim else phi.shape[3] - 1 - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - updatePhi(i, j, k, l, my_object, phi, g, x1, x2, x3, x4) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - i2 = phi.shape[0] - i - 1 - j2 = phi.shape[1] - j - 1 - k2 = phi.shape[2] - k - 1 - updatePhi(i2, j2, k2, l, my_object, phi, g, x1, x2, x3, x4) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - j2 = phi.shape[1] - j - 1 - k2 = phi.shape[2] - k - 1 - updatePhi(i, j2, k2, l, my_object, phi, g, x1, x2, x3, x4) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - i2 = phi.shape[0] - i - 1 - j2 = phi.shape[1] - j - 1 - updatePhi(i2, j2, k, l, my_object, phi, g, x1, x2, x3, x4) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - i2 = phi.shape[0] - i - 1 - l2 = phi.shape[3] - l - 1 - updatePhi(i2, j, k, l2, my_object, phi, g, x1, x2, x3, x4) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - j2 = phi.shape[1] - j - 1 - l2 = phi.shape[3] - l - 1 - updatePhi(i, j2, k, l2, my_object, phi, g, x1, x2, x3, x4) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - k2 = phi.shape[2] - k - 1 - l2 = phi.shape[3] - l - 1 - updatePhi(i, j, k2, l2, my_object, phi, g, x1, x2, x3, x4) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - i2 = phi.shape[0] - i - 1 - j2 = phi.shape[1] - j - 1 - k2 = phi.shape[2] - k - 1 - l2 = phi.shape[3] - l - 1 - updatePhi(i2, j2, k2, l2, my_object, phi, g, x1, x2, x3, x4) - EvalBoundary(phi, g) - - - ###################################### SETUP PLACEHOLDERS ###################################### - - # Positions vector - x1 = hcl.placeholder((g.pts_each_dim[0],), name="x1", dtype=hcl.Float()) - x2 = hcl.placeholder((g.pts_each_dim[1],), name="x2", dtype=hcl.Float()) - x3 = hcl.placeholder((g.pts_each_dim[2],), name="x3", dtype=hcl.Float()) - x4 = hcl.placeholder((g.pts_each_dim[3],), name="x4", dtype=hcl.Float()) - phi = hcl.placeholder(tuple(g.pts_each_dim), name="phi", dtype=hcl.Float()) - # debugger = hcl.placeholder(tuple(g.pts_each_dim), name="debugger", dtype=hcl.Float()) - # debug2 = hcl.placeholder((0,), "debug2") - - # Create a static schedule -- graph - # s = hcl.create_schedule([phi, x1, x2, x3, x4, debugger, debug2], solve_phiNew) - - s = hcl.create_schedule([phi, x1, x2, x3, x4], solve_phiNew) - sweep_1 = solve_phiNew.Sweep_1 - sweep_2 = solve_phiNew.Sweep_2 - sweep_3 = solve_phiNew.Sweep_3 - sweep_4 = solve_phiNew.Sweep_4 - sweep_5 = solve_phiNew.Sweep_5 - sweep_6 = solve_phiNew.Sweep_6 - sweep_7 = solve_phiNew.Sweep_7 - sweep_8 = solve_phiNew.Sweep_8 - - # s[sweep_1].parallel(sweep_1.i) - # s[sweep_2].parallel(sweep_2.i) - # s[sweep_3].parallel(sweep_3.i) - # s[sweep_4].parallel(sweep_4.i) - # s[sweep_5].parallel(sweep_5.i) - # s[sweep_6].parallel(sweep_6.i) - # s[sweep_7].parallel(sweep_7.i) - # s[sweep_8].parallel(sweep_8.i) - - # Build an executable and return - return hcl.build(s) diff --git a/odp/TimeToReach/TimeToReach_5D.py b/odp/TimeToReach/TimeToReach_5D.py deleted file mode 100644 index 65e9e7b5..00000000 --- a/odp/TimeToReach/TimeToReach_5D.py +++ /dev/null @@ -1,296 +0,0 @@ -import heterocl as hcl -import numpy as np -from odp.computeGraphs.graph_5D import * - -######################################### HELPER FUNCTIONS ######################################### - -# Update the phi function at position (i,j,k) -def updatePhi(i, j, k, l, m, my_object, phi, g, x1, x2, x3, x4, x5): - dV_dx1_L = hcl.scalar(0, "dV_dx1_L") - dV_dx1_R = hcl.scalar(0, "dV_dx1_R") - dV_dx1 = hcl.scalar(0, "dV_dx1") - dV_dx2_L = hcl.scalar(0, "dV_dx2_L") - dV_dx2_R = hcl.scalar(0, "dV_dx2_R") - dV_dx2 = hcl.scalar(0, "dV_dx2") - dV_dx3_L = hcl.scalar(0, "dV_dx3_L") - dV_dx3_R = hcl.scalar(0, "dV_dx3_R") - dV_dx3 = hcl.scalar(0, "dV_dx3") - dV_dx4_L = hcl.scalar(0, "dV_dx4_L") - dV_dx4_R = hcl.scalar(0, "dV_dx4_R") - dV_dx4 = hcl.scalar(0, "dV_dx4") - dV_dx5_L = hcl.scalar(0, "dV_dx5_L") - dV_dx5_R = hcl.scalar(0, "dV_dx5_R") - dV_dx5 = hcl.scalar(0, "dV_dx5") - - sigma1 = hcl.scalar(0, "sigma1") - sigma2 = hcl.scalar(0, "sigma2") - sigma3 = hcl.scalar(0, "sigma3") - sigma4 = hcl.scalar(0, "sigma4") - sigma5 = hcl.scalar(0, "sigma5") - - # dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - dV_dx1_L[0], dV_dx1_R[0] = spa_derivX1_5d(i, j, k, l, m, phi, g) - dV_dx2_L[0], dV_dx2_R[0] = spa_derivX2_5d(i, j, k, l, m, phi, g) - dV_dx3_L[0], dV_dx3_R[0] = spa_derivX3_5d(i, j, k, l, m, phi, g) - dV_dx4_L[0], dV_dx4_R[0] = spa_derivX4_5d(i, j, k, l, m, phi, g) - dV_dx5_L[0], dV_dx5_R[0] = spa_derivX5_5d(i, j, k, l, m, phi, g) - - # Calculate average gradient - dV_dx1[0] = (dV_dx1_L[0] + dV_dx1_R[0]) / 2 - dV_dx2[0] = (dV_dx2_L[0] + dV_dx2_R[0]) / 2 - dV_dx3[0] = (dV_dx3_L[0] + dV_dx3_R[0]) / 2 - dV_dx4[0] = (dV_dx4_L[0] + dV_dx4_R[0]) / 2 - dV_dx5[0] = (dV_dx5_L[0] + dV_dx5_R[0]) / 2 - - # Find the optimal control through my_object's API - uOpt = my_object.opt_ctrl(0, (x1[i], x2[j], x3[k], x4[l], x5[m]), - (dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0])) - # Find optimal disturbance - dOpt = my_object.opt_dstb((dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0])) - - # Find rates of changes based on dynamics equation - dx1_dt, dx2_dt, dx3_dt, dx4_dt, dx5_dt = my_object.dynamics(0, (x1[i], x2[j], x3[k], x4[l], x5[m]), uOpt, dOpt) - - H = hcl.scalar(0, "H") - phiNew = hcl.scalar(0, "phiNew") - diss1 = hcl.scalar(0, "diss1") - diss2 = hcl.scalar(0, "diss2") - diss3 = hcl.scalar(0, "diss3") - diss4 = hcl.scalar(0, "diss4") - diss5 = hcl.scalar(0, "diss5") - - # Calculate Hamiltonian terms: - H[0] = (-(dx1_dt * dV_dx1[0] + dx2_dt * dV_dx2[0] + dx3_dt * dV_dx3[0] + dx4_dt * dV_dx4[0] - + dx5_dt * dV_dx5[0] + 1)) - - # Calculate the "dissipation" - sigma1[0] = my_abs(dx1_dt) - sigma2[0] = my_abs(dx2_dt) - sigma3[0] = my_abs(dx3_dt) - sigma4[0] = my_abs(dx4_dt) - sigma5[0] = my_abs(dx5_dt) - - c = hcl.scalar(0, "c") - c[0] = sigma1[0] / g.dx[0] + sigma2[0] / g.dx[1] + sigma3[0] / g.dx[2] \ - + sigma4[0] / g.dx[3] + sigma5[0] / g.dx[4] - - diss1[0] = sigma1[0] * ((dV_dx1_R[0] - dV_dx1_L[0]) / 2 + phi[i, j, k, l, m] / g.dx[0]) - diss2[0] = sigma2[0] * ((dV_dx2_R[0] - dV_dx2_L[0]) / 2 + phi[i, j, k, l, m] / g.dx[1]) - diss3[0] = sigma3[0] * ((dV_dx3_R[0] - dV_dx3_L[0]) / 2 + phi[i, j, k, l, m] / g.dx[2]) - diss4[0] = sigma4[0] * ((dV_dx4_R[0] - dV_dx4_L[0]) / 2 + phi[i, j, k, l, m] / g.dx[3]) - diss5[0] = sigma5[0] * ((dV_dx5_R[0] - dV_dx5_L[0]) / 2 + phi[i, j, k, l, m] / g.dx[4]) - - # New phi - phiNew[0] = (-H[0] + diss1[0] + diss2[0] + diss3[0] + diss4[0] + diss5[0]) / c[0] - #debugger[i, j, k, l] = phiNew[0] - phi[i, j, k, l, m] = my_min(phi[i, j, k, l, m], phiNew[0]) - -def EvalBoundary(phi, g): - if 0 not in g.pDim: - with hcl.for_(0, phi.shape[1], name="j") as j: - with hcl.for_(0, phi.shape[2], name="k") as k: - with hcl.for_(0, phi.shape[3], name="l") as l: - with hcl.for_(0, phi.shape[4], name="m") as m: - #debug2[0] = j - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[1, j, k, l, m] - phi[2, j, k, l, m] - tmp1[0] = my_max(tmp1[0], phi[2, j, k, l, m]) - phi[0, j, k, l, m] = my_min(tmp1[0], phi[0, j, k, l, m]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[phi.shape[0] - 2, j, k, l, m] - phi[phi.shape[0] - 3, j, k, l, m] - tmp2[0] = my_max(tmp2[0], phi[phi.shape[0] - 3, j, k, l, m]) - phi[phi.shape[0] - 1, j, k, l, m] = my_min(tmp2[0], phi[phi.shape[0] - 1, j, k, l, m]) - - if 1 not in g.pDim: - with hcl.for_(0, phi.shape[0], name="i") as i: - with hcl.for_(0, phi.shape[2], name="k") as k: - with hcl.for_(0, phi.shape[3], name="l") as l: - with hcl.for_(0, phi.shape[4], name="m") as m: - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[i, 1, k, l] - phi[i, 2, k, l, m] - tmp1[0] = my_max(tmp1[0], phi[i, 2, k, l, m]) - phi[i, 0, k, l, m] = my_min(tmp1[0], phi[i, 0, k, l, m]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[i, phi.shape[1] - 2, k, l, m] - phi[i, phi.shape[1] - 3, k, l, m] - tmp2[0] = my_max(tmp2[0], phi[i, phi.shape[1] - 3, k, l, m]) - phi[i, phi.shape[1] - 1, k, l, m] = my_min(tmp2[0], phi[i, phi.shape[1] - 1, k, l, m]) - - if 2 not in g.pDim: - with hcl.for_(0, phi.shape[0], name="i") as i: - with hcl.for_(0, phi.shape[1], name="j") as j: - with hcl.for_(0, phi.shape[3], name="l") as l: - with hcl.for_(0, phi.shape[4], name="m") as m: - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[i, j, 1, l, m] - phi[i, j, 2, l, m] - tmp1[0] = my_max(tmp1[0], phi[i, j, 2, l, m]) - phi[i, j, 0, l, m] = my_min(tmp1[0], phi[i, j, 0, l, m]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[i, j, phi.shape[2] - 2, l, m] - phi[i, j, phi.shape[2] - 3, l, m] - tmp2[0] = my_max(tmp2[0], phi[i, j, phi.shape[2] - 3, l, m]) - phi[i, j, phi.shape[2] - 1, l, m] = my_min(tmp2[0], phi[i, j, phi.shape[2] - 1, l, m]) - - if 3 not in g.pDim: - with hcl.for_(0, phi.shape[0], name="i") as i: - with hcl.for_(0, phi.shape[1], name="j") as j: - with hcl.for_(0, phi.shape[2], name="k") as k: - with hcl.for_(0, phi.shape[4], name="m") as m: - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[i, j, k, 1, m] - phi[i, j, k, 2, m] - tmp1[0] = my_max(tmp1[0], phi[i, j, k, 2, m]) - phi[i, j, k, 0, m] = my_min(tmp1[0], phi[i, j, k, 0, m]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[i, j, k, phi.shape[2] - 2, m] - phi[i, j, k, phi.shape[2] - 3, m] - tmp2[0] = my_max(tmp2[0], phi[i, j, k, phi.shape[2] - 3, m]) - phi[i, j, k, phi.shape[2] - 1, m] = my_min(tmp2[0], phi[i, j, k, phi.shape[2] - 1, m]) - - if 4 not in g.pDim: - with hcl.for_(0, phi.shape[0], name="i") as i: - with hcl.for_(0, phi.shape[1], name="j") as j: - with hcl.for_(0, phi.shape[2], name="k") as k: - with hcl.for_(0, phi.shape[3], name="l") as l: - tmp1 = hcl.scalar(0, "tmp1") - tmp1[0] = 2 * phi[i, j, k, l, 1] - phi[i, j, k, l, 2] - tmp1[0] = my_max(tmp1[0], phi[i, j, k, l, 2]) - phi[i, j, k, l, 0] = my_min(tmp1[0], phi[i, j, k, l, 0]) - - tmp2 = hcl.scalar(0, "tmp2") - tmp2[0] = 2 * phi[i, j, k, l, phi.shape[2] - 2] - phi[i, j, k, l, phi.shape[2] - 3] - tmp2[0] = my_max(tmp2[0], phi[i, j, k, l, phi.shape[2] - 3]) - phi[i, j, k, l, phi.shape[2] - 1] = my_min(tmp2[0], phi[i, j, k, l, phi.shape[2] - 1]) - -######################################### VALUE ITERATION ########################################## - - -def TTR_5D(my_object, g): - def solve_phiNew(phi, x1, x2, x3, x4, x5): - l_i = 0 if 0 in g.pDim else 1 - h_i = phi.shape[0] if 0 in g.pDim else phi.shape[0] - 1 - l_j = 0 if 1 in g.pDim else 1 - h_j = phi.shape[1] if 1 in g.pDim else phi.shape[1] - 1 - l_k = 0 if 2 in g.pDim else 1 - h_k = phi.shape[2] if 2 in g.pDim else phi.shape[2] - 1 - l_l = 0 if 3 in g.pDim else 1 - h_l = phi.shape[3] if 3 in g.pDim else phi.shape[3] - 1 - l_m = 0 if 4 in g.pDim else 1 - h_m = phi.shape[4] if 4 in g.pDim else phi.shape[4] - 1 - - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - with hcl.for_(l_m, h_m, name="m") as m: - updatePhi(i, j, k, l, m, my_object, phi, g, x1, x2, x3, x4, x5) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - with hcl.for_(l_m, h_m, name="m") as m: - i2 = phi.shape[0] - i - 1 - j2 = phi.shape[1] - j - 1 - k2 = phi.shape[2] - k - 1 - l2 = phi.shape[3] - l - 1 - m2 = phi.shape[4] - m - 1 - updatePhi(i2, j2, k2, l2, m2, my_object, phi, g, x1, x2, x3, x4, x5) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - with hcl.for_(l_m, h_m, name="m") as m: - i2 = phi.shape[0] - i - 1 - j2 = phi.shape[1] - j - 1 - k2 = phi.shape[2] - k - 1 - l2 = phi.shape[3] - l - 1 - updatePhi(i2, j2, k2, l2, m, my_object, phi, g, x1, x2, x3, x4, x5) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - with hcl.for_(l_m, h_m, name="m") as m: - i2 = phi.shape[0] - i - 1 - j2 = phi.shape[1] - j - 1 - k2 = phi.shape[2] - k - 1 - updatePhi(i2, j2, k2, l, m, my_object, phi, g, x1, x2, x3, x4, x5) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - with hcl.for_(l_m, h_m, name="m") as m: - i2 = phi.shape[0] - i - 1 - j2 = phi.shape[1] - j - 1 - updatePhi(i2, j2, k, l, m, my_object, phi, g, x1, x2, x3, x4, x5) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - with hcl.for_(l_m, h_m, name="m") as m: - i2 = phi.shape[0] - i - 1 - updatePhi(i2, j, k, l, m, my_object, phi, g, x1, x2, x3, x4, x5) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - with hcl.for_(l_m, h_m, name="m") as m: - j2 = phi.shape[1] - j - 1 - updatePhi(i, j2, k, l, m, my_object, phi, g, x1, x2, x3, x4, x5) - EvalBoundary(phi, g) - - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - with hcl.for_(l_i, h_i, name="i") as i: - with hcl.for_(l_j, h_j, name="j") as j: - with hcl.for_(l_k, h_k, name="k") as k: - with hcl.for_(l_l, h_l, name="l") as l: - with hcl.for_(l_m, h_m, name="m") as m: - j2 = phi.shape[1] - j - 1 - k2 = phi.shape[2] - k - 1 - updatePhi(i, j2, k2, l, m, my_object, phi, g, x1, x2, x3, x4, x5) - EvalBoundary(phi, g) - - - ###################################### SETUP PLACEHOLDERS ###################################### - - # Positions vector - x1 = hcl.placeholder((g.pts_each_dim[0],), name="x1", dtype=hcl.Float()) - x2 = hcl.placeholder((g.pts_each_dim[1],), name="x2", dtype=hcl.Float()) - x3 = hcl.placeholder((g.pts_each_dim[2],), name="x3", dtype=hcl.Float()) - x4 = hcl.placeholder((g.pts_each_dim[3],), name="x4", dtype=hcl.Float()) - x5 = hcl.placeholder((g.pts_each_dim[4],), name="x5", dtype=hcl.Float()) - phi = hcl.placeholder(tuple(g.pts_each_dim), name="phi", dtype=hcl.Float()) - debugger = hcl.placeholder(tuple(g.pts_each_dim), name="debugger", dtype=hcl.Float()) - debug2 = hcl.placeholder((0,), "debug2") - - # Create a static schedule -- graph - s = hcl.create_schedule([phi, x1, x2, x3, x4, x5, debugger, debug2], solve_phiNew) - - # Build an executable and return - return hcl.build(s) diff --git a/odp/TimeToReach/TimeToReach_6D.py b/odp/TimeToReach/TimeToReach_6D.py deleted file mode 100644 index ed220356..00000000 --- a/odp/TimeToReach/TimeToReach_6D.py +++ /dev/null @@ -1,316 +0,0 @@ -import heterocl as hcl -import numpy as np -import time -import user_definer_6D as UD - - - -######################################### HELPER FUNCTIONS ######################################### - - -# Update the value function at position (i,j,k,l,m,n) -# iVals: holds index values (i,j,k,l,m,n) that correspond to state values (si,sj,sk,sl,sm,sn) -# intermeds: holds the estimated value associated with taking each action -# interpV: holds the estimated value of a successor state (linear interpolation only) -# gamma: discount factor -# ptsEachDim: the number of grid points in each dimension of the state space -# useNN: a mode flag (0: use linear interpolation, 1: use nearest neighbour) -def updateVopt(i, j, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN): - p = hcl.scalar(0, "p") - - with hcl.for_(0, actions.shape[0], name="a") as a: - # set iVals equal to (i,j,k,l,m,n) and sVals equal to the corresponding state values (si,sj,sk,sl,sm,sn) - updateStateVals(i, j, k, l, m, n, iVals, sVals, bounds, ptsEachDim) - # call the transition function to obtain the outcome(s) of action a from state (si,sj,sk,sl,sm,sn) - UD.transition(sVals, actions[a], bounds, trans, goal) - # initialize the value of the action Q value with the immediate reward of taking that action - intermeds[a] = UD.reward(sVals, actions[a], bounds, goal, trans) - # add the value of each possible successor state to the Q value - with hcl.for_(0, trans.shape[0], name="si") as si: - p[0] = trans[si,0] - sVals[0] = trans[si,1] - sVals[1] = trans[si,2] - sVals[2] = trans[si,3] - sVals[3] = trans[si,4] - sVals[4] = trans[si,5] - sVals[5] = trans[si,6] - - # Nearest neighbour - with hcl.if_(useNN[0] == 1): - # convert the state values of the successor state (si,sj,sk,sl,sm,sn) into indeces (ia,ja,ka,la,ma,na) - stateToIndex(sVals, iVals, bounds, ptsEachDim) - # if (ia,ja,ka,la,ma,na) is within the state space, add its discounted value to the Q value - with hcl.if_(hcl.and_(iVals[0] < Vopt.shape[0], iVals[1] < Vopt.shape[1], iVals[2] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iVals[3] < Vopt.shape[3], iVals[4] < Vopt.shape[4], iVals[5] < Vopt.shape[5])): - with hcl.if_(hcl.and_(iVals[0] >= 0, iVals[1] >= 0, iVals[2] >= 0, iVals[3] >= 0, iVals[4] >= 0, iVals[5] >= 0)): - intermeds[a] += (gamma[0] * (p[0] * Vopt[iVals[0], iVals[1], iVals[2], iVals[3], iVals[4], iVals[5]])) - - # maximize over each Q value to obtain the optimal value - Vopt[i,j,k,l,m,n] = -1000000 - with hcl.for_(0, intermeds.shape[0], name="r") as r: - with hcl.if_(Vopt[i,j,k,l,m,n] < intermeds[r]): - Vopt[i,j,k,l,m,n] = intermeds[r] - - -# Returns 0 if convergence has been reached -def evaluateConvergence(newV, oldV, epsilon, reSweep): - delta = hcl.scalar(0, "delta") - # Calculate the difference, if it's negative, make it positive - delta[0] = newV[0] - oldV[0] - with hcl.if_(delta[0] < 0): - delta[0] = delta[0] * -1 - with hcl.if_(delta[0] > epsilon[0]): - reSweep[0] = 1 - - -# Converts state values into indeces using nearest neighbour rounding -def stateToIndex(sVals, iVals, bounds, ptsEachDim): - iVals[0] = ((sVals[0] - bounds[0,0]) / (bounds[0,1] - bounds[0,0])) * (ptsEachDim[0] - 1) - iVals[1] = ((sVals[1] - bounds[1,0]) / (bounds[1,1] - bounds[1,0])) * (ptsEachDim[1] - 1) - iVals[2] = ((sVals[2] - bounds[2,0]) / (bounds[2,1] - bounds[2,0])) * (ptsEachDim[2] - 1) - iVals[3] = ((sVals[3] - bounds[3,0]) / (bounds[3,1] - bounds[3,0])) * (ptsEachDim[3] - 1) - iVals[4] = ((sVals[4] - bounds[4,0]) / (bounds[4,1] - bounds[4,0])) * (ptsEachDim[4] - 1) - iVals[5] = ((sVals[5] - bounds[5,0]) / (bounds[5,1] - bounds[5,0])) * (ptsEachDim[5] - 1) - # NOTE: add 0.5 to simulate rounding - iVals[0] = hcl.cast(hcl.Int(), iVals[0] + 0.5) - iVals[1] = hcl.cast(hcl.Int(), iVals[1] + 0.5) - iVals[2] = hcl.cast(hcl.Int(), iVals[2] + 0.5) - iVals[3] = hcl.cast(hcl.Int(), iVals[3] + 0.5) - iVals[4] = hcl.cast(hcl.Int(), iVals[4] + 0.5) - iVals[5] = hcl.cast(hcl.Int(), iVals[5] + 0.5) - - -# Convert indices into state values -def indexToState(iVals, sVals, bounds, ptsEachDim): - sVals[0] = bounds[0,0] + ( (bounds[0,1] - bounds[0,0]) * (iVals[0] / (ptsEachDim[0]-1)) ) - sVals[1] = bounds[1,0] + ( (bounds[1,1] - bounds[1,0]) * (iVals[1] / (ptsEachDim[1]-1)) ) - sVals[2] = bounds[2,0] + ( (bounds[2,1] - bounds[2,0]) * (iVals[2] / (ptsEachDim[2]-1)) ) - sVals[3] = bounds[3,0] + ( (bounds[3,1] - bounds[3,0]) * (iVals[3] / (ptsEachDim[3]-1)) ) - sVals[4] = bounds[4,0] + ( (bounds[4,1] - bounds[4,0]) * (iVals[4] / (ptsEachDim[4]-1)) ) - sVals[5] = bounds[5,0] + ( (bounds[5,1] - bounds[5,0]) * (iVals[5] / (ptsEachDim[5]-1)) ) - - -# Sets iVals equal to (i,j,k,l,m,n) and sVals equal to the corresponding state values -def updateStateVals(i, j, k, l, m, n, iVals, sVals, bounds, ptsEachDim): - iVals[0] = i - iVals[1] = j - iVals[2] = k - iVals[3] = l - iVals[4] = m - iVals[5] = n - indexToState(iVals, sVals, bounds, ptsEachDim) - - - -######################################### VALUE ITERATION ########################################## - - -# Main value iteration algorithm -# reSweep: a convergence flag (1: continue iterating, 0: convergence reached) -# epsilon: convergence criteria -# maxIters: maximum number of iterations that can occur without convergence being reached -# count: the number of iterations that have been performed -def value_iteration_6D(): - def solve_Vopt(Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN): - reSweep = hcl.scalar(1, "reSweep") - oldV = hcl.scalar(0, "oldV") - newV = hcl.scalar(0, "newV") - with hcl.while_(hcl.and_(reSweep[0] == 1, count[0] < maxIters[0])): - reSweep[0] = 0 - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - oldV[0] = Vopt[i,j,k,l,m,n] - updateVopt(i, j, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j2,k2,l,m,n] - updateVopt(i2, j2, k2, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k2,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - i2 = Vopt.shape[0] - i - oldV[0] = Vopt[i2,j,k,l,m,n] - updateVopt(i2, j, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i,j2,k,l,m,n] - updateVopt(i, j2, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j,k2,l,m,n] - updateVopt(i, j, k2, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k2,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i2,j2,k,l,m,n] - updateVopt(i2, j2, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - i2 = Vopt.shape[0] - i - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j,k2,l,m,n] - updateVopt(i2, j, k2, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k2,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j2,k2,l,m,n] - updateVopt(i, j2, k2, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k2,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - - - ###################################### SETUP PLACEHOLDERS ###################################### - - # Initialize the HCL environment - hcl.init() - hcl.config.init_dtype = hcl.Float() - - # NOTE: trans is a tensor with size = maximum number of transitions - # NOTE: intermeds must have size [# possible actions] - # NOTE: transition must have size [# possible outcomes, #state dimensions + 1] - Vopt = hcl.placeholder(tuple(UD._ptsEachDim), name="Vopt", dtype=hcl.Float()) - gamma = hcl.placeholder((0,), "gamma") - count = hcl.placeholder((0,), "count") - maxIters = hcl.placeholder((0,), "maxIters") - epsilon = hcl.placeholder((0,), "epsilon") - actions = hcl.placeholder(tuple(UD._actions.shape), name="actions", dtype=hcl.Float()) - intermeds = hcl.placeholder(tuple([UD._actions.shape[0]]), name="intermeds", dtype=hcl.Float()) - trans = hcl.placeholder(tuple(UD._trans.shape), name="successors", dtype=hcl.Float()) - bounds = hcl.placeholder(tuple(UD._bounds.shape), name="bounds", dtype=hcl.Float()) - goal = hcl.placeholder(tuple(UD._goal.shape), name="goal", dtype=hcl.Float()) - ptsEachDim = hcl.placeholder(tuple([6]), name="ptsEachDim", dtype=hcl.Float()) - sVals = hcl.placeholder(tuple([6]), name="sVals", dtype=hcl.Float()) - iVals = hcl.placeholder(tuple([6]), name="iVals", dtype=hcl.Float()) - interpV = hcl.placeholder((0,), "interpols") - useNN = hcl.placeholder((0,), "useNN") - - # Create a static schedule -- graph - s = hcl.create_schedule([Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN], solve_Vopt) - - - ########################################## INITIALIZE ########################################## - - # Convert the python array to hcl type array - V_opt = hcl.asarray(np.zeros(UD._ptsEachDim)) - intermeds = hcl.asarray(np.ones(UD._actions.shape[0])) - trans = hcl.asarray(UD._trans) - gamma = hcl.asarray(UD._gamma) - epsilon = hcl.asarray(UD._epsilon) - count = hcl.asarray(np.zeros(1)) - maxIters = hcl.asarray(UD._maxIters) - actions = hcl.asarray(UD._actions) - bounds = hcl.asarray(UD._bounds) - goal = hcl.asarray(UD._goal) - ptsEachDim = hcl.asarray(UD._ptsEachDim) - sVals = hcl.asarray(np.zeros([6])) - iVals = hcl.asarray(np.zeros([6])) - interpV = hcl.asarray(np.zeros([1])) - useNN = hcl.asarray(UD._useNN) - - # Use this graph and build an executable - f = hcl.build(s, target="llvm") - - - ########################################### EXECUTE ############################################ - - # Now use the executable - t_s = time.time() - f(V_opt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN) - t_e = time.time() - - V = V_opt.asnumpy() - c = count.asnumpy() - print("Finished in ", int(c[0]), " iterations") - print("Took ", t_e-t_s, " seconds") - - # Write results to file - dir_path = "./hcl_value_matrix_test/" - file_name = "hcl_value_iteration_6D_" + str(int(c[0])) + "_iterations_by" + ("_Interpolation" if UD._useNN[0] == 0 else "_NN") - UD.writeResults(V, dir_path, file_name, just_values=False) - - -# Call the function -value_iteration_6D() diff --git a/odp/TimeToReach/__init__.py b/odp/TimeToReach/__init__.py deleted file mode 100644 index 519f86d4..00000000 --- a/odp/TimeToReach/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from odp.TimeToReach.TimeToReach_3D import TTR_3D -from odp.TimeToReach.TimeToReach_4D import TTR_4D -from odp.TimeToReach.TimeToReach_5D import TTR_5D -# from odp.TimeToReach.TimeToReach_6D import TTR_6D \ No newline at end of file diff --git a/odp/__init__.py b/odp/__init__.py new file mode 100644 index 00000000..111db558 --- /dev/null +++ b/odp/__init__.py @@ -0,0 +1,5 @@ +from . import dynamics +from . import shapes +from . import math + +from .grid import Grid diff --git a/odp/computeGraphs/CustomGraphFunctions.py b/odp/computeGraphs/CustomGraphFunctions.py deleted file mode 100644 index 37039784..00000000 --- a/odp/computeGraphs/CustomGraphFunctions.py +++ /dev/null @@ -1,121 +0,0 @@ -import heterocl as hcl -import numpy as np -# Custom function - -def my_min(a,b): - result = hcl.scalar(0, "result") - with hcl.if_(a < b): - result[0] = a - with hcl.else_(): - result[0] = b - return result[0] - -# Input is value, output is value -def my_max(a,b): - result = hcl.scalar(0, "result") - with hcl.if_(a > b): - result.v = a - with hcl.else_(): - result.v = b - return result.v - -# Input is value, output is value -def max_4n(num1, num2, num3, num4): - largest = hcl.scalar(0, "largest") - largest[0] = my_max(num1, num2) - largest[0] = my_max(largest[0], num3) - largest[0] = my_max(largest[0], num4) - - return largest[0] - -# Input is a value, output is value -def my_abs(my_x): - abs_value = hcl.scalar(0, "abs_value", dtype=hcl.Float()) - with hcl.if_(my_x > 0): - abs_value.v = my_x - with hcl.else_(): - abs_value.v = -my_x - return abs_value.v - -def new_abs(my_x): - my_value = hcl.scalar(0, "my_value", dtype=hcl.Float()) - with hcl.if_(my_x > 0): - my_value.v = my_x - with hcl.else_(): - my_value.v = -my_x - return my_value.v - -def my_sign(x): - sign = hcl.scalar(0, "sign", dtype=hcl.Float()) - with hcl.if_(x == 0): - sign[0] = 0 - with hcl.if_(x > 0): - sign[0] = 1 - with hcl.if_(x < 0): - sign[0] = -1 - return sign[0] - -# ########################## 3D SPATIAL DERIVATIVE FUNCTION ################################# -# -# def spa_derivX(i, j, k, V, g): -# left_deriv = hcl.scalar(0, "left_deriv") -# right_deriv = hcl.scalar(0, "right_deriv") -# with hcl.if_(i == 0): -# left_boundary = hcl.scalar(0, "left_boundary") -# left_boundary[0] = V[k, j, i] + my_abs(V[k, j, i + 1] - V[k, j, i]) * my_sign( -# V[k, j, i]) -# left_deriv[0] = (V[k, j, i] - left_boundary[0]) / g.dx[0] -# right_deriv[0] = (V[k, j, i + 1] - V[k, j, i]) / g.dx[0] -# with hcl.elif_(i == V.shape[2] - 1): -# right_boundary = hcl.scalar(0, "right_boundary") -# right_boundary[0] = V[k, j, i] + my_abs(V[k, j, i] - V[k, j, i - 1]) * my_sign( -# V[k, j, i]) -# left_deriv[0] = (V[k, j, i] - V[k, j, i - 1]) / g.dx[0] -# right_deriv[0] = (right_boundary[0] - V[k, j, i]) / g.dx[0] -# with hcl.elif_(i != 0 and i != V.shape[2] - 1): -# left_deriv[0] = (V[k, j, i] - V[k, j, i-1]) / g.dx[0] -# right_deriv[0] = (V[k, j, i+1] - V[k, j, i]) / g.dx[0] -# return left_deriv[0], right_deriv[0] -# -# -# def spa_derivY(i, j, k, V, g): -# left_deriv = hcl.scalar(0, "left_deriv") -# right_deriv = hcl.scalar(0, "right_deriv") -# with hcl.if_(j == 0): -# left_boundary = hcl.scalar(0, "left_boundary") -# left_boundary[0] = V[k, j, i] + my_abs(V[k, j + 1, i] - V[k, j, i]) * my_sign( -# V[k, j, i]) -# left_deriv[0] = (V[k, j, i] - left_boundary[0]) / g.dx[1] -# right_deriv[0] = (V[k, j + 1, i] - V[k, j, i]) / g.dx[1] -# with hcl.elif_(j == V.shape[1] - 1): -# right_boundary = hcl.scalar(0, "right_boundary") -# right_boundary[0] = V[k, j, i] + my_abs(V[k, j, i] - V[k, j - 1, i]) * my_sign( -# V[k, j, i]) -# left_deriv[0] = (V[k, j, i] - V[k, j - 1, i]) / g.dx[1] -# right_deriv[0] = (right_boundary[0] - V[k, j, i]) / g.dx[1] -# with hcl.elif_(j != 0 and j != V.shape[1] - 1): -# left_deriv[0] = (V[k, j, i] - V[k, j - 1, i]) / g.dx[1] -# right_deriv[0] = (V[k, j + 1, i] - V[k, j, i]) / g.dx[1] -# return left_deriv[0], right_deriv[0] -# -# def spa_derivT(i, j, k, V, g): -# left_deriv = hcl.scalar(0, "left_deriv") -# right_deriv = hcl.scalar(0, "right_deriv") -# with hcl.if_(k == 0): -# left_boundary = hcl.scalar(0, "left_boundary") -# # left_boundary[0] = V_init[i,j,50] -# left_boundary[0] = V[V.shape[0] - 1, j, i] -# left_deriv[0] = (V[k, j, i] - left_boundary[0]) / g.dx[2] -# right_deriv[0] = (V[k + 1, j, i] - V[k, j, i]) / g.dx[2] -# with hcl.elif_(k == V.shape[0] - 1): -# right_boundary = hcl.scalar(0, "right_boundary") -# right_boundary[0] = V[0, j, i] -# left_deriv[0] = (V[k, j, i] - V[k-1, j, i]) / g.dx[2] -# right_deriv[0] = (right_boundary[0] - V[k, j, i]) / g.dx[2] -# with hcl.elif_(k != 0 and k != V.shape[0] - 1): -# left_deriv[0] = (V[k, j, i] - V[k-1, j, i]) / g.dx[2] -# right_deriv[0] = (V[k+1, j, i] - V[k, j, i]) / g.dx[2] -# return left_deriv[0], right_deriv[0] - - - diff --git a/odp/computeGraphs/__init__.py b/odp/computeGraphs/__init__.py deleted file mode 100644 index aef90920..00000000 --- a/odp/computeGraphs/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from odp.computeGraphs.graph_3D import graph_3D -from odp.computeGraphs.graph_4D import graph_4D -from odp.computeGraphs.graph_5D import graph_5D -from odp.computeGraphs.graph_6D import graph_6D \ No newline at end of file diff --git a/odp/computeGraphs/graph_3D.py b/odp/computeGraphs/graph_3D.py deleted file mode 100644 index f97ff59c..00000000 --- a/odp/computeGraphs/graph_3D.py +++ /dev/null @@ -1,332 +0,0 @@ -import heterocl as hcl -import numpy as np -from odp.computeGraphs.CustomGraphFunctions import * -from odp.spatialDerivatives.first_orderENO3D import * -from odp.spatialDerivatives.second_orderENO3D import * - -#from user_definer import * -#def graph_3D(dynamics_obj, grid): -def graph_3D(my_object, g, compMethod, accuracy, generate_SpatDeriv=False, deriv_dim=1): - V_f = hcl.placeholder(tuple(g.pts_each_dim), name="V_f", dtype=hcl.Float()) - V_init = hcl.placeholder(tuple(g.pts_each_dim), name="V_init", dtype=hcl.Float()) - l0 = hcl.placeholder(tuple(g.pts_each_dim), name="l0", dtype=hcl.Float()) - t = hcl.placeholder((2,), name="t", dtype=hcl.Float()) - probe = hcl.placeholder(tuple(g.pts_each_dim), name="probe", dtype=hcl.Float()) - - # Positions vector - x1 = hcl.placeholder((g.pts_each_dim[0],), name="x1", dtype=hcl.Float()) - x2 = hcl.placeholder((g.pts_each_dim[1],), name="x2", dtype=hcl.Float()) - x3 = hcl.placeholder((g.pts_each_dim[2],), name="x3", dtype=hcl.Float()) - def graph_create(V_new, V_init, x1, x2, x3, t, l0): - # Specify intermediate tensors - deriv_diff1 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff1") - deriv_diff2 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff2") - deriv_diff3 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff3") - - # Maximum derivative for each dim - max_deriv1 = hcl.scalar(-1e9, "max_deriv1") - max_deriv2 = hcl.scalar(-1e9, "max_deriv2") - max_deriv3 = hcl.scalar(-1e9, "max_deriv3") - - # Min derivative for each dim - min_deriv1 = hcl.scalar(1e9, "min_deriv1") - min_deriv2 = hcl.scalar(1e9, "min_deriv2") - min_deriv3 = hcl.scalar(1e9, "min_deriv3") - - # These variables are used to dissipation calculation - max_alpha1 = hcl.scalar(-1e9, "max_alpha1") - max_alpha2 = hcl.scalar(-1e9, "max_alpha2") - max_alpha3 = hcl.scalar(-1e9, "max_alpha3") - def step_bound(): # Function to calculate time step - stepBoundInv = hcl.scalar(0, "stepBoundInv") - stepBound = hcl.scalar(0, "stepBound") - stepBoundInv[0] = max_alpha1[0] / g.dx[0] + max_alpha2[0] / g.dx[1] + max_alpha3[0] / g.dx[2] - stepBound[0] = 0.8 / stepBoundInv[0] - with hcl.if_(stepBound > t[1] - t[0]): - stepBound[0] = t[1] - t[0] - t[0] = t[0] + stepBound[0] - return stepBound[0] - - # Min with V_before - def minVWithVInit(i, j, k): - with hcl.if_(V_new[i, j, k] > V_init[i, j, k]): - V_new[i, j, k] = V_init[i, j, k] - - def maxVWithVInit(i, j, k): - with hcl.if_(V_new[i, j, k] < V_init[i, j, k]): - V_new[i, j, k] = V_init[i, j, k] - - def maxVWithV0(i, j, k): # Take the max - with hcl.if_(V_new[i, j, k] < l0[i, j, k]): - V_new[i, j, k] = l0[i, j, k] - - def minVWithV0(i, j, k): - with hcl.if_(V_new[i, j, k] > l0[i, j, k]): - V_new[i, j, k] = l0[i, j, k] - - # Calculate Hamiltonian for every grid point in V_init - with hcl.Stage("Hamiltonian"): - with hcl.for_(0, V_init.shape[0], name="i") as i: # Plus 1 as for loop count stops at V_init.shape[0] - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - # Variables to calculate dV_dx - dV_dx_L = hcl.scalar(0, "dV_dx_L") - dV_dx_R = hcl.scalar(0, "dV_dx_R") - dV_dx = hcl.scalar(0, "dV_dx") - # Variables to calculate dV_dy - dV_dy_L = hcl.scalar(0, "dV_dy_L") - dV_dy_R = hcl.scalar(0, "dV_dy_R") - dV_dy = hcl.scalar(0, "dV_dy") - # Variables to calculate dV_dtheta - dV_dT_L = hcl.scalar(0, "dV_dT_L") - dV_dT_R = hcl.scalar(0, "dV_dT_R") - dV_dT = hcl.scalar(0, "dV_dT") - - # No tensor slice operation - if accuracy == "low": - dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k, V_init, g) - dV_dy_L[0], dV_dy_R[0] = spa_derivY(i, j, k, V_init, g) - dV_dT_L[0], dV_dT_R[0] = spa_derivT(i, j, k, V_init, g) - if accuracy == "medium": - dV_dx_L[0], dV_dx_R[0] = secondOrderX(i, j, k, V_init, g) - dV_dy_L[0], dV_dy_R[0] = secondOrderY(i, j, k, V_init, g) - dV_dT_L[0], dV_dT_R[0] = secondOrderT(i, j, k, V_init, g) - - # Saves spatial derivative diff into tables - deriv_diff1[i, j, k] = dV_dx_R[0] - dV_dx_L[0] - deriv_diff2[i, j, k] = dV_dy_R[0] - dV_dy_L[0] - deriv_diff3[i, j, k] = dV_dT_R[0] - dV_dT_L[0] - - # Calculate average gradient - dV_dx[0] = (dV_dx_L + dV_dx_R) / 2 - dV_dy[0] = (dV_dy_L + dV_dy_R) / 2 - dV_dT[0] = (dV_dT_L + dV_dT_R) / 2 - - # Use method of DubinsCar to solve optimal control instead - uOpt = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k]), - (dV_dx[0], dV_dy[0], dV_dT[0])) - dOpt = my_object.opt_dstb(t, (x1[i], x2[j], x3[k]), - (dV_dx[0], dV_dy[0], dV_dT[0])) - - # Calculate dynamical rates of changes - dx_dt, dy_dt, dtheta_dt = my_object.dynamics(t, (x1[i], x2[j], x3[k]), uOpt, dOpt) - - # Calculate Hamiltonian terms: - V_new[i, j, k] = -(dx_dt * dV_dx[0] + dy_dt * dV_dy[0] + dtheta_dt * dV_dT[0]) - - # Get derivMin - with hcl.if_(dV_dx_L[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx_L[0] - with hcl.if_(dV_dx_R[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx_R[0] - - with hcl.if_(dV_dy_L[0] < min_deriv2[0]): - min_deriv2[0] = dV_dy_L[0] - with hcl.if_(dV_dy_R[0] < min_deriv2[0]): - min_deriv2[0] = dV_dy_R[0] - - with hcl.if_(dV_dT_L[0] < min_deriv3[0]): - min_deriv3[0] = dV_dT_L[0] - with hcl.if_(dV_dT_R[0] < min_deriv3[0]): - min_deriv3[0] = dV_dT_R[0] - - # Get derivMax - with hcl.if_(dV_dx_L[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx_L[0] - with hcl.if_(dV_dx_R[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx_R[0] - - with hcl.if_(dV_dy_L[0] > max_deriv2[0]): - max_deriv2[0] = dV_dy_L[0] - with hcl.if_(dV_dy_R[0] > max_deriv2[0]): - max_deriv2[0] = dV_dy_R[0] - - with hcl.if_(dV_dT_L[0] > max_deriv3[0]): - max_deriv3[0] = dV_dT_L[0] - with hcl.if_(dV_dT_R[0] > max_deriv3[0]): - max_deriv3[0] = dV_dT_R[0] - - # Calculate the dissipation - with hcl.Stage("Dissipation"): - # Storing alphas - dOptL1 = hcl.scalar(0, "dOptL1") - dOptL2 = hcl.scalar(0, "dOptL2") - dOptL3 = hcl.scalar(0, "dOptL3") - # Find UPPER BOUND optimal disturbance - dOptU1 = hcl.scalar(0, "dOptU1") - dOptU2 = hcl.scalar(0, "dOptU2") - dOptU3 = hcl.scalar(0, "dOptU3") - - alpha1 = hcl.scalar(0, "alpha1") - alpha2 = hcl.scalar(0, "alpha2") - alpha3 = hcl.scalar(0, "alpha3") - - # Lower bound optimal control - uOptL1 = hcl.scalar(0, "uOptL1") - uOptL2 = hcl.scalar(0, "uOptL2") - uOptL3 = hcl.scalar(0, "uOptL3") - - # Find UPPER BOUND optimal disturbance - uOptU1 = hcl.scalar(0, "uOptU1") - uOptU2 = hcl.scalar(0, "uOptU2") - uOptU3 = hcl.scalar(0, "uOptU3") - - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - dx_LL1 = hcl.scalar(0, "dx_LL1") - dx_LL2 = hcl.scalar(0, "dx_LL2") - dx_LL3 = hcl.scalar(0, "dx_LL3") - - dx_UL1 = hcl.scalar(0, "dx_UL1") - dx_UL2 = hcl.scalar(0, "dx_UL2") - dx_UL3 = hcl.scalar(0, "dx_UL3") - - dx_UU1 = hcl.scalar(0, "dx_UU1") - dx_UU2 = hcl.scalar(0, "dx_UU2") - dx_UU3 = hcl.scalar(0, "dx_UU3") - - dx_LU1 = hcl.scalar(0, "dx_LU1") - dx_LU2 = hcl.scalar(0, "dx_LU2") - dx_LU3 = hcl.scalar(0, "dx_LU3") - - # Find LOWER BOUND optimal disturbance - dOptL1[0], dOptL2[0], dOptL3[0] = my_object.opt_dstb(t, (x1[i], x2[j], x3[k]),\ - (min_deriv1[0], min_deriv2[0],min_deriv3[0])) - - dOptU1[0], dOptU2[0], dOptU3[0] = my_object.opt_dstb(t, (x1[i], x2[j], x3[k]),\ - (max_deriv1[0], max_deriv2[0],max_deriv3[0])) - - # Find LOWER BOUND optimal control - uOptL1[0], uOptL2[0], uOptL3[0] = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k]), \ - (min_deriv1[0], min_deriv2[0],min_deriv3[0])) - - # Find UPPER BOUND optimal control - uOptU1[0], uOptU2[0], uOptU3[0] = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k]), - (max_deriv1[0], max_deriv2[0], - max_deriv3[0])) - # Find magnitude of rates of changes - dx_LL1[0], dx_LL2[0], dx_LL3[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k]), - (uOptL1[0], uOptL2[0], uOptL3[0]), \ - (dOptL1[0], dOptL2[0], dOptL3[0])) - dx_LL1[0] = my_abs(dx_LL1[0]) - dx_LL2[0] = my_abs(dx_LL2[0]) - dx_LL3[0] = my_abs(dx_LL3[0]) - - dx_LU1[0], dx_LU2[0], dx_LU3[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k]), - (uOptL1[0], uOptL2[0], uOptL3[0]), \ - (dOptU1[0], dOptU2[0], dOptU3[0])) - dx_LU1[0] = my_abs(dx_LU1[0]) - dx_LU2[0] = my_abs(dx_LU2[0]) - dx_LU3[0] = my_abs(dx_LU3[0]) - - # Calculate alpha - alpha1[0] = my_max(dx_LL1[0], dx_LU1[0]) - alpha2[0] = my_max(dx_LL2[0], dx_LU2[0]) - alpha3[0] = my_max(dx_LL3[0], dx_LU3[0]) - - dx_UL1[0], dx_UL2[0], dx_UL3[0]= my_object.dynamics(t, (x1[i], x2[j], x3[k]),\ - (uOptU1[0], uOptU2[0], uOptU3[0]), \ - (dOptL1[0], dOptL2[0], dOptL3[0])) - dx_UL1[0] = my_abs(dx_UL1[0]) - dx_UL2[0] = my_abs(dx_UL2[0]) - dx_UL3[0] = my_abs(dx_UL3[0]) - - # Calculate alpha - alpha1[0] = my_max(alpha1[0], dx_UL1[0]) - alpha2[0] = my_max(alpha2[0], dx_UL2[0]) - alpha3[0] = my_max(alpha3[0], dx_UL3[0]) - - dx_UU1[0], dx_UU2[0], dx_UU3[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k]), - (uOptU1[0], uOptU2[0], uOptU3[0]),\ - (dOptU1[0], dOptU2[0], dOptU3[0])) - dx_UU1[0] = my_abs(dx_UU1[0]) - dx_UU2[0] = my_abs(dx_UU2[0]) - dx_UU3[0] = my_abs(dx_UU3[0]) - # Calculate alpha - alpha1[0] = my_max(alpha1[0], dx_UU1[0]) - alpha2[0] = my_max(alpha2[0], dx_UU2[0]) - alpha3[0] = my_max(alpha3[0], dx_UU3[0]) - - diss = hcl.scalar(0, "diss") - diss[0] = 0.5 * ( - deriv_diff1[i, j, k] * alpha1[0] + deriv_diff2[i, j, k] * alpha2[0] + deriv_diff3[i, j, k] * alpha3[0]) - - # Finally - V_new[i, j, k] = -(V_new[i, j, k] - diss[0]) - - # Calculate alphas - with hcl.if_(alpha1[0] > max_alpha1[0]): - max_alpha1[0] = alpha1[0] - with hcl.if_(alpha2[0] > max_alpha2[0]): - max_alpha2[0] = alpha2[0] - with hcl.if_(alpha3[0] > max_alpha3[0]): - max_alpha3[0] = alpha3[0] - - - - # Determine time step - delta_t = hcl.compute((1,), lambda x: step_bound(), name="delta_t") - # Integrate - result = hcl.update(V_new, lambda i, j, k: V_init[i, j, k] + V_new[i, j, k] * delta_t[0]) - - # Different computation method check - if compMethod == 'maxVWithV0' or compMethod == 'maxVWithVTarget': - result = hcl.update(V_new, lambda i, j, k: maxVWithV0(i, j, k)) - if compMethod == 'minVWithV0' or compMethod == 'minVWithVTarget': - result = hcl.update(V_new, lambda i, j, k: minVWithV0(i, j, k)) - if compMethod == 'minVWithVInit': - result = hcl.update(V_new, lambda i, j, k: minVWithVInit(i, j, k)) - if compMethod == 'maxVWithVInit': - result = hcl.update(V_new, lambda i, j, k: maxVWithVInit(i, j, k)) - - # Copy V_new to V_init - hcl.update(V_init, lambda i, j, k: V_new[i, j, k]) - return result - - def returnDerivative(V_array, Deriv_array): - with hcl.Stage("ComputeDeriv"): - with hcl.for_(0, V_array.shape[0], name="i") as i: - with hcl.for_(0, V_array.shape[1], name="j") as j: - with hcl.for_(0, V_array.shape[2], name="k") as k: - dV_dx_L = hcl.scalar(0, "dV_dx_L") - dV_dx_R = hcl.scalar(0, "dV_dx_R") - if accuracy == "low": - if deriv_dim == 1: - dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k, V_array, g) - if deriv_dim == 2: - dV_dx_L[0], dV_dx_R[0] = spa_derivY(i, j, k, V_array, g) - if deriv_dim == 3: - dV_dx_L[0], dV_dx_R[0] = spa_derivT(i, j, k, V_array, g) - if accuracy == "medium": - if deriv_dim == 1: - dV_dx_L[0], dV_dx_R[0] = secondOrderX(i, j, k, V_array, g) - if deriv_dim == 2: - dV_dx_L[0], dV_dx_R[0] = secondOrderY(i, j, k, V_array, g) - if deriv_dim == 3: - dV_dx_L[0], dV_dx_R[0] = secondOrderT(i, j, k, V_array, g) - - Deriv_array[i, j, k] = (dV_dx_L[0] + dV_dx_R[0]) / 2 - - if generate_SpatDeriv == False: - s = hcl.create_schedule([V_f, V_init, x1, x2, x3, t, l0], graph_create) - ##################### CODE OPTIMIZATION HERE ########################### - print("Optimizing\n") - - # Accessing the hamiltonian and dissipation stage - s_H = graph_create.Hamiltonian - s_D = graph_create.Dissipation - - # Thread parallelize hamiltonian and dissipation computation - s[s_H].parallel(s_H.i) - s[s_D].parallel(s_D.i) - else: - print("I'm here\n") - s = hcl.create_schedule([V_init, V_f], returnDerivative) - - # Inspect IR - # if args.llvm: - #print(hcl.lower(s)) - - # Return executable - return (hcl.build(s)) diff --git a/odp/computeGraphs/graph_4D.py b/odp/computeGraphs/graph_4D.py deleted file mode 100644 index 1b4084b0..00000000 --- a/odp/computeGraphs/graph_4D.py +++ /dev/null @@ -1,409 +0,0 @@ -import heterocl as hcl -import numpy as np -from odp.computeGraphs.CustomGraphFunctions import * -from odp.spatialDerivatives.first_orderENO4D import * -from odp.spatialDerivatives.second_orderENO4D import * - -########################## 4D Graph definition ################################# -def graph_4D(my_object, g, compMethod, accuracy, generate_SpatDeriv=False, deriv_dim=1): - V_f = hcl.placeholder(tuple(g.pts_each_dim), name="V_f", dtype=hcl.Float()) - V_init = hcl.placeholder(tuple(g.pts_each_dim), name="V_init", dtype=hcl.Float()) - l0 = hcl.placeholder(tuple(g.pts_each_dim), name="l0", dtype=hcl.Float()) - t = hcl.placeholder((2,), name="t", dtype=hcl.Float()) - probe = hcl.placeholder(tuple(g.pts_each_dim), name="probe", dtype=hcl.Float()) - - # Positions vector - x1 = hcl.placeholder((g.pts_each_dim[0],), name="x1", dtype=hcl.Float()) - x2 = hcl.placeholder((g.pts_each_dim[1],), name="x2", dtype=hcl.Float()) - x3 = hcl.placeholder((g.pts_each_dim[2],), name="x3", dtype=hcl.Float()) - x4 = hcl.placeholder((g.pts_each_dim[3],), name="x4", dtype=hcl.Float()) - - def graph_create(V_new, V_init, x1, x2, x3, x4, t, l0, probe): - # Specify intermediate tensors - deriv_diff1 = hcl.compute(V_init.shape, lambda *x:0, "deriv_diff1") - deriv_diff2 = hcl.compute(V_init.shape, lambda *x:0, "deriv_diff2") - deriv_diff3 = hcl.compute(V_init.shape, lambda *x:0, "deriv_diff3") - deriv_diff4 = hcl.compute(V_init.shape, lambda *x:0, "deriv_diff4") - - # Maximum derivative for each dim - max_deriv1 = hcl.scalar(-1e9, "max_deriv1") - max_deriv2 = hcl.scalar(-1e9, "max_deriv2") - max_deriv3 = hcl.scalar(-1e9, "max_deriv3") - max_deriv4 = hcl.scalar(-1e9, "max_deriv4") - - # Min derivative for each dim - min_deriv1 = hcl.scalar(1e9, "min_deriv1") - min_deriv2 = hcl.scalar(1e9, "min_deriv2") - min_deriv3 = hcl.scalar(1e9, "min_deriv3") - min_deriv4 = hcl.scalar(1e9, "min_deriv4") - - # These variables are used to dissipation calculation - max_alpha1 = hcl.scalar(-1e9, "max_alpha1") - max_alpha2 = hcl.scalar(-1e9, "max_alpha2") - max_alpha3 = hcl.scalar(-1e9, "max_alpha3") - max_alpha4 = hcl.scalar(-1e9, "max_alpha4") - - def step_bound(): # Function to calculate time step - stepBoundInv = hcl.scalar(0, "stepBoundInv") - stepBound = hcl.scalar(0, "stepBound") - stepBoundInv[0] = max_alpha1[0] / g.dx[0] + max_alpha2[0] / g.dx[1] + max_alpha3[0] / g.dx[2] + max_alpha4[0] / \ - g.dx[3] - - stepBound[0] = 0.8 / stepBoundInv[0] - with hcl.if_(stepBound > t[1] - t[0]): - stepBound[0] = t[1] - t[0] - - # Update the lower time ranges - t[0] = t[0] + stepBound[0] - # t[0] = min_deriv2[0] - return stepBound[0] - - # Min with V_before - def minVWithVInit(i, j, k, l): - with hcl.if_(V_new[i, j, k, l] > V_init[i, j, k, l]): - V_new[i, j, k, l] = V_init[i, j, k, l] - - def maxVWithVInit(i, j, k, l): - with hcl.if_(V_new[i, j, k, l] < V_init[i, j, k, l]): - V_new[i, j, k, l] = V_init[i, j, k, l] - - def maxVWithV0(i, j, k, l): # Take the max - with hcl.if_(V_new[i, j, k, l] < l0[i, j, k, l]): - V_new[i, j, k, l] = l0[i, j, k, l] - - def minVWithV0(i, j, k, l): - with hcl.if_(V_new[i, j, k, l] > l0[i, j, k, l]): - V_new[i, j, k, l] = l0[i, j, k, l] - - # Calculate Hamiltonian for every grid point in V_init - with hcl.Stage("Hamiltonian"): - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - # Variables to calculate dV_dx - dV_dx1_L = hcl.scalar(0, "dV_dx1_L") - dV_dx1_R = hcl.scalar(0, "dV_dx1_R") - dV_dx1 = hcl.scalar(0, "dV_dx1") - dV_dx2_L = hcl.scalar(0, "dV_dx2_L") - dV_dx2_R = hcl.scalar(0, "dV_dx2_R") - dV_dx2 = hcl.scalar(0, "dV_dx2") - dV_dx3_L = hcl.scalar(0, "dV_dx3_L") - dV_dx3_R = hcl.scalar(0, "dV_dx3_R") - dV_dx3 = hcl.scalar(0, "dV_dx3") - dV_dx4_L = hcl.scalar(0, "dV_dx4_L") - dV_dx4_R = hcl.scalar(0, "dV_dx4_R") - dV_dx4 = hcl.scalar(0, "dV_dx4") - - # No tensor slice operation - # dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - if accuracy == "low": - dV_dx1_L[0], dV_dx1_R[0] = spa_derivX1_4d(i, j, k, l, V_init, g) - dV_dx2_L[0], dV_dx2_R[0] = spa_derivX2_4d(i, j, k, l, V_init, g) - dV_dx3_L[0], dV_dx3_R[0] = spa_derivX3_4d(i, j, k, l, V_init, g) - dV_dx4_L[0], dV_dx4_R[0] = spa_derivX4_4d(i, j, k, l, V_init, g) - if accuracy == "high": - dV_dx1_L[0], dV_dx1_R[0] = secondOrderX1_4d(i, j, k, l, V_init, g) - dV_dx2_L[0], dV_dx2_R[0] = secondOrderX2_4d(i, j, k, l, V_init, g) - dV_dx3_L[0], dV_dx3_R[0] = secondOrderX3_4d(i, j, k, l, V_init, g) - dV_dx4_L[0], dV_dx4_R[0] = secondOrderX4_4d(i, j, k, l, V_init, g) - - # Saves spatial derivative diff into tables - deriv_diff1[i, j, k, l] = dV_dx1_R[0] - dV_dx1_L[0] - deriv_diff2[i, j, k, l] = dV_dx2_R[0] - dV_dx2_L[0] - deriv_diff3[i, j, k, l] = dV_dx3_R[0] - dV_dx3_L[0] - deriv_diff4[i, j, k, l] = dV_dx4_R[0] - dV_dx4_L[0] - - # Calculate average gradient - dV_dx1[0] = (dV_dx1_L + dV_dx1_R) / 2 - dV_dx2[0] = (dV_dx2_L + dV_dx2_R) / 2 - dV_dx3[0] = (dV_dx3_L + dV_dx3_R) / 2 - dV_dx4[0] = (dV_dx4_L + dV_dx4_R) / 2 - - #probe[i,j,k,l] = dV_dx2[0] - # Find optimal control - uOpt = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l]), - (dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0])) - - # Find optimal disturbance - dOpt = my_object.opt_dstb(t, (x1[i], x2[j], x3[k], x4[l]), - (dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0])) - - # Find rates of changes based on dynamics equation - dx1_dt, dx2_dt, dx3_dt, dx4_dt = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l]), uOpt, dOpt) - - # Calculate Hamiltonian terms: - V_new[i, j, k, l] = -( - dx1_dt * dV_dx1[0] + dx2_dt * dV_dx2[0] + dx3_dt * dV_dx3[0] + dx4_dt * dV_dx4[0]) - # Debugging - # V_new[i, j, k, l] = dV_dx2[0] - probe[i, j, k, l] = V_init[i, j, k, l] - - # Get derivMin - with hcl.if_(dV_dx1_L[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_R[0] - - # Get derivMax - with hcl.if_(dV_dx1_L[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_R[0] - - # Calculate dissipation amount - with hcl.Stage("Dissipation"): - # Storing alphas - dOptL1 = hcl.scalar(0, "dOptL1") - dOptL2 = hcl.scalar(0, "dOptL2") - dOptL3 = hcl.scalar(0, "dOptL3") - dOptL4 = hcl.scalar(0, "dOptL4") - # Find UPPER BOUND optimal disturbance - dOptU1 = hcl.scalar(0, "dOptL1") - dOptU2 = hcl.scalar(0, "dOptL2") - dOptU3 = hcl.scalar(0, "dOptL3") - dOptU4 = hcl.scalar(0, "dOptL4") - - alpha1 = hcl.scalar(0, "alpha1") - alpha2 = hcl.scalar(0, "alpha2") - alpha3 = hcl.scalar(0, "alpha3") - alpha4 = hcl.scalar(0, "alpha4") - - """ - NOTE: If optimal adversarial disturbance is not dependent on states - , the below approximate LOWER/UPPER BOUND optimal disturbance is accurate. - If that's not the case, move the next two statements into the nested loops and modify the states passed in - as my_object.opt_dstb(t, (x1[i], x2[j], x3[k], x4[l], ...), ...). - The reason we don't have this line in the nested loop by default is to avoid redundant computations - for certain systems where disturbance are not dependent on states. - In general, dissipation amount can just be approximates. - """ - dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0] = my_object.opt_dstb(t, (x1[0], x2[0], x3[0], x4[0]), - (min_deriv1[0], min_deriv2[0], \ - min_deriv3[0], min_deriv4[0])) - - dOptU1[0], dOptL2[0], dOptL3[0], dOptL4[0] = my_object.opt_dstb(t, (x1[0], x2[0], x3[0], x4[0]), - (max_deriv1[0], max_deriv2[0], \ - max_deriv3[0], max_deriv4[0])) - uOptL1 = hcl.scalar(0, "uOptL1") - uOptL2 = hcl.scalar(0, "uOptL2") - uOptL3 = hcl.scalar(0, "uOptL3") - uOptL4 = hcl.scalar(0, "uOptL4") - - # Find UPPER BOUND optimal disturbance - uOptU1 = hcl.scalar(0, "uOptU1") - uOptU2 = hcl.scalar(0, "uOptU2") - uOptU3 = hcl.scalar(0, "uOptU3") - uOptU4 = hcl.scalar(0, "uOptU4") - - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - dx_LL1 = hcl.scalar(0, "dx_LL1") - dx_LL2 = hcl.scalar(0, "dx_LL2") - dx_LL3 = hcl.scalar(0, "dx_LL3") - dx_LL4 = hcl.scalar(0, "dx_LL4") - - dx_UL1 = hcl.scalar(0, "dx_UL1") - dx_UL2 = hcl.scalar(0, "dx_UL2") - dx_UL3 = hcl.scalar(0, "dx_UL3") - dx_UL4 = hcl.scalar(0, "dx_UL4") - - dx_UU1 = hcl.scalar(0, "dx_UU1") - dx_UU2 = hcl.scalar(0, "dx_UU2") - dx_UU3 = hcl.scalar(0, "dx_UU3") - dx_UU4 = hcl.scalar(0, "dx_UU4") - - dx_LU1 = hcl.scalar(0, "dx_LU1") - dx_LU2 = hcl.scalar(0, "dx_LU2") - dx_LU3 = hcl.scalar(0, "dx_LU3") - dx_LU4 = hcl.scalar(0, "dx_LU4") - - # dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0] = my_object.opt_dstb(t, (x1[i], x2[j], x3[k], x4[l]), - # (min_deriv1[0], min_deriv2[0], \ - # min_deriv3[0], min_deriv4[0])) - - # dOptU1[0], dOptL2[0], dOptL3[0], dOptL4[0] = my_object.opt_dstb(t, (x1[i], x2[j], x3[k], x4[l]), - # (max_deriv1[0], max_deriv2[0], \ - # max_deriv3[0], max_deriv4[0])) - - # Find LOWER BOUND optimal control - uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0]= my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l]), - (min_deriv1[0], min_deriv2[0], min_deriv3[0], - min_deriv4[0])) - - # Find UPPER BOUND optimal control - uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0] = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l]), - (max_deriv1[0], max_deriv2[0], max_deriv3[0], - max_deriv4[0])) - - # Find magnitude of rates of changes - dx_LL1[0], dx_LL2[0], dx_LL3[0], dx_LL4[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l]), - (uOptL1[0], uOptL2[0],uOptL3[0], uOptL4[0]),\ - (dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0])) - dx_LL1[0] = my_abs(dx_LL1[0]) - dx_LL2[0] = my_abs(dx_LL2[0]) - dx_LL3[0] = my_abs(dx_LL3[0]) - dx_LL4[0] = my_abs(dx_LL4[0]) - - dx_LU1[0], dx_LU2[0], dx_LU3[0], dx_LU4[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l]), - (uOptL1[0], uOptL2[0],uOptL3[0], uOptL4[0]), \ - (dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0])) - dx_LU1[0] = my_abs(dx_LU1[0]) - dx_LU2[0] = my_abs(dx_LU2[0]) - dx_LU3[0] = my_abs(dx_LU3[0]) - dx_LU4[0] = my_abs(dx_LU4[0]) - - # Calculate alpha - alpha1[0] = my_max(dx_LL1[0], dx_LU1[0]) - alpha2[0] = my_max(dx_LL2[0], dx_LU2[0]) - alpha3[0] = my_max(dx_LL3[0], dx_LU3[0]) - alpha4[0] = my_max(dx_LL4[0], dx_LU4[0]) - - dx_UL1[0], dx_UL2[0], dx_UL3[0], dx_UL4[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l]),\ - (uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0]), \ - (dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0])) - dx_UL1[0] = my_abs(dx_UL1[0]) - dx_UL2[0] = my_abs(dx_UL2[0]) - dx_UL3[0] = my_abs(dx_UL3[0]) - dx_UL4[0] = my_abs(dx_UL4[0]) - - # Calculate alpha - alpha1[0] = my_max(alpha1[0], dx_UL1[0]) - alpha2[0] = my_max(alpha2[0], dx_UL2[0]) - alpha3[0] = my_max(alpha3[0], dx_UL3[0]) - alpha4[0] = my_max(alpha4[0], dx_UL4[0]) - - dx_UU1[0], dx_UU2[0], dx_UU3[0], dx_UU4[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l]), - (uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0]),\ - (dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0])) - dx_UU1[0] = my_abs(dx_UU1[0]) - dx_UU2[0] = my_abs(dx_UU2[0]) - dx_UU3[0] = my_abs(dx_UU3[0]) - dx_UU4[0] = my_abs(dx_UU4[0]) - - # Calculate alphas - alpha1[0] = my_max(alpha1[0], dx_UU1[0]) - alpha2[0] = my_max(alpha2[0], dx_UU2[0]) - alpha3[0] = my_max(alpha3[0], dx_UU3[0]) - alpha4[0] = my_max(alpha4[0], dx_UU4[0]) - - diss = hcl.scalar(0, "diss") - diss[0] = 0.5 * ( - deriv_diff1[i, j, k, l] * alpha1[0] + deriv_diff2[i, j, k, l] * alpha2[0] + deriv_diff3[ - i, j, k, l] * alpha3[0] + deriv_diff4[i, j, k, l] * alpha4[0]) - #probe[i, j, k, l] = alpha1[0] - - # Finally - V_new[i, j, k, l] = -(V_new[i, j, k, l] - diss[0]) - - # Get maximum alphas in each dimension - with hcl.if_(alpha1[0] > max_alpha1[0]): - max_alpha1[0] = alpha1[0] - with hcl.if_(alpha2[0] > max_alpha2[0]): - max_alpha2[0] = alpha2[0] - with hcl.if_(alpha3[0] > max_alpha3[0]): - max_alpha3[0] = alpha3[0] - with hcl.if_(alpha4[0] > max_alpha4[0]): - max_alpha4[0] = alpha4[0] - - # Determine time step - delta_t = hcl.compute((1,), lambda x: step_bound(), name="delta_t") - # Integrate - result = hcl.update(V_new, lambda i, j, k, l: V_init[i, j, k, l] + V_new[i, j, k, l] * delta_t[0]) - # Different computation method check - if compMethod == 'maxVWithV0' or compMethod == 'maxVWithVTarget': - result = hcl.update(V_new, lambda i, j, k, l: maxVWithV0(i, j, k, l)) - if compMethod == 'minVWithV0' or compMethod == 'minVWithVTarget': - result = hcl.update(V_new, lambda i, j, k, l: minVWithV0(i, j, k, l)) - if compMethod == 'minVWithVInit': - result = hcl.update(V_new, lambda i, j, k, l: minVWithVInit(i, j, k, l)) - if compMethod == 'maxVWithVInit': - result = hcl.update(V_new, lambda i, j, k, l: maxVWithVInit(i, j, k, l)) - - # Copy V_new to V_init - hcl.update(V_init, lambda i, j, k, l: V_new[i, j, k, l]) - return result - - def returnDerivative(V_array, Deriv_array): - with hcl.Stage("ComputeDeriv"): - with hcl.for_(0, V_array.shape[0], name="i") as i: - with hcl.for_(0, V_array.shape[1], name="j") as j: - with hcl.for_(0, V_array.shape[2], name="k") as k: - with hcl.for_(0, V_array.shape[3], name="l") as l: - dV_dx_L = hcl.scalar(0, "dV_dx_L") - dV_dx_R = hcl.scalar(0, "dV_dx_R") - if accuracy == "low": - if deriv_dim == 1: - dV_dx_L[0], dV_dx_R[0] = spa_derivX1_4d(i, j, k, l, V_array, g) - if deriv_dim == 2: - dV_dx_L[0], dV_dx_R[0] = spa_derivX2_4d(i, j, k, l, V_array, g) - if deriv_dim == 3: - dV_dx_L[0], dV_dx_R[0] = spa_derivX3_4d(i, j, k, l, V_array, g) - if deriv_dim == 4: - dV_dx_L[0], dV_dx_R[0] = spa_derivX4_4d(i, j, k, l, V_array, g) - if accuracy == "medium": - if deriv_dim == 1: - dV_dx_L[0], dV_dx_R[0] = secondOrderX1_4d(i, j, k, l, V_array, g) - if deriv_dim == 2: - dV_dx_L[0], dV_dx_R[0] = secondOrderX2_4d(i, j, k, l, V_array, g) - if deriv_dim == 3: - dV_dx_L[0], dV_dx_R[0] = secondOrderX3_4d(i, j, k, l, V_array, g) - if deriv_dim == 4: - dV_dx_L[0], dV_dx_R[0] = secondOrderX4_4d(i, j, k, l, V_array, g) - - Deriv_array[i, j, k, l] = (dV_dx_L[0] + dV_dx_R[0]) / 2 - - if generate_SpatDeriv == False: - s = hcl.create_schedule([V_f, V_init, x1, x2, x3, x4, t, l0, probe], graph_create) - - ##################### CODE OPTIMIZATION HERE ########################### - print("Optimizing\n") - - # Accessing the hamiltonian and dissipation stage - s_H = graph_create.Hamiltonian - s_D = graph_create.Dissipation - - # Thread parallelize hamiltonian and dissipation - s[s_H].parallel(s_H.i) - s[s_D].parallel(s_D.i) - - # Inspect IR - # if args.llvm: - # print(hcl.lower(s)) - else: - s = hcl.create_schedule([V_init, V_f], returnDerivative) - - # Return executable - return(hcl.build(s)) \ No newline at end of file diff --git a/odp/computeGraphs/graph_5D.py b/odp/computeGraphs/graph_5D.py deleted file mode 100644 index 547541f3..00000000 --- a/odp/computeGraphs/graph_5D.py +++ /dev/null @@ -1,445 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * -from odp.spatialDerivatives.second_orderENO5D import * -from odp.spatialDerivatives.first_orderENO5D import * -########################## 5D graph definition ######################## - -# Note that t has 2 elements t1, t2 -def graph_5D(my_object, g, compMethod, accuracy, generate_SpatDeriv=False, deriv_dim=1): - V_f = hcl.placeholder(tuple(g.pts_each_dim), name="V_f", dtype=hcl.Float()) - V_init = hcl.placeholder(tuple(g.pts_each_dim), name="V_init", dtype=hcl.Float()) - l0 = hcl.placeholder(tuple(g.pts_each_dim), name="l0", dtype=hcl.Float()) - t = hcl.placeholder((2,), name="t", dtype=hcl.Float()) - - # Positions vector - x1 = hcl.placeholder((g.pts_each_dim[0],), name="x1", dtype=hcl.Float()) - x2 = hcl.placeholder((g.pts_each_dim[1],), name="x2", dtype=hcl.Float()) - x3 = hcl.placeholder((g.pts_each_dim[2],), name="x3", dtype=hcl.Float()) - x4 = hcl.placeholder((g.pts_each_dim[3],), name="x4", dtype=hcl.Float()) - x5 = hcl.placeholder((g.pts_each_dim[4],), name="x5", dtype=hcl.Float()) - - def graph_create(V_new, V_init, x1, x2, x3, x4, x5, t, l0): - # Specify intermediate tensors - deriv_diff1 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff1") - deriv_diff2 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff2") - deriv_diff3 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff3") - deriv_diff4 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff4") - deriv_diff5 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff5") - - # Maximum derivative for each dim - max_deriv1 = hcl.scalar(-1e9, "max_deriv1") - max_deriv2 = hcl.scalar(-1e9, "max_deriv2") - max_deriv3 = hcl.scalar(-1e9, "max_deriv3") - max_deriv4 = hcl.scalar(-1e9, "max_deriv4") - max_deriv5 = hcl.scalar(-1e9, "max_deriv5") - - # Min derivative for each dim - min_deriv1 = hcl.scalar(1e9, "min_deriv1") - min_deriv2 = hcl.scalar(1e9, "min_deriv2") - min_deriv3 = hcl.scalar(1e9, "min_deriv3") - min_deriv4 = hcl.scalar(1e9, "min_deriv4") - min_deriv5 = hcl.scalar(1e9, "min_deriv5") - - # These variables are used to dissipation calculation - max_alpha1 = hcl.scalar(-1e9, "max_alpha1") - max_alpha2 = hcl.scalar(-1e9, "max_alpha2") - max_alpha3 = hcl.scalar(-1e9, "max_alpha3") - max_alpha4 = hcl.scalar(-1e9, "max_alpha4") - max_alpha5 = hcl.scalar(-1e9, "max_alpha5") - - def step_bound(): # Function to calculate time step - stepBoundInv = hcl.scalar(0, "stepBoundInv") - stepBound = hcl.scalar(0, "stepBound") - stepBoundInv[0] = max_alpha1[0] / g.dx[0] + max_alpha2[0] / g.dx[1] + max_alpha3[0] / g.dx[2] + max_alpha4[ - 0] / g.dx[3] \ - + max_alpha5[0] / g.dx[4] - - stepBound[0] = 0.8 / stepBoundInv[0] - with hcl.if_(stepBound > t[1] - t[0]): - stepBound[0] = t[1] - t[0] - - # Update the lower time ranges - t[0] = t[0] + stepBound[0] - # t[0] = min_deriv2[0] - return stepBound[0] - - def maxVWithV0(i, j, k, l, m): # Take the max - with hcl.if_(V_new[i, j, k, l, m] < l0[i, j, k, l, m]): - V_new[i, j, k, l, m] = l0[i, j, k, l, m] - - def minVWithV0(i, j, k, l, m): # Take the max - with hcl.if_(V_new[i, j, k, l, m] > l0[i, j, k, l, m]): - V_new[i, j, k, l, m] = l0[i, j, k, l, m] - - # Min with V_before - def minVWithVInit(i, j, k, l, m): - with hcl.if_(V_new[i, j, k, l, m] > V_init[i, j, k, l, m]): - V_new[i, j, k, l, m] = V_init[i, j, k, l, m] - - def maxVWithVInit(i, j, k, l, m): - with hcl.if_(V_new[i, j, k, l, m] < V_init[i, j, k, l, m]): - V_new[i, j, k, l, m] = V_init[i, j, k, l, m] - - # Calculate Hamiltonian for every grid point in V_init - with hcl.Stage("Hamiltonian"): - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - with hcl.for_(0, V_init.shape[4], name="m") as m: - # Variables to calculate dV_dx - dV_dx1_L = hcl.scalar(0, "dV_dx1_L") - dV_dx1_R = hcl.scalar(0, "dV_dx1_R") - dV_dx1 = hcl.scalar(0, "dV_dx1") - dV_dx2_L = hcl.scalar(0, "dV_dx2_L") - dV_dx2_R = hcl.scalar(0, "dV_dx2_R") - dV_dx2 = hcl.scalar(0, "dV_dx2") - dV_dx3_L = hcl.scalar(0, "dV_dx3_L") - dV_dx3_R = hcl.scalar(0, "dV_dx3_R") - dV_dx3 = hcl.scalar(0, "dV_dx3") - dV_dx4_L = hcl.scalar(0, "dV_dx4_L") - dV_dx4_R = hcl.scalar(0, "dV_dx4_R") - dV_dx4 = hcl.scalar(0, "dV_dx4") - dV_dx5_L = hcl.scalar(0, "dV_dx5_L") - dV_dx5_R = hcl.scalar(0, "dV_dx5_R") - dV_dx5 = hcl.scalar(0, "dV_dx5") - - # No tensor slice operation - # dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - if accuracy == "low": - dV_dx1_L[0], dV_dx1_R[0] = spa_derivX1_5d(i, j, k, l, m, V_init, g) - dV_dx2_L[0], dV_dx2_R[0] = spa_derivX2_5d(i, j, k, l, m, V_init, g) - dV_dx3_L[0], dV_dx3_R[0] = spa_derivX3_5d(i, j, k, l, m, V_init, g) - dV_dx4_L[0], dV_dx4_R[0] = spa_derivX4_5d(i, j, k, l, m, V_init, g) - dV_dx5_L[0], dV_dx5_R[0] = spa_derivX5_5d(i, j, k, l, m, V_init, g) - if accuracy == "high": - dV_dx1_L[0], dV_dx1_R[0] = secondOrderX1_5d(i, j, k, l, m, V_init, g) - dV_dx2_L[0], dV_dx2_R[0] = secondOrderX2_5d(i, j, k, l, m, V_init, g) - dV_dx3_L[0], dV_dx3_R[0] = secondOrderX3_5d(i, j, k, l, m, V_init, g) - dV_dx4_L[0], dV_dx4_R[0] = secondOrderX4_5d(i, j, k, l, m, V_init, g) - dV_dx5_L[0], dV_dx5_R[0] = secondOrderX5_5d(i, j, k, l, m, V_init, g) - - # Saves spatial derivative diff into tables - deriv_diff1[i, j, k, l, m] = dV_dx1_R[0] - dV_dx1_L[0] - deriv_diff2[i, j, k, l, m] = dV_dx2_R[0] - dV_dx2_L[0] - deriv_diff3[i, j, k, l, m] = dV_dx3_R[0] - dV_dx3_L[0] - deriv_diff4[i, j, k, l, m] = dV_dx4_R[0] - dV_dx4_L[0] - deriv_diff5[i, j, k, l, m] = dV_dx5_R[0] - dV_dx5_L[0] - - # Calculate average gradient - dV_dx1[0] = (dV_dx1_L + dV_dx1_R) / 2 - dV_dx2[0] = (dV_dx2_L + dV_dx2_R) / 2 - dV_dx3[0] = (dV_dx3_L + dV_dx3_R) / 2 - dV_dx4[0] = (dV_dx4_L + dV_dx4_R) / 2 - dV_dx5[0] = (dV_dx5_L + dV_dx5_R) / 2 - - # Find optimal control - uOpt = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l], x5[m]), \ - (dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0])) - # Find optimal disturbance - dOpt = my_object.opt_dstb(t, (x1[i], x2[j], x3[k], x4[l], x5[m]), \ - (dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0])) - - # Find rates of changes based on dynamics equation - dx1_dt, dx2_dt, dx3_dt, dx4_dt, dx5_dt = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m]), uOpt, dOpt) - - # Calculate Hamiltonian terms: - V_new[i, j, k, l, m] = -( - dx1_dt * dV_dx1[0] + dx2_dt * dV_dx2[0] + dx3_dt * dV_dx3[0] + dx4_dt * - dV_dx4[0] + dx5_dt * dV_dx5[0]) - - # Get derivMin - with hcl.if_(dV_dx1_L[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_R[0] - - with hcl.if_(dV_dx5_L[0] < min_deriv5[0]): - min_deriv5[0] = dV_dx5_L[0] - with hcl.if_(dV_dx5_R[0] < min_deriv5[0]): - min_deriv5[0] = dV_dx5_R[0] - - # Get derivMax - with hcl.if_(dV_dx1_L[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_R[0] - - with hcl.if_(dV_dx5_L[0] > max_deriv5[0]): - max_deriv5[0] = dV_dx5_L[0] - with hcl.if_(dV_dx5_R[0] > max_deriv5[0]): - max_deriv5[0] = dV_dx5_R[0] - - # Calculate dissipation amount - with hcl.Stage("Dissipation"): - uOptL1 = hcl.scalar(0, "uOptL1") - uOptL2 = hcl.scalar(0, "uOptL2") - uOptL3 = hcl.scalar(0, "uOptL3") - uOptL4 = hcl.scalar(0, "uOptL4") - uOptL5 = hcl.scalar(0, "uOptL5") - - uOptU1 = hcl.scalar(0, "uOptU1") - uOptU2 = hcl.scalar(0, "uOptU2") - uOptU3 = hcl.scalar(0, "uOptU3") - uOptU4 = hcl.scalar(0, "uOptU4") - uOptU5 = hcl.scalar(0, "uOptU5") - - dOptL1 = hcl.scalar(0, "dOptL1") - dOptL2 = hcl.scalar(0, "dOptL2") - dOptL3 = hcl.scalar(0, "dOptL3") - dOptL4 = hcl.scalar(0, "dOptL4") - dOptL5 = hcl.scalar(0, "dOptL5") - - dOptU1 = hcl.scalar(0, "dOptU1") - dOptU2 = hcl.scalar(0, "dOptU2") - dOptU3 = hcl.scalar(0, "dOptU3") - dOptU4 = hcl.scalar(0, "dOptU4") - dOptU5 = hcl.scalar(0, "dOptU5") - - # Storing alphas - alpha1 = hcl.scalar(0, "alpha1") - alpha2 = hcl.scalar(0, "alpha2") - alpha3 = hcl.scalar(0, "alpha3") - alpha4 = hcl.scalar(0, "alpha4") - alpha5 = hcl.scalar(0, "alpha5") - - """ - NOTE: If optimal adversarial disturbance is not dependent on states - , the below approximate LOWER/UPPER BOUND optimal disturbance is accurate. - If that's not the case, move the next two statements into the nested loops and modify the states passed in - as my_object.opt_dstb(t, (x1[i], x2[j], x3[k], x4[l], ...), ...). - The reason we don't have this line in the nested loop by default is to avoid redundant computations - for certain systems where disturbance are not dependent on states. - In general, dissipation amount can just be approximates. - """ - - # Find LOWER BOUND optimal disturbance - dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0], dOptL5[0] = my_object.opt_dstb(t, (x1[0], x2[0], x3[0], x4[0], x5[0]), \ - (min_deriv1[0], min_deriv2[0], min_deriv3[0], min_deriv4[0], min_deriv5[0])) - # Find UPPER BOUND optimal disturbance - dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0], dOptU5[0] = my_object.opt_dstb(t, (x1[0], x2[0], x3[0], x4[0], x5[0]), \ - (max_deriv1[0], max_deriv2[0], max_deriv3[0], max_deriv4[0], max_deriv5[0])) - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - with hcl.for_(0, V_init.shape[4], name="m") as m: - dx_LL1 = hcl.scalar(0, "dx_LL1") - dx_LL2 = hcl.scalar(0, "dx_LL2") - dx_LL3 = hcl.scalar(0, "dx_LL3") - dx_LL4 = hcl.scalar(0, "dx_LL4") - dx_LL5 = hcl.scalar(0, "dx_LL5") - - dx_UL1 = hcl.scalar(0, "dx_UL1") - dx_UL2 = hcl.scalar(0, "dx_UL2") - dx_UL3 = hcl.scalar(0, "dx_UL3") - dx_UL4 = hcl.scalar(0, "dx_UL4") - dx_UL5 = hcl.scalar(0, "dx_UL5") - # - dx_LU1 = hcl.scalar(0, "dx_LU1") - dx_LU2 = hcl.scalar(0, "dx_LU2") - dx_LU3 = hcl.scalar(0, "dx_LU3") - dx_LU4 = hcl.scalar(0, "dx_LU4") - dx_LU5 = hcl.scalar(0, "dx_LU5") - - dx_UU1 = hcl.scalar(0, "dx_UU1") - dx_UU2 = hcl.scalar(0, "dx_UU2") - dx_UU3 = hcl.scalar(0, "dx_UU3") - dx_UU4 = hcl.scalar(0, "dx_UU4") - dx_UU5 = hcl.scalar(0, "dx_UU5") - - # Find LOWER BOUND optimal control - uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0], uOptL5[0] = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l], x5[m]), \ - (min_deriv1[0], min_deriv2[0], min_deriv3[0], min_deriv4[0], min_deriv5[0])) - # Find UPPER BOUND optimal control - uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0], uOptU5[0] = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l], x5[m]), \ - (max_deriv1[0], max_deriv2[0], max_deriv3[0], max_deriv4[0], max_deriv5[0])) - - # Get upper bound and lower bound rates of changes - dx_LL1[0], dx_LL2[0], dx_LL3[0], dx_LL4[0], dx_LL5[0] = my_object.dynamics(t, \ - (x1[i], x2[j], x3[k], x4[l], x5[m]), (uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0], uOptL5[0]), - (dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0], dOptL5[0])) - # Get absolute value of each - dx_LL1[0] = my_abs(dx_LL1[0]) - dx_LL2[0] = my_abs(dx_LL2[0]) - dx_LL3[0] = my_abs(dx_LL3[0]) - dx_LL4[0] = my_abs(dx_LL4[0]) - dx_LL5[0] = my_abs(dx_LL5[0]) - - dx_UL1[0], dx_UL2[0], dx_UL3[0], dx_UL4[0], dx_UL5[0] = my_object.dynamics(t, \ - (x1[i], x2[j], x3[k], x4[l], x5[m]), (uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0], uOptU5[0]), - (dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0], dOptL5[0])) - # Get absolute value of each - dx_UL1[0] = my_abs(dx_UL1[0]) - dx_UL2[0] = my_abs(dx_UL2[0]) - dx_UL3[0] = my_abs(dx_UL3[0]) - dx_UL4[0] = my_abs(dx_UL4[0]) - dx_UL5[0] = my_abs(dx_UL5[0]) - - # Set maximum alphas - alpha1[0] = my_max(dx_UL1[0], dx_LL1[0]) - alpha2[0] = my_max(dx_UL2[0], dx_LL2[0]) - alpha3[0] = my_max(dx_UL3[0], dx_LL3[0]) - alpha4[0] = my_max(dx_UL4[0], dx_LL4[0]) - alpha5[0] = my_max(dx_UL5[0], dx_LL5[0]) - - dx_LU1[0], dx_LU2[0], dx_LU3[0], dx_LU4[0], dx_LU5[0] = my_object.dynamics(t, \ - (x1[i], x2[j], x3[k], x4[l], x5[m]), (uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0], uOptL5[0]), - (dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0], dOptU5[0])) - # Get absolute value of each - dx_LU1[0] = my_abs(dx_LU1[0]) - dx_LU2[0] = my_abs(dx_LU2[0]) - dx_LU3[0] = my_abs(dx_LU3[0]) - dx_LU4[0] = my_abs(dx_LU4[0]) - dx_LU5[0] = my_abs(dx_LU5[0]) - - alpha1[0] = my_max(alpha1[0], dx_LU1[0]) - alpha2[0] = my_max(alpha2[0], dx_LU2[0]) - alpha3[0] = my_max(alpha3[0], dx_LU3[0]) - alpha4[0] = my_max(alpha4[0], dx_LU4[0]) - alpha5[0] = my_max(alpha5[0], dx_LU5[0]) - - dx_UU1[0], dx_UU2[0], dx_UU3[0], dx_UU4[0], dx_UU5[0] = my_object.dynamics(t, \ - (x1[i], x2[j], x3[k], x4[l], x5[m]), (uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0], uOptU5[0]), - (dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0], dOptU5[0])) - dx_UU1[0] = my_abs(dx_UU1[0]) - dx_UU2[0] = my_abs(dx_UU2[0]) - dx_UU3[0] = my_abs(dx_UU3[0]) - dx_UU4[0] = my_abs(dx_UU4[0]) - dx_UU5[0] = my_abs(dx_UU5[0]) - - alpha1[0] = my_max(alpha1[0], dx_UU1[0]) - alpha2[0] = my_max(alpha2[0], dx_UU2[0]) - alpha3[0] = my_max(alpha3[0], dx_UU3[0]) - alpha4[0] = my_max(alpha4[0], dx_UU4[0]) - alpha5[0] = my_max(alpha5[0], dx_UU5[0]) - - diss = hcl.scalar(0, "diss") - diss[0] = 0.5 * (deriv_diff1[i, j, k, l, m] * alpha1[0] + deriv_diff2[ - i, j, k, l, m] * alpha2[0] \ - + deriv_diff3[i, j, k, l, m] * alpha3[0] + deriv_diff4[ - i, j, k, l, m] * alpha4[0] \ - + deriv_diff5[i, j, k, l, m] * alpha5[0] ) - - # Finally - V_new[i, j, k, l, m] = -(V_new[i, j, k, l, m] - diss[0]) - # Get maximum alphas in each dimension - - # Calculate alphas - with hcl.if_(alpha1 > max_alpha1): - max_alpha1[0] = alpha1[0] - with hcl.if_(alpha2 > max_alpha2): - max_alpha2[0] = alpha2[0] - with hcl.if_(alpha3 > max_alpha3): - max_alpha3[0] = alpha3[0] - with hcl.if_(alpha4 > max_alpha4): - max_alpha4[0] = alpha4[0] - with hcl.if_(alpha5 > max_alpha5): - max_alpha5[0] = alpha5[0] - - # Determine time step - delta_t = hcl.compute((1,), lambda x: step_bound(), name="delta_t") - # hcl.update(t, lambda x: t[x] + delta_t[x]) - - # Integrate - # if compMethod == 'HJ_PDE': - result = hcl.update(V_new, - lambda i, j, k, l, m: V_init[i, j, k, l, m] + V_new[i, j, k, l, m] * delta_t[0]) - if compMethod == 'maxVWithV0' or compMethod == 'maxVWithVTarget': - result = hcl.update(V_new, lambda i, j, k, l, m: maxVWithV0(i, j, k, l, m)) - if compMethod == 'minVWithV0' or compMethod == 'minVWithVTarget': - result = hcl.update(V_new, lambda i, j, k, l, m: minVWithV0(i, j, k, l, m)) - if compMethod == 'maxVWithVInit': - result = hcl.update(V_new, lambda i, j, k, l, m: maxVWithVInit(i, j, k, l, m)) - if compMethod == 'minVWithVInit': - result = hcl.update(V_new, lambda i, j, k, l, m: minVWithVInit(i, j, k, l, m)) - # Copy V_new to V_init - hcl.update(V_init, lambda i, j, k, l, m: V_new[i, j, k, l, m]) - return result - - def returnDerivative(V_array, Deriv_array): - with hcl.Stage("ComputeDeriv"): - with hcl.for_(0, V_array.shape[0], name="i") as i: - with hcl.for_(0, V_array.shape[1], name="j") as j: - with hcl.for_(0, V_array.shape[2], name="k") as k: - with hcl.for_(0, V_array.shape[3], name="l") as l: - with hcl.for_(0, V_array.shape[4], name="m") as m: - dV_dx_L = hcl.scalar(0, "dV_dx_L") - dV_dx_R = hcl.scalar(0, "dV_dx_R") - if accuracy == "low": - if deriv_dim == 1: - dV_dx_L[0], dV_dx_R[0] = spa_derivX1_5d(i, j, k, l, m, V_array, g) - if deriv_dim == 2: - dV_dx_L[0], dV_dx_R[0] = spa_derivX2_5d(i, j, k, l, m, V_array, g) - if deriv_dim == 3: - dV_dx_L[0], dV_dx_R[0] = spa_derivX3_5d(i, j, k, l, m, V_array, g) - if deriv_dim == 4: - dV_dx_L[0], dV_dx_R[0] = spa_derivX4_5d(i, j, k, l, m, V_array, g) - if deriv_dim == 5: - dV_dx_L[0], dV_dx_R[0] = spa_derivX5_5d(i, j, k, l, m, V_array, g) - - if accuracy == "medium": - if deriv_dim == 1: - dV_dx_L[0], dV_dx_R[0] = secondOrderX1_5d(i, j, k, l, m, V_array, g) - if deriv_dim == 2: - dV_dx_L[0], dV_dx_R[0] = secondOrderX2_5d(i, j, k, l, m, V_array, g) - if deriv_dim == 3: - dV_dx_L[0], dV_dx_R[0] = secondOrderX3_5d(i, j, k, l, m, V_array, g) - if deriv_dim == 4: - dV_dx_L[0], dV_dx_R[0] = secondOrderX4_5d(i, j, k, l, m, V_array, g) - if deriv_dim == 5: - dV_dx_L[0], dV_dx_R[0] = secondOrderX5_5d(i, j, k, l, m, V_array, g) - - Deriv_array[i, j, k, l, m] = (dV_dx_L[0] + dV_dx_R[0]) / 2 - - if generate_SpatDeriv == False: - s = hcl.create_schedule([V_f, V_init, x1, x2, x3, x4, x5, t, l0], graph_create) - ##################### CODE OPTIMIZATION HERE ########################### - print("Optimizing\n") - - # Accessing the hamiltonian and dissipation stage - s_H = graph_create.Hamiltonian - s_D = graph_create.Dissipation - - # Thread parallelize hamiltonian and dissipation - s[s_H].parallel(s_H.i) - s[s_D].parallel(s_D.i) - - # Inspect IR - # if args.llvm: - # print(hcl.lower(s)) - else: - s = hcl.create_schedule([V_init, V_f], returnDerivative) - - # Return executable - return (hcl.build(s)) diff --git a/odp/computeGraphs/graph_6D.py b/odp/computeGraphs/graph_6D.py deleted file mode 100644 index 5ef91782..00000000 --- a/odp/computeGraphs/graph_6D.py +++ /dev/null @@ -1,448 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * -from odp.spatialDerivatives.first_orderENO6D import * -from odp.spatialDerivatives.second_orderENO6D import * - -########################## 6D graph definition ######################## - -# Note that t has 2 elements t1, t2 -def graph_6D(my_object, g, compMethod, accuracy): - V_f = hcl.placeholder(tuple(g.pts_each_dim), name="V_f", dtype=hcl.Float()) - V_init = hcl.placeholder(tuple(g.pts_each_dim), name="V_init", dtype=hcl.Float()) - l0 = hcl.placeholder(tuple(g.pts_each_dim), name="l0", dtype=hcl.Float()) - t = hcl.placeholder((2,), name="t", dtype=hcl.Float()) - - # Positions vector - x1 = hcl.placeholder((g.pts_each_dim[0],), name="x1", dtype=hcl.Float()) - x2 = hcl.placeholder((g.pts_each_dim[1],), name="x2", dtype=hcl.Float()) - x3 = hcl.placeholder((g.pts_each_dim[2],), name="x3", dtype=hcl.Float()) - x4 = hcl.placeholder((g.pts_each_dim[3],), name="x4", dtype=hcl.Float()) - x5 = hcl.placeholder((g.pts_each_dim[4],), name="x5", dtype=hcl.Float()) - x6 = hcl.placeholder((g.pts_each_dim[5],), name="x6", dtype=hcl.Float()) - - def graph_create(V_new, V_init, x1, x2, x3, x4, x5, x6, t, l0): - # Specify intermediate tensors - deriv_diff1 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff1") - deriv_diff2 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff2") - deriv_diff3 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff3") - deriv_diff4 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff4") - deriv_diff5 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff5") - deriv_diff6 = hcl.compute(V_init.shape, lambda *x: 0, "deriv_diff6") - - # Maximum derivative for each dim - max_deriv1 = hcl.scalar(-1e9, "max_deriv1") - max_deriv2 = hcl.scalar(-1e9, "max_deriv2") - max_deriv3 = hcl.scalar(-1e9, "max_deriv3") - max_deriv4 = hcl.scalar(-1e9, "max_deriv4") - max_deriv5 = hcl.scalar(-1e9, "max_deriv5") - max_deriv6 = hcl.scalar(-1e9, "max_deriv6") - - # Min derivative for each dim - min_deriv1 = hcl.scalar(1e9, "min_deriv1") - min_deriv2 = hcl.scalar(1e9, "min_deriv2") - min_deriv3 = hcl.scalar(1e9, "min_deriv3") - min_deriv4 = hcl.scalar(1e9, "min_deriv4") - min_deriv5 = hcl.scalar(1e9, "min_deriv5") - min_deriv6 = hcl.scalar(1e9, "min_deriv6") - - # These variables are used to dissipation calculation - max_alpha1 = hcl.scalar(-1e9, "max_alpha1") - max_alpha2 = hcl.scalar(-1e9, "max_alpha2") - max_alpha3 = hcl.scalar(-1e9, "max_alpha3") - max_alpha4 = hcl.scalar(-1e9, "max_alpha4") - max_alpha5 = hcl.scalar(-1e9, "max_alpha5") - max_alpha6 = hcl.scalar(-1e9, "max_alpha6") - - def step_bound(): # Function to calculate time step - stepBoundInv = hcl.scalar(0, "stepBoundInv") - stepBound = hcl.scalar(0, "stepBound") - stepBoundInv[0] = max_alpha1[0] / g.dx[0] + max_alpha2[0] / g.dx[1] + max_alpha3[0] / g.dx[2] + max_alpha4[ - 0] / g.dx[3] \ - + max_alpha5[0] / g.dx[4] + max_alpha6[0] / g.dx[5] - - stepBound[0] = 0.8 / stepBoundInv[0] - with hcl.if_(stepBound > t[1] - t[0]): - stepBound[0] = t[1] - t[0] - - # Update the lower time ranges - t[0] = t[0] + stepBound[0] - # t[0] = min_deriv2[0] - return stepBound[0] - - # Operation with target value array - def maxVWithV0(i, j, k, l, m, n): # Take max - with hcl.if_(V_new[i, j, k, l, m, n] < l0[i, j, k, l, m, n]): - V_new[i, j, k, l, m, n] = l0[i, j, k, l, m, n] - - def minVWithV0(i, j, k, l, m, n): # Take min - with hcl.if_(V_new[i, j, k, l, m, n] > l0[i, j, k, l, m, n]): - V_new[i, j, k, l, m, n] = l0[i, j, k, l, m, n] - - # Operations over time - def minVWithVInit(i, j, k, l, m, n): - with hcl.if_(V_new[i, j, k, l, m, n] > V_init[i, j, k, l, m, n]): - V_new[i, j, k, l, m, n] = V_init[i, j, k, l, m, n] - - def maxVWithVInit(i, j, k, l, m, n): - with hcl.if_(V_new[i, j, k, l, m, n] > V_init[i, j, k, l, m, n]): - V_new[i, j, k, l, m, n] = V_init[i, j, k, l, m, n] - - # Calculate Hamiltonian for every grid point in V_init - with hcl.Stage("Hamiltonian"): - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - with hcl.for_(0, V_init.shape[4], name="m") as m: - with hcl.for_(0, V_init.shape[5], name="n") as n: - # Variables to calculate dV_dx - dV_dx1_L = hcl.scalar(0, "dV_dx1_L") - dV_dx1_R = hcl.scalar(0, "dV_dx1_R") - dV_dx1 = hcl.scalar(0, "dV_dx1") - dV_dx2_L = hcl.scalar(0, "dV_dx2_L") - dV_dx2_R = hcl.scalar(0, "dV_dx2_R") - dV_dx2 = hcl.scalar(0, "dV_dx2") - dV_dx3_L = hcl.scalar(0, "dV_dx3_L") - dV_dx3_R = hcl.scalar(0, "dV_dx3_R") - dV_dx3 = hcl.scalar(0, "dV_dx3") - dV_dx4_L = hcl.scalar(0, "dV_dx4_L") - dV_dx4_R = hcl.scalar(0, "dV_dx4_R") - dV_dx4 = hcl.scalar(0, "dV_dx4") - dV_dx5_L = hcl.scalar(0, "dV_dx5_L") - dV_dx5_R = hcl.scalar(0, "dV_dx5_R") - dV_dx5 = hcl.scalar(0, "dV_dx5") - dV_dx6_L = hcl.scalar(0, "dV_dx6_L") - dV_dx6_R = hcl.scalar(0, "dV_dx6_R") - dV_dx6 = hcl.scalar(0, "dV_dx6") - - # No tensor slice operation - # dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - if accuracy == "low": - dV_dx1_L[0], dV_dx1_R[0] = spa_derivX1_6d(i, j, k, l, m, n, V_init, g) - dV_dx2_L[0], dV_dx2_R[0] = spa_derivX2_6d(i, j, k, l, m, n, V_init, g) - dV_dx3_L[0], dV_dx3_R[0] = spa_derivX3_6d(i, j, k, l, m, n, V_init, g) - dV_dx4_L[0], dV_dx4_R[0] = spa_derivX4_6d(i, j, k, l, m, n, V_init, g) - dV_dx5_L[0], dV_dx5_R[0] = spa_derivX5_6d(i, j, k, l, m, n, V_init, g) - dV_dx6_L[0], dV_dx6_R[0] = spa_derivX6_6d(i, j, k, l, m, n, V_init, g) - if accuracy == "high": - dV_dx1_L[0], dV_dx1_R[0] = secondOrderX1_6d(i, j, k, l, m, n, V_init, g) - dV_dx2_L[0], dV_dx2_R[0] = secondOrderX2_6d(i, j, k, l, m, n, V_init, g) - dV_dx3_L[0], dV_dx3_R[0] = secondOrderX3_6d(i, j, k, l, m, n, V_init, g) - dV_dx4_L[0], dV_dx4_R[0] = secondOrderX4_6d(i, j, k, l, m, n, V_init, g) - dV_dx5_L[0], dV_dx5_R[0] = secondOrderX5_6d(i, j, k, l, m, n, V_init, g) - dV_dx6_L[0], dV_dx6_R[0] = secondOrderX6_6d(i, j, k, l, m, n, V_init, g) - - # Saves spatial derivative diff into tables - deriv_diff1[i, j, k, l, m, n] = dV_dx1_R[0] - dV_dx1_L[0] - deriv_diff2[i, j, k, l, m, n] = dV_dx2_R[0] - dV_dx2_L[0] - deriv_diff3[i, j, k, l, m, n] = dV_dx3_R[0] - dV_dx3_L[0] - deriv_diff4[i, j, k, l, m, n] = dV_dx4_R[0] - dV_dx4_L[0] - deriv_diff5[i, j, k, l, m, n] = dV_dx5_R[0] - dV_dx5_L[0] - deriv_diff6[i, j, k, l, m, n] = dV_dx6_R[0] - dV_dx6_L[0] - - # Calculate average gradient - dV_dx1[0] = (dV_dx1_L + dV_dx1_R) / 2 - dV_dx2[0] = (dV_dx2_L + dV_dx2_R) / 2 - dV_dx3[0] = (dV_dx3_L + dV_dx3_R) / 2 - dV_dx4[0] = (dV_dx4_L + dV_dx4_R) / 2 - dV_dx5[0] = (dV_dx5_L + dV_dx5_R) / 2 - dV_dx6[0] = (dV_dx6_L + dV_dx6_R) / 2 - - # Find optimal control - uOpt = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), ( - dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0], dV_dx6[0])) - # Find optimal disturbance - dOpt = my_object.opt_dstb(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), ( - dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0], dV_dx6[0])) - - # Find rates of changes based on dynamics equation - dx1_dt, dx2_dt, dx3_dt, dx4_dt, dx5_dt, dx6_dt = my_object.dynamics(t, ( - x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), uOpt, dOpt) - - # Calculate Hamiltonian terms: - V_new[i, j, k, l, m, n] = -( - dx1_dt * dV_dx1[0] + dx2_dt * dV_dx2[0] + dx3_dt * dV_dx3[0] + dx4_dt * - dV_dx4[0] + dx5_dt * dV_dx5[0] + dx6_dt * dV_dx6[0]) - - # Get derivMin - with hcl.if_(dV_dx1_L[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_R[0] - - with hcl.if_(dV_dx5_L[0] < min_deriv5[0]): - min_deriv5[0] = dV_dx5_L[0] - with hcl.if_(dV_dx5_R[0] < min_deriv5[0]): - min_deriv5[0] = dV_dx5_R[0] - - with hcl.if_(dV_dx6_L[0] < min_deriv6[0]): - min_deriv6[0] = dV_dx6_L[0] - with hcl.if_(dV_dx6_R[0] < min_deriv6[0]): - min_deriv6[0] = dV_dx6_R[0] - - # Get derivMax - with hcl.if_(dV_dx1_L[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_R[0] - - with hcl.if_(dV_dx5_L[0] > max_deriv5[0]): - max_deriv5[0] = dV_dx5_L[0] - with hcl.if_(dV_dx5_R[0] > max_deriv5[0]): - max_deriv5[0] = dV_dx5_R[0] - - with hcl.if_(dV_dx6_L[0] > max_deriv6[0]): - max_deriv6[0] = dV_dx6_L[0] - with hcl.if_(dV_dx6_R[0] > max_deriv6[0]): - max_deriv6[0] = dV_dx6_R[0] - - # Calculate dissipation amount - with hcl.Stage("Dissipation"): - uOptL1 = hcl.scalar(0, "uOptL1") - uOptL2 = hcl.scalar(0, "uOptL2") - uOptL3 = hcl.scalar(0, "uOptL3") - uOptL4 = hcl.scalar(0, "uOptL4") - - uOptU1 = hcl.scalar(0, "uOptU1") - uOptU2 = hcl.scalar(0, "uOptU2") - uOptU3 = hcl.scalar(0, "uOptU3") - uOptU4 = hcl.scalar(0, "uOptU4") - - dOptL1 = hcl.scalar(0, "dOptL1") - dOptL2 = hcl.scalar(0, "dOptL2") - dOptL3 = hcl.scalar(0, "dOptL3") - dOptL4 = hcl.scalar(0, "dOptL4") - - dOptU1 = hcl.scalar(0, "dOptU1") - dOptU2 = hcl.scalar(0, "dOptU2") - dOptU3 = hcl.scalar(0, "dOptU3") - dOptU4 = hcl.scalar(0, "dOptU4") - - # Storing alphas - alpha1 = hcl.scalar(0, "alpha1") - alpha2 = hcl.scalar(0, "alpha2") - alpha3 = hcl.scalar(0, "alpha3") - alpha4 = hcl.scalar(0, "alpha4") - alpha5 = hcl.scalar(0, "alpha5") - alpha6 = hcl.scalar(0, "alpha6") - - """ - NOTE: If optimal adversarial disturbance is not dependent on states - , the below approximate LOWER/UPPER BOUND optimal disturbance is accurate. - If that's not the case, move the next two statements into the nested loops and modify the states passed in - as my_object.opt_dstb(t, (x1[i], x2[j], x3[k], x4[l], ...), ...). - The reason we don't have this line in the nested loop by default is to avoid redundant computations - for certain systems where disturbance are not dependent on states. - In general, dissipation amount can just be approximates. - """ - - # Find LOWER BOUND optimal disturbance - dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0] = my_object.opt_dstb(t, (x1[0], x2[0], x3[0], x4[0], x5[0], x6[0]), - (min_deriv1[0], min_deriv2[0], min_deriv3[0], min_deriv4[0], min_deriv5[0], min_deriv6[0])) - # Find UPPER BOUND optimal disturbance - dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0] = my_object.opt_dstb(t, (x1[0], x2[0], x3[0], x4[0], x5[0], x6[0]), - (max_deriv1[0], max_deriv2[0], max_deriv3[0], max_deriv4[0], max_deriv5[0], max_deriv6[0])) - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - with hcl.for_(0, V_init.shape[4], name="m") as m: - with hcl.for_(0, V_init.shape[5], name="n") as n: - dx_LL1 = hcl.scalar(0, "dx_LL1") - dx_LL2 = hcl.scalar(0, "dx_LL2") - dx_LL3 = hcl.scalar(0, "dx_LL3") - dx_LL4 = hcl.scalar(0, "dx_LL4") - dx_LL5 = hcl.scalar(0, "dx_LL5") - dx_LL6 = hcl.scalar(0, "dx_LL6") - - dx_UL1 = hcl.scalar(0, "dx_UL1") - dx_UL2 = hcl.scalar(0, "dx_UL2") - dx_UL3 = hcl.scalar(0, "dx_UL3") - dx_UL4 = hcl.scalar(0, "dx_UL4") - dx_UL5 = hcl.scalar(0, "dx_UL5") - dx_UL6 = hcl.scalar(0, "dx_UL6") - # - dx_LU1 = hcl.scalar(0, "dx_LU1") - dx_LU2 = hcl.scalar(0, "dx_LU2") - dx_LU3 = hcl.scalar(0, "dx_LU3") - dx_LU4 = hcl.scalar(0, "dx_LU4") - dx_LU5 = hcl.scalar(0, "dx_LU5") - dx_LU6 = hcl.scalar(0, "dx_LU6") - - dx_UU1 = hcl.scalar(0, "dx_UU1") - dx_UU2 = hcl.scalar(0, "dx_UU2") - dx_UU3 = hcl.scalar(0, "dx_UU3") - dx_UU4 = hcl.scalar(0, "dx_UU4") - dx_UU5 = hcl.scalar(0, "dx_UU5") - dx_UU6 = hcl.scalar(0, "dx_UU6") - - # Find LOWER BOUND optimal control - uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0] = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), ( - min_deriv1[0], min_deriv2[0], min_deriv3[0], min_deriv4[0], min_deriv5[0], - min_deriv6[0])) - # Find UPPER BOUND optimal control - uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0] = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), ( - max_deriv1[0], max_deriv2[0], max_deriv3[0], max_deriv4[0], max_deriv5[0], - max_deriv6[0])) - - # Get upper bound and lower bound rates of changes - dx_LL1[0], dx_LL2[0], dx_LL3[0], dx_LL4[0], dx_LL5[0], dx_LL6[ - 0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), (uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0]), - (dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0])) - # Get absolute value of each - dx_LL1[0] = my_abs(dx_LL1[0]) - dx_LL2[0] = my_abs(dx_LL2[0]) - dx_LL3[0] = my_abs(dx_LL3[0]) - dx_LL4[0] = my_abs(dx_LL4[0]) - dx_LL5[0] = my_abs(dx_LL5[0]) - dx_LL6[0] = my_abs(dx_LL6[0]) - - dx_UL1[0], dx_UL2[0], dx_UL3[0], dx_UL4[0], dx_UL5[0], dx_UL6[ - 0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), (uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0]), - (dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0])) - # Get absolute value of each - dx_UL1[0] = my_abs(dx_UL1[0]) - dx_UL2[0] = my_abs(dx_UL2[0]) - dx_UL3[0] = my_abs(dx_UL3[0]) - dx_UL4[0] = my_abs(dx_UL4[0]) - dx_UL5[0] = my_abs(dx_UL5[0]) - dx_UL6[0] = my_abs(dx_UL6[0]) - - # Set maximum alphas - alpha1[0] = my_max(dx_UL1[0], dx_LL1[0]) - alpha2[0] = my_max(dx_UL2[0], dx_LL2[0]) - alpha3[0] = my_max(dx_UL3[0], dx_LL3[0]) - alpha4[0] = my_max(dx_UL4[0], dx_LL4[0]) - alpha5[0] = my_max(dx_UL5[0], dx_LL5[0]) - alpha6[0] = my_max(dx_UL6[0], dx_LL6[0]) - - dx_LU1[0], dx_LU2[0], dx_LU3[0], dx_LU4[0], dx_LU5[0], dx_LU6[ - 0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), (uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0]), - (dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0])) - # Get absolute value of each - dx_LU1[0] = my_abs(dx_LU1[0]) - dx_LU2[0] = my_abs(dx_LU2[0]) - dx_LU3[0] = my_abs(dx_LU3[0]) - dx_LU4[0] = my_abs(dx_LU4[0]) - dx_LU5[0] = my_abs(dx_LU5[0]) - dx_LU6[0] = my_abs(dx_LU6[0]) - - alpha1[0] = my_max(alpha1[0], dx_LU1[0]) - alpha2[0] = my_max(alpha2[0], dx_LU2[0]) - alpha3[0] = my_max(alpha3[0], dx_LU3[0]) - alpha4[0] = my_max(alpha4[0], dx_LU4[0]) - alpha5[0] = my_max(alpha5[0], dx_LU5[0]) - alpha6[0] = my_max(alpha6[0], dx_LU6[0]) - - dx_UU1[0], dx_UU2[0], dx_UU3[0], dx_UU4[0], dx_UU5[0], dx_UU6[ - 0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), (uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0]), - (dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0])) - dx_UU1[0] = my_abs(dx_UU1[0]) - dx_UU2[0] = my_abs(dx_UU2[0]) - dx_UU3[0] = my_abs(dx_UU3[0]) - dx_UU4[0] = my_abs(dx_UU4[0]) - dx_UU5[0] = my_abs(dx_UU5[0]) - dx_UU6[0] = my_abs(dx_UU6[0]) - - alpha1[0] = my_max(alpha1[0], dx_UU1[0]) - alpha2[0] = my_max(alpha2[0], dx_UU2[0]) - alpha3[0] = my_max(alpha3[0], dx_UU3[0]) - alpha4[0] = my_max(alpha4[0], dx_UU4[0]) - alpha5[0] = my_max(alpha5[0], dx_UU5[0]) - alpha6[0] = my_max(alpha6[0], dx_UU6[0]) - - diss = hcl.scalar(0, "diss") - diss[0] = 0.5 * (deriv_diff1[i, j, k, l, m, n] * alpha1[0] + deriv_diff2[ - i, j, k, l, m, n] * alpha2[0] \ - + deriv_diff3[i, j, k, l, m, n] * alpha3[0] + deriv_diff4[ - i, j, k, l, m, n] * alpha4[0] \ - + deriv_diff5[i, j, k, l, m, n] * alpha5[0] + deriv_diff6[ - i, j, k, l, m, n] * alpha6[0]) - - # Finally - V_new[i, j, k, l, m, n] = -(V_new[i, j, k, l, m, n] - diss[0]) - # Get maximum alphas in each dimension - - # Calculate alphas - with hcl.if_(alpha1 > max_alpha1): - max_alpha1[0] = alpha1[0] - with hcl.if_(alpha2 > max_alpha2): - max_alpha2[0] = alpha2[0] - with hcl.if_(alpha3 > max_alpha3): - max_alpha3[0] = alpha3[0] - with hcl.if_(alpha4 > max_alpha4): - max_alpha4[0] = alpha4[0] - with hcl.if_(alpha5 > max_alpha5): - max_alpha5[0] = alpha5[0] - with hcl.if_(alpha6 > max_alpha6): - max_alpha6[0] = alpha6[0] - - # Determine time step - delta_t = hcl.compute((1,), lambda x: step_bound(), name="delta_t") - # hcl.update(t, lambda x: t[x] + delta_t[x]) - - # Integrate - # if compMethod == 'HJ_PDE': - result = hcl.update(V_new, - lambda i, j, k, l, m, n: V_init[i, j, k, l, m, n] + V_new[i, j, k, l, m, n] * delta_t[0]) - if compMethod == 'maxVWithV0' or compMethod == 'maxVWithVTarget': - result = hcl.update(V_new, lambda i, j, k, l, m, n: maxVWithV0(i, j, k, l, m, n)) - if compMethod == 'minVWithV0' or compMethod == 'minVWithVTarget': - result = hcl.update(V_new, lambda i, j, k, l, m, n: minVWithV0(i, j, k, l, m, n)) - if compMethod == 'maxVWithVInit': - result = hcl.update(V_new, lambda i, j, k, l, m, n: maxVWithVInit(i, j, k, l, m, n)) - if compMethod == 'minVWithVInit': - result = hcl.update(V_new, lambda i, j, k, l, m, n: minVWithVInit(i, j, k, l, m, n)) - # Copy V_new to V_init - hcl.update(V_init, lambda i, j, k, l, m, n: V_new[i, j, k, l, m, n]) - return result - - - s = hcl.create_schedule([V_f, V_init, x1, x2, x3, x4, x5, x6, t, l0], graph_create) - ##################### CODE OPTIMIZATION HERE ########################### - print("Optimizing\n") - - # Accessing the hamiltonian and dissipation stage - s_H = graph_create.Hamiltonian - s_D = graph_create.Dissipation - - # Thread parallelize hamiltonian and dissipation - s[s_H].parallel(s_H.i) - s[s_D].parallel(s_D.i) - - # Inspect IR - # if args.llvm: - # print(hcl.lower(s)) - - # Return executable - return (hcl.build(s)) diff --git a/odp/derivatives.py b/odp/derivatives.py new file mode 100644 index 00000000..eb2d3402 --- /dev/null +++ b/odp/derivatives.py @@ -0,0 +1,117 @@ +import heterocl as hcl +from . import math as hcl_math + +def spatial_derivative(left, right, axis, vf, grid, *idxs): + """1st order spatial derivative.""" + + axis_len = vf.shape[axis] + axis_step = grid.dx[axis] + + if grid.periodic_dims[axis]: + with hcl.if_(idxs[axis] == 0): + ## if n == 0 then... + ## left deriv := (vf[n] - vf[N]) / dx + ## right deriv := (vf[n+1] - vf[n]) / dx + + # pick last element of axis + ix = list(idxs) + ix[axis] = axis_len-1 + ix = tuple(ix) + left.v = vf[ix] + left.v = (vf[idxs] - left.v) / axis_step + + # pick element to the right + ix = list(idxs) + ix[axis] += 1 + ix = tuple(ix) + right.v = (vf[ix] - vf[idxs]) / axis_step + + with hcl.elif_(idxs[axis] == axis_len-1): + ## if n == N then... + ## left deriv := (vf[n] - vf[n-1]) / dx + ## right deriv := (vf[0] - vf[n]) / dx + + # pick element to the left + ix = list(idxs) + ix[axis] -= 1 + ix = tuple(ix) + left.v = (vf[idxs] - vf[ix]) / axis_step + + # pick first element of axis + ix = list(idxs) + ix[axis] = 0 + ix = tuple(ix) + right.v = vf[ix] # right boundary + right.v = (right.v - vf[idxs]) / axis_step + + with hcl.else_(): + + # pick element to the left + ix = list(idxs) + ix[axis] -= 1 + ix = tuple(ix) + left.v = (vf[idxs] - vf[ix]) / axis_step + + # pick element to the right + ix = list(idxs) + ix[axis] += 1 + ix = tuple(ix) + right.v = (vf[ix] - vf[idxs]) / axis_step + + else: + + # left boundary = vf[n] + sign(vf[n]) * |vf[n+1] - vf[n]| + # right boundary = vf[n] + sign(vf[n]) * |vf[n] - vf[n-1]| + + with hcl.if_(idxs[axis] == 0): + ## if n == 0 then... + ## left deriv := (vf[n] - LB) / dx + ## right deriv := (vf[n+1] - vf[n]) / dx + + # left boundary + ix = list(idxs) + ix[axis] += 1 + ix = tuple(ix) + left.v = vf[idxs] + hcl_math.sign(vf[idxs]) * hcl_math.abs(vf[ix] - vf[idxs]) + left.v = (vf[idxs] - left.v) / axis_step + + # element to the right + ix = list(idxs) + ix[axis] += 1 + ix = tuple(ix) + right.v = (vf[ix] - vf[idxs]) / axis_step + + with hcl.elif_(idxs[axis] == axis_len-1): + ## if n == N then... + ## left deriv := (vf[n] - vf[n-1]) / dx + ## right deriv := (RB - vf[n]) / dx + + # element to the left + ix = list(idxs) + ix[axis] -= 1 + ix = tuple(ix) + left.v = (vf[idxs] - vf[ix]) / axis_step + + # right boundary + ix = list(idxs) + ix[axis] -= 1 + ix = tuple(ix) + right.v = vf[idxs] + hcl_math.sign(vf[idxs]) * hcl_math.abs(vf[idxs] - vf[ix]) + right.v = (right.v - vf[idxs]) / axis_step + + with hcl.else_(): + + # element to the left + ix = list(idxs) + ix[axis] -= 1 + ix = tuple(ix) + left.v = (vf[idxs] - vf[ix]) / axis_step + + # element to the right + ix = list(idxs) + ix[axis] += 1 + ix = tuple(ix) + right.v = (vf[ix] - vf[idxs]) / axis_step + + return left.v, right.v + diff --git a/odp/drafts/6d_graph.py b/odp/drafts/6d_graph.py deleted file mode 100644 index 75e5aa9d..00000000 --- a/odp/drafts/6d_graph.py +++ /dev/null @@ -1,570 +0,0 @@ -import heterocl as hcl -import numpy as np -import time -import plotly.graph_objects as go -from GridProcessing import Grid -from ShapesFunctions import * -from CustomGraphFunctions import * -from Humannoid6D_sys1 import * -from argparse import ArgumentParser - -import scipy.io as sio - -import math - -""" USER INTERFACES -- Define grid - -- Generate initial values for grid using shape functions - -- Time length for computations - -- Run -""" - -# Grid field in this order: x, x_dot, z, z_dot, theta, theta_dot - -g = grid(np.array([-0.5, -1.0, 0.5, -2.0, -math.pi/2, -8.0]), np.array([0.5,1.0, 1.5, 2.0, math.pi/2, 8.0]), 6, np.array([29,29,29, 29, 29, 29])) # Leave out periodic field -# Define my object -my_humanoid = Humanoid_6D() - -# Use the grid to initialize initial value function -my_shape = Rectangle6D(g) - -# Constraint function --- g function -# cstraint_values = np.zeros((29, 29, 29, 29, 29, 29)) -# cstraint_values = cstraint_values + np.power(g.vs[0], 2) + np.power(g.vs[2], 2) - np.power(my_humanoid.L,2) - -# Initialization -- V_0 = max{l(x_1, t_0), g(x_1, t_0)}; it's called my_shape for now -# my_shape = np.maximum(my_shape, cstraint_values) - - -# Look-back lenght and time step -lookback_length = 2.0 -t_step = 0.05 - -tau = np.arange(start = 0, stop = lookback_length + t_step, step = t_step) -print("I'm here \n") - -compMethod = "Nothing" -my_object = my_humanoid - -#parameters = { "object": myROV_6D} - -# Note that t has 2 elements t1, t2 -def graph_6D(V_new, V_init, deriv_diff1, deriv_diff2, deriv_diff3, deriv_diff4, deriv_diff5, deriv_diff6, - x1, x2, x3, x4, x5, x6 ,t , l0, obstacle): - # Maximum derivative for each dim - max_deriv1 = hcl.scalar(-1e9, "max_deriv1") - max_deriv2 = hcl.scalar(-1e9, "max_deriv2") - max_deriv3 = hcl.scalar(-1e9, "max_deriv3") - max_deriv4 = hcl.scalar(-1e9, "max_deriv4") - max_deriv5 = hcl.scalar(-1e9, "max_deriv5") - max_deriv6 = hcl.scalar(-1e9, "max_deriv6") - - # Min derivative for each dim - min_deriv1 = hcl.scalar(1e9, "min_deriv1") - min_deriv2 = hcl.scalar(1e9, "min_deriv2") - min_deriv3 = hcl.scalar(1e9, "min_deriv3") - min_deriv4 = hcl.scalar(1e9, "min_deriv4") - min_deriv5 = hcl.scalar(1e9, "min_deriv5") - min_deriv6 = hcl.scalar(1e9, "min_deriv6") - - # These variables are used to dissipation calculation - max_alpha1 = hcl.scalar(-1e9, "max_alpha1") - max_alpha2 = hcl.scalar(-1e9, "max_alpha2") - max_alpha3 = hcl.scalar(-1e9, "max_alpha3") - max_alpha4 = hcl.scalar(-1e9, "max_alpha4") - max_alpha5 = hcl.scalar(-1e9, "max_alpha5") - max_alpha6 = hcl.scalar(-1e9, "max_alpha6") - - def step_bound(): # Function to calculate time step - stepBoundInv = hcl.scalar(0, "stepBoundInv") - stepBound = hcl.scalar(0, "stepBound") - stepBoundInv[0] = max_alpha1[0]/g.dx[0] + max_alpha2[0]/g.dx[1] + max_alpha3[0]/g.dx[2] + max_alpha4[0]/g.dx[3] \ - + max_alpha5[0]/g.dx[4] + max_alpha6[0]/g.dx[5] - - stepBound[0] = 0.8/stepBoundInv[0] - with hcl.if_(stepBound > t[1] - t[0]): - stepBound[0] = t[1] - t[0] - - # Update the lower time ranges - t[0] = t[0] + stepBound[0] - #t[0] = min_deriv2[0] - return stepBound[0] - - def maxVWithV0(i, j, k, l, m, n): # Take the max - with hcl.if_(V_new[i, j, k, l, m, n] < l0[i, j, k, l, m, n]): - V_new[i, j, k, l, m, n] = l0[i, j, k, l, m, n] - - # Max(V, g ) - def maxVWithCStraint(i, j, k, l, m, n): - with hcl.if_(V_new[i, j, k, l, m, n] < obstacle[i, j, k, l, m, n]): - V_new[i, j, k, l, m, n] = obstacle[i, j, k, l, m, n] - - # Calculate Hamiltonian for every grid point in V_init - with hcl.Stage("Hamiltonian"): - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - with hcl.for_(0, V_init.shape[4], name="m") as m: - with hcl.for_(0, V_init.shape[5], name="n") as n: - #Variables to calculate dV_dx - dV_dx1_L = hcl.scalar(0, "dV_dx1_L") - dV_dx1_R = hcl.scalar(0, "dV_dx1_R") - dV_dx1 = hcl.scalar(0, "dV_dx1") - dV_dx2_L = hcl.scalar(0, "dV_dx2_L") - dV_dx2_R = hcl.scalar(0, "dV_dx2_R") - dV_dx2 = hcl.scalar(0, "dV_dx2") - dV_dx3_L = hcl.scalar(0, "dV_dx3_L") - dV_dx3_R = hcl.scalar(0, "dV_dx3_R") - dV_dx3 = hcl.scalar(0, "dV_dx3") - dV_dx4_L = hcl.scalar(0, "dV_dx4_L") - dV_dx4_R = hcl.scalar(0, "dV_dx4_R") - dV_dx4 = hcl.scalar(0, "dV_dx4") - dV_dx5_L = hcl.scalar(0, "dV_dx5_L") - dV_dx5_R = hcl.scalar(0, "dV_dx5_R") - dV_dx5 = hcl.scalar(0, "dV_dx5") - dV_dx6_L = hcl.scalar(0, "dV_dx6_L") - dV_dx6_R = hcl.scalar(0, "dV_dx6_R") - dV_dx6 = hcl.scalar(0, "dV_dx6") - - # No tensor slice operation - #dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - dV_dx1_L[0], dV_dx1_R[0] = spa_derivX6_6d(i, j, k, l, m, n, V_init, g) - dV_dx2_L[0], dV_dx2_R[0] = spa_derivX5_6d(i, j, k, l, m, n, V_init, g) - dV_dx3_L[0], dV_dx3_R[0] = spa_derivX4_6d(i, j, k, l, m, n, V_init, g) - dV_dx4_L[0], dV_dx4_R[0] = spa_derivX3_6d(i, j, k, l, m, n, V_init, g) - dV_dx5_L[0], dV_dx5_R[0] = spa_derivX2_6d(i, j, k, l, m, n, V_init, g) - dV_dx6_L[0], dV_dx6_R[0] = spa_derivX1_6d(i, j, k, l, m, n, V_init, g) - - # Saves spatial derivative diff into tables - deriv_diff1[i, j, k, l, m, n] = dV_dx1_R[0] - dV_dx1_L[0] - deriv_diff2[i, j, k, l, m, n] = dV_dx2_R[0] - dV_dx2_L[0] - deriv_diff3[i, j, k, l, m, n] = dV_dx3_R[0] - dV_dx3_L[0] - deriv_diff4[i, j, k, l, m, n] = dV_dx4_R[0] - dV_dx4_L[0] - deriv_diff5[i, j, k, l, m, n] = dV_dx5_R[0] - dV_dx5_L[0] - deriv_diff6[i, j, k, l, m, n] = dV_dx6_R[0] - dV_dx6_L[0] - - #Calculate average gradient - dV_dx1[0] = (dV_dx1_L + dV_dx1_R) / 2 - dV_dx2[0] = (dV_dx2_L + dV_dx2_R) / 2 - dV_dx3[0] = (dV_dx3_L + dV_dx3_R) / 2 - dV_dx4[0] = (dV_dx4_L + dV_dx4_R) / 2 - dV_dx5[0] = (dV_dx5_L + dV_dx5_R) / 2 - dV_dx6[0] = (dV_dx6_L + dV_dx6_R) / 2 - - - # Find optimal control - uOpt = my_object.opt_ctrl(t,(x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), (dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0], dV_dx6[0])) - # Find optimal disturbance - dOpt = my_object.opt_dstb((dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0], dV_dx6[0])) - - # Find rates of changes based on dynamics equation - dx1_dt, dx2_dt, dx3_dt, dx4_dt, dx5_dt, dx6_dt = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), uOpt, dOpt) - - # Calculate Hamiltonian terms: - V_new[i, j, k, l, m, n] = -(dx1_dt * dV_dx1[0] + dx2_dt * dV_dx2[0] + dx3_dt * dV_dx3[0] + dx4_dt * dV_dx4[0] + dx5_dt * dV_dx5[0] + dx6_dt * dV_dx6[0]) - - # Get derivMin - with hcl.if_(dV_dx1_L[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_R[0] - - with hcl.if_(dV_dx5_L[0] < min_deriv5[0]): - min_deriv5[0] = dV_dx5_L[0] - with hcl.if_(dV_dx5_R[0] < min_deriv5[0]): - min_deriv5[0] = dV_dx5_R[0] - - with hcl.if_(dV_dx6_L[0] < min_deriv6[0]): - min_deriv6[0] = dV_dx6_L[0] - with hcl.if_(dV_dx6_R[0] < min_deriv6[0]): - min_deriv6[0] = dV_dx6_R[0] - - # Get derivMax - with hcl.if_(dV_dx1_L[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_R[0] - - with hcl.if_(dV_dx5_L[0] > max_deriv5[0]): - max_deriv5[0] = dV_dx5_L[0] - with hcl.if_(dV_dx5_R[0] > max_deriv5[0]): - max_deriv5[0] = dV_dx5_R[0] - - with hcl.if_(dV_dx6_L[0] > max_deriv6[0]): - max_deriv6[0] = dV_dx6_L[0] - with hcl.if_(dV_dx6_R[0] > max_deriv6[0]): - max_deriv6[0] = dV_dx6_R[0] - - # Calculate dissipation amount - with hcl.Stage("Dissipation"): - hcl.scalar(0, "uOptL1") - hcl.scalar(0, "uOptL2") - hcl.scalar(0, "uOptL3") - hcl.scalar(0, "uOptL4") - - - hcl.scalar(0, "uOptU1") - hcl.scalar(0, "uOptU2") - hcl.scalar(0, "uOptU3") - hcl.scalar(0, "uOptU4") - - hcl.scalar(0, "dOptL1") - hcl.scalar(0, "dOptL2") - hcl.scalar(0, "dOptL3") - hcl.scalar(0, "dOptL4") - - hcl.scalar(0, "dOptU1") - hcl.scalar(0, "dOptU2") - hcl.scalar(0, "dOptU3") - hcl.scalar(0, "dOptU4") - - # Storing alphas - alpha1 = hcl.scalar(0, "alpha1") - alpha2 = hcl.scalar(0, "alpha2") - alpha3 = hcl.scalar(0, "alpha3") - alpha4 = hcl.scalar(0, "alpha4") - alpha5 = hcl.scalar(0, "alpha5") - alpha6 = hcl.scalar(0, "alpha6") - - # Find LOWER BOUND optimal disturbance - dOptL = my_object.opt_dstb((min_deriv1[0], min_deriv2[0], min_deriv3[0], min_deriv4[0], min_deriv5[0], min_deriv6[0])) - # Find UPPER BOUND optimal disturbance - dOptU = my_object.opt_dstb((max_deriv1[0], max_deriv2[0], max_deriv3[0], max_deriv4[0], min_deriv5[0], min_deriv6[0])) - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - with hcl.for_(0, V_init.shape[4], name="m") as m: - with hcl.for_(0, V_init.shape[5], name="n") as n: - dx_LL1 = hcl.scalar(0, "dx_LL1") - dx_LL2 = hcl.scalar(0, "dx_LL2") - dx_LL3 = hcl.scalar(0, "dx_LL3") - dx_LL4 = hcl.scalar(0, "dx_LL4") - dx_LL5 = hcl.scalar(0, "dx_LL5") - dx_LL6 = hcl.scalar(0, "dx_LL6") - - dx_UL1 = hcl.scalar(0, "dx_UL1") - dx_UL2 = hcl.scalar(0, "dx_UL2") - dx_UL3 = hcl.scalar(0, "dx_UL3") - dx_UL4 = hcl.scalar(0, "dx_UL4") - dx_UL5 = hcl.scalar(0, "dx_UL5") - dx_UL6 = hcl.scalar(0, "dx_UL6") - # - dx_LU1 = hcl.scalar(0, "dx_LU1") - dx_LU2 = hcl.scalar(0, "dx_LU2") - dx_LU3 = hcl.scalar(0, "dx_LU3") - dx_LU4 = hcl.scalar(0, "dx_LU4") - dx_LU5 = hcl.scalar(0, "dx_LU5") - dx_LU6 = hcl.scalar(0, "dx_LU6") - - dx_UU1 = hcl.scalar(0, "dx_UU1") - dx_UU2 = hcl.scalar(0, "dx_UU2") - dx_UU3 = hcl.scalar(0, "dx_UU3") - dx_UU4 = hcl.scalar(0, "dx_UU4") - dx_UU5 = hcl.scalar(0, "dx_UU5") - dx_UU6 = hcl.scalar(0, "dx_UU6") - - # Find LOWER BOUND optimal control - uOptL = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), (min_deriv1[0], min_deriv2[0], min_deriv3[0], min_deriv4[0], min_deriv5[0], min_deriv6[0])) - # Find UPPER BOUND optimal control - uOptU = my_object.opt_ctrl(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), (max_deriv1[0], max_deriv2[0], max_deriv3[0], max_deriv4[0], max_deriv5[0], max_deriv6[0])) - - # Get upper bound and lower bound rates of changes - dx_LL1[0], dx_LL2[0], dx_LL3[0], dx_LL4[0], dx_LL5[0], dx_LL6[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), uOptL, dOptL) - # Get absolute value of each - dx_LL1[0] = my_abs(dx_LL1[0]) - dx_LL2[0] = my_abs(dx_LL2[0]) - dx_LL3[0] = my_abs(dx_LL3[0]) - dx_LL4[0] = my_abs(dx_LL4[0]) - dx_LL5[0] = my_abs(dx_LL5[0]) - dx_LL6[0] = my_abs(dx_LL6[0]) - - dx_UL1[0], dx_UL2[0], dx_UL3[0], dx_UL4[0], dx_UL5[0], dx_UL6[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), uOptU, dOptL) - # Get absolute value of each - dx_UL1[0] = my_abs(dx_UL1[0]) - dx_UL2[0] = my_abs(dx_UL2[0]) - dx_UL3[0] = my_abs(dx_UL3[0]) - dx_UL4[0] = my_abs(dx_UL4[0]) - dx_UL5[0] = my_abs(dx_UL5[0]) - dx_UL6[0] = my_abs(dx_UL6[0]) - - # Set maximum alphas - alpha1[0] = my_max(dx_UL1[0], dx_LL1[0]) - alpha2[0] = my_max(dx_UL2[0], dx_LL2[0]) - alpha3[0] = my_max(dx_UL3[0], dx_LL3[0]) - alpha4[0] = my_max(dx_UL4[0], dx_LL4[0]) - alpha5[0] = my_max(dx_UL5[0], dx_LL5[0]) - alpha6[0] = my_max(dx_UL6[0], dx_LL6[0]) - - dx_LU1[0], dx_LU2[0], dx_LU3[0], dx_LU4[0], dx_LU5[0], dx_LU6[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), uOptL, dOptU) - # Get absolute value of each - dx_LU1[0] = my_abs(dx_LU1[0]) - dx_LU2[0] = my_abs(dx_LU2[0]) - dx_LU3[0] = my_abs(dx_LU3[0]) - dx_LU4[0] = my_abs(dx_LU4[0]) - dx_LU5[0] = my_abs(dx_LU5[0]) - dx_LU6[0] = my_abs(dx_LU6[0]) - - alpha1[0] = my_max(alpha1[0], dx_LU1[0]) - alpha2[0] = my_max(alpha2[0], dx_LU2[0]) - alpha3[0] = my_max(alpha3[0], dx_LU3[0]) - alpha4[0] = my_max(alpha4[0], dx_LU4[0]) - alpha5[0] = my_max(alpha5[0], dx_LU5[0]) - alpha6[0] = my_max(alpha6[0], dx_LU6[0]) - - dx_UU1[0], dx_UU2[0], dx_UU3[0], dx_UU4[0], dx_UU5[0], dx_UU6[0] = my_object.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), uOptU, dOptU) - dx_UU1[0] = my_abs(dx_UU1[0]) - dx_UU2[0] = my_abs(dx_UU2[0]) - dx_UU3[0] = my_abs(dx_UU3[0]) - dx_UU4[0] = my_abs(dx_UU4[0]) - dx_UU5[0] = my_abs(dx_UU5[0]) - dx_UU6[0] = my_abs(dx_UU6[0]) - - alpha1[0] = my_max(alpha1[0], dx_UU1[0]) - alpha2[0] = my_max(alpha2[0], dx_UU2[0]) - alpha3[0] = my_max(alpha3[0], dx_UU3[0]) - alpha4[0] = my_max(alpha4[0], dx_UU4[0]) - alpha5[0] = my_max(alpha5[0], dx_UU5[0]) - alpha6[0] = my_max(alpha6[0], dx_UU6[0]) - - diss = hcl.scalar(0, "diss") - diss[0] = 0.5*(deriv_diff1[i, j, k, l, m, n]*alpha1[0] + deriv_diff2[i, j, k, l, m, n]*alpha2[0] \ - + deriv_diff3[i, j, k, l, m, n]* alpha3[0] + deriv_diff4[i, j, k, l, m, n]* alpha4[0] \ - + deriv_diff5[i, j, k, l, m, n]* alpha5[0] + deriv_diff6[i, j, k, l, m, n]* alpha6[0]) - - # Finally - V_new[i, j, k, l, m, n] = -(V_new[i, j, k, l, m, n] - diss[0]) - # Get maximum alphas in each dimension - - # Calculate alphas - with hcl.if_(alpha1 > max_alpha1): - max_alpha1[0] = alpha1[0] - with hcl.if_(alpha2 > max_alpha2): - max_alpha2[0] = alpha2[0] - with hcl.if_(alpha3 > max_alpha3): - max_alpha3[0] = alpha3[0] - with hcl.if_(alpha4 > max_alpha4): - max_alpha4[0] = alpha4[0] - with hcl.if_(alpha5 > max_alpha5): - max_alpha5[0] = alpha5[0] - with hcl.if_(alpha6 > max_alpha6): - max_alpha6[0] = alpha6[0] - - - # Determine time step - delta_t = hcl.compute((1,), lambda x: step_bound(), name="delta_t") - #hcl.update(t, lambda x: t[x] + delta_t[x]) - - # Integrate - #if compMethod == 'HJ_PDE': - result = hcl.update(V_new, lambda i, j, k, l, m, n: V_init[i, j, k, l, m, n] + V_new[i, j, k, l, m, n] * delta_t[0]) - if compMethod == 'maxVWithV0': - result = hcl.update(V_new, lambda i, j, k, l, m, n: maxVWithV0(i, j, k, l, m, n)) - if compMethod == 'maxVWithCStraint': - result = hcl.update(V_new, lambda i, j, k, l, m, n: maxVWithCStraint(i, j, k, l, m, n)) - # Copy V_new to V_init - hcl.update(V_init, lambda i, j, k, l, m, n: V_new[i, j, k, l, m, n]) - return result - -def main(): - ################### PARSING ARGUMENTS FROM USERS ##################### - - parser = ArgumentParser() - parser.add_argument("-p", "--plot", default=False, type=bool) - # Print out LLVM option only - parser.add_argument("-l", "--llvm", default=False, type=bool) - args = parser.parse_args() - - hcl.init() - hcl.config.init_dtype = hcl.Float() - - ################## DATA SHAPE PREPARATION FOR GRAPH FORMATION #################### - V_f = hcl.placeholder(tuple(g.pts_each_dim), name="V_f", dtype = hcl.Float()) - V_init = hcl.placeholder(tuple(g.pts_each_dim), name="V_init", dtype=hcl.Float()) - l0 = hcl.placeholder(tuple(g.pts_each_dim), name="l0", dtype=hcl.Float()) - #x = hcl.placeholder((6, g.pts_each_dim[0]), name="x", dtype=hcl.Float()) - t = hcl.placeholder((2,), name="t", dtype=hcl.Float()) - - # Deriv diff tensor - deriv_diff1 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff1") - deriv_diff2 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff2") - deriv_diff3 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff3") - deriv_diff4 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff4") - deriv_diff5 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff5") - deriv_diff6 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff6") - - # Positions vector - x1 = hcl.placeholder((g.pts_each_dim[0],), name="x1", dtype=hcl.Float()) - x2 = hcl.placeholder((g.pts_each_dim[1],), name="x2", dtype=hcl.Float()) - x3 = hcl.placeholder((g.pts_each_dim[2],), name="x3", dtype=hcl.Float()) - x4 = hcl.placeholder((g.pts_each_dim[3],), name="x4", dtype=hcl.Float()) - x5 = hcl.placeholder((g.pts_each_dim[4],), name="x5", dtype=hcl.Float()) - x6 = hcl.placeholder((g.pts_each_dim[5],), name="x6", dtype=hcl.Float()) - - # Obstacle placeholder - obstacle = hcl.placeholder((tuple(g.pts_each_dim)), name="obstacle") - - ##################### CREATE SCHEDULE############## - - # Create schedule - s = hcl.create_schedule( - [V_f, V_init, deriv_diff1, deriv_diff2, deriv_diff3, deriv_diff4, deriv_diff5, deriv_diff6, x1, x2, x3, x4, x5, x6, t, l0, obstacle], graph_6D) - - # Inspect the LLVM code - print(hcl.lower(s)) - - - - ################# INITIALIZE DATA TO BE INPUT INTO GRAPH ########################## - - print("Initializing\n") - - V_0 = hcl.asarray(my_shape) - V_1 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - l0 = hcl.asarray(my_shape) - obstacle = hcl.asarray(cstraint_values) - - list_x1 = np.reshape(g.vs[0], g.pts_each_dim[0]) - list_x2 = np.reshape(g.vs[1], g.pts_each_dim[1]) - list_x3 = np.reshape(g.vs[2], g.pts_each_dim[2]) - list_x4 = np.reshape(g.vs[3], g.pts_each_dim[3]) - list_x5 = np.reshape(g.vs[4], g.pts_each_dim[4]) - list_x6 = np.reshape(g.vs[5], g.pts_each_dim[5]) - - # Convert to hcl array type - list_x1 = hcl.asarray(list_x1) - list_x2 = hcl.asarray(list_x2) - list_x3 = hcl.asarray(list_x3) - list_x4 = hcl.asarray(list_x4) - list_x5 = hcl.asarray(list_x5) - list_x6 = hcl.asarray(list_x6) - - # Initialize deriv diff tensor - deriv_diff1 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff2 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff3 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff4 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff5 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff6 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - - - ##################### CODE OPTIMIZATION HERE ########################### - print("Optimizing\n") - - # Accessing the hamiltonian stage - s_H = graph_6D.Hamiltonian - s_D = graph_6D.Dissipation - - # - s[s_H].parallel(s_H.i) - s[s_D].parallel(s_D.i) - - # Inspect IR - #if args.llvm: - # print(hcl.lower(s)) - - ################ GET EXECUTABLE AND USE THE EXECUTABLE ############ - print("Running\n") - - # Get executable - solve_pde = hcl.build(s) - - # Variables used for timing - execution_time = 0 - lookback_time = 0 - - tNow = tau[0] - for i in range (1, len(tau)): - #tNow = tau[i-1] - t_minh= hcl.asarray(np.array((tNow, tau[i]))) - while tNow <= tau[i] - 1e-4: - # Start timing - start = time.time() - - # Run the execution and pass input into graph - solve_pde(V_1, V_0, deriv_diff1, deriv_diff2, deriv_diff3, deriv_diff4, deriv_diff5, deriv_diff6, - list_x1, list_x2, list_x3, list_x4, list_x5, list_x6, t_minh, l0, obstacle) - - tNow = np.asscalar((t_minh.asnumpy())[0]) - - if lookback_time != 0: # Exclude first time of the computation - execution_time += time.time() - start - - # Some information printing - print(t_minh) - print("Computational time to integrate (s): {:.5f}".format(time.time() - start)) - # Saving data into disk - if tNow >= tau[i] - 1e-4: - print("Saving files\n") - sio.savemat('/local-scratch/Humannoid/humannoid_v_{:d}.mat'.format(i), {'V_array': V_1.asnumpy()}) - - #print(V_1.asnumpy()) - # - # V_1 = V_1.asnumpy() - # # V_1 = np.swapaxes(V_1, 0,2) - # #V = np.swapaxes(V, 1,2) - # #probe = probe.asnumpy() - # #probe = np.swapaxes(probe, 0, 2) - # #probe = np.swapaxes(probe, 1, 2) - # #print(V) - # #V_1 = V_1.asnumpy() - # - # - # Time info printing - print("Total kernel time (s): {:.5f}".format(execution_time)) - print("Finished solving\n") - - ##################### PLOTTING ##################### - if args.plot: - print("Plotting beautiful plots. Please wait\n") - fig = go.Figure(data=go.Isosurface( - x=g.mg_X.flatten(), - y=g.mg_Y.flatten(), - z=g.mg_T.flatten(), - value=V_1.flatten(), - colorscale='jet', - isomin=0, - surface_count=1, - isomax=0, - caps=dict(x_show=True, y_show=True) - )) - fig.show() - print("Please check the plot on your browser.") - - -if __name__ == '__main__': - main() diff --git a/odp/drafts/HJ_PDE_HeteroCL.py b/odp/drafts/HJ_PDE_HeteroCL.py deleted file mode 100644 index 77d627e9..00000000 --- a/odp/drafts/HJ_PDE_HeteroCL.py +++ /dev/null @@ -1,287 +0,0 @@ -import heterocl as hcl -import numpy as np -import time -import plotly.graph_objects as go -from GridProcessing import Grid -from ShapesFunctions import * -from CustomGraphFunctions import * -from DubinsCar import * - -import math - -""" USER INTERFACES -- Define grid - -- Generate initial values for grid using shape functions - -- Time length for computations - -- Run -""" - -# Create a grid -g = grid(np.array([-5.0, -5.0, -math.pi]), np.array([5.0, 5.0, math.pi]), 3 ,np.array([100,100,100]), 2) -# Use the grid to initialize initial value function -shape = CyclinderShape(g, 3, np.zeros(3), 1) -# Define my car -myCar = DubinsCar(x=np.array([0,0,0]), wMax=1, speed=1, dMax=np.array([0,0,0]), uMode="min", dMode="max") - -# Look-back lenght and time step -lookback_length = 1.00 -t_step = 0.05 - - - - -def HJ_PDE_solver(V_new, V_init, thetas ,t): - - # These variables are used to dissipation calculation - max_alpha1 = hcl.scalar(-1e9, "max_alpha1") - max_alpha2 = hcl.scalar(-1e9, "max_alpha2") - max_alpha3 = hcl.scalar(-1e9, "max_alpha3") - - # Calculate spatial derivative - def spa_derivX(i, j, k): - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - with hcl.if_(i == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V_init[i, j, k] + my_abs(V_init[i + 1, j, k] - V_init[i, j, k]) * my_sign( - V_init[i, j, k]) - left_deriv[0] = (V_init[i, j, k] - left_boundary[0]) / g.dx[0] - right_deriv[0] = (V_init[i + 1, j, k] - V_init[i, j, k]) / g.dx[0] - with hcl.elif_(i == V_init.shape[0] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V_init[i, j, k] + my_abs(V_init[i, j, k] - V_init[i - 1, j, k]) * my_sign( - V_init[i, j, k]) - left_deriv[0] = (V_init[i, j, k] - V_init[i - 1, j, k]) / g.dx[0] - right_deriv[0] = (right_boundary[0] - V_init[i, j, k]) / g.dx[0] - with hcl.elif_(i != 0 and i != V_init.shape[0] - 1): - left_deriv[0] = (V_init[i, j, k] - V_init[i - 1, j, k]) / g.dx[0] - right_deriv[0] = (V_init[i + 1, j, k] - V_init[i, j, k]) / g.dx[0] - return left_deriv[0], right_deriv[0] - - def spa_derivY(i, j, k): - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - with hcl.if_(j == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V_init[i, j, k] + my_abs(V_init[i, j + 1, k] - V_init[i, j, k]) * my_sign( - V_init[i, j, k]) - left_deriv[0] = (V_init[i, j, k] - left_boundary[0]) / g.dx[1] - right_deriv[0] = (V_init[i, j + 1, k] - V_init[i, j, k]) / g.dx[1] - with hcl.elif_(j == V_init.shape[1] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V_init[i, j, k] + my_abs(V_init[i, j, k] - V_init[i, j - 1, k]) * my_sign( - V_init[i, j, k]) - left_deriv[0] = (V_init[i, j, k] - V_init[i, j - 1, k]) / g.dx[1] - right_deriv[0] = (right_boundary[0] - V_init[i, j, k]) / g.dx[1] - with hcl.elif_(j != 0 and j != V_init.shape[1] - 1): - left_deriv[0] = (V_init[i, j, k] - V_init[i, j - 1, k]) / g.dx[1] - right_deriv[0] = (V_init[i, j + 1, k] - V_init[i, j, k]) / g.dx[1] - return left_deriv[0], right_deriv[0] - - def spa_derivT(i, j, k): - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - with hcl.if_(k == 0): - left_boundary = hcl.scalar(0, "left_boundary") - # left_boundary[0] = V_init[i,j,50] - left_boundary[0] = V_init[i, j, V_init.shape[2] - 1] - left_deriv[0] = (V_init[i, j, k] - left_boundary[0]) / g.dx[2] - right_deriv[0] = (V_init[i, j, k + 1] - V_init[i, j, k]) / g.dx[2] - with hcl.elif_(k == V_init.shape[2] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V_init[i, j, 0] - left_deriv[0] = (V_init[i, j, k] - V_init[i, j, k - 1]) / g.dx[2] - right_deriv[0] = (right_boundary[0] - V_init[i, j, k]) / g.dx[2] - with hcl.elif_(k != 0 and k != V_init.shape[2] - 1): - left_deriv[0] = (V_init[i, j, k] - V_init[i, j, k - 1]) / g.dx[2] - right_deriv[0] = (V_init[i, j, k + 1] - V_init[i, j, k]) / g.dx[2] - return left_deriv[0], right_deriv[0] - - def step_bound(): # Function to calculate time step - stepBoundInv = hcl.scalar(0, "stepBoundInv") - stepBound = hcl.scalar(0, "stepBound") - stepBoundInv[0] = max_alpha1[0]/g.dx[0] + max_alpha2[0]/g.dx[1] + max_alpha3[0]/g.dx[2] - - stepBound[0] = 0.8/stepBoundInv[0] - with hcl.if_(stepBound > t_step): - stepBound[0] = t_step - time = stepBound[0] - return time - - # Calculate Hamiltonian for every grid point in V_init - with hcl.Stage("Hamiltonian"): - with hcl.for_(0, V_init.shape[0], name="k") as k: # Plus 1 as for loop count stops at V_init.shape[0] - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="i") as i: - # Variables to calculate dV_dx - dV_dx_L = hcl.scalar(0, "dV_dx_L") - dV_dx_R = hcl.scalar(0, "dV_dx_R") - dV_dx = hcl.scalar(0, "dV_dx") - # Variables to calculate dV_dy - dV_dy_L = hcl.scalar(0, "dV_dy_L") - dV_dy_R = hcl.scalar(0, "dV_dy_R") - dV_dy = hcl.scalar(0, "dV_dy") - # Variables to calculate dV_dtheta - dV_dT_L = hcl.scalar(0, "dV_dT_L") - dV_dT_R = hcl.scalar(0, "dV_dT_R") - dV_dT = hcl.scalar(0, "dV_dT") - # Variables to keep track of dynamics - #dx_dt = hcl.scalar(0, "dx_dt") - #dy_dt = hcl.scalar(0, "dy_dt") - #dtheta_dt = hcl.scalar(0, "dtheta_dt") - - # No tensor slice operation - dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - dV_dy_L[0], dV_dy_R[0] = spa_derivY(i, j, k) - dV_dT_L[0], dV_dT_R[0] = spa_derivT(i, j, k) - - # Calculate average gradient - dV_dx[0] = (dV_dx_L + dV_dx_R) / 2 - dV_dy[0] = (dV_dy_L + dV_dy_R) / 2 - dV_dT[0] = (dV_dT_L + dV_dT_R) / 2 - - # Use method of DubinsCar to solve optimal control instead - uOpt = myCar.opt_ctrl((dV_dx[0], dV_dy[0], dV_dT[0])) - - # Calculate dynamical rates of changes - dx_dt, dy_dt, dtheta_dt = myCar.dynamics(thetas[k], uOpt) - - # Calculate Hamiltonian terms: - V_new[i, j, k] = -(dx_dt * dV_dx[0] + dy_dt * dV_dy[0] + dtheta_dt * dV_dT[0]) - - # Calculate dissipation step - dx_dt = my_abs(dx_dt) - dy_dt = my_abs(dy_dt) - dtheta_dt = my_abs(dtheta_dt) - diss = hcl.scalar(0, "diss") - diss[0] = 0.5*((dV_dx_R[0] - dV_dx_L[0])*dx_dt + (dV_dy_R[0] - dV_dy_L[0])*dy_dt + (dV_dT_R[0] - dV_dT_L[0])* dtheta_dt) - V_new[i, j, k] = -(V_new[i, j, k] - diss[0]) - - # Calculate alphas - with hcl.if_(dx_dt > max_alpha1): - max_alpha1[0] = dx_dt - with hcl.if_(dy_dt > max_alpha2): - max_alpha2[0] = dy_dt - with hcl.if_(dtheta_dt > max_alpha3): - max_alpha3[0] = dtheta_dt - - # Determine time step - hcl.update(t, lambda x: step_bound()) - # Integrate - result = hcl.update(V_new, lambda i,j,k: V_init[i,j,k] + V_new[i,j,k] * t[0]) - # Copy V_new to V_init - hcl.update(V_init, lambda i,j,k: V_new[i,j,k] ) - return result - -def main(): - hcl.init() - hcl.config.init_dtype = hcl.Float() - V_f = hcl.placeholder(tuple(g.pts_each_dim), name="V_f", dtype = hcl.Float()) - V_init = hcl.placeholder(tuple(g.pts_each_dim), name="V_init", dtype=hcl.Float()) - thetas = hcl.placeholder((g.pts_each_dim[2],), name="thetas", dtype=hcl.Float()) - t = hcl.placeholder((1,), name="t", dtype=hcl.Float()) - - # Create schedule - s = hcl.create_schedule([V_f, V_init, thetas,t], HJ_PDE_solver) - - # Here comes the optimization - - # Accessing the hamiltonian stage - s_H = HJ_PDE_solver.Hamiltonian - # Split the loops - k_out, k_in = s[s_H].split(s_H.k, 10) # These numbers are experimental, changable - j_out, j_in = s[s_H].split(s_H.j, 10) - i_out, i_in = s[s_H].split(s_H.i, 10) - - # Reorder the loops - s[s_H].reorder(j_out, k_in) - s[s_H].reorder(i_out, k_in) - s[s_H].reorder(k_in, j_in) - - # FPGA Back end - parallel specs - s[s_H].pipeline(k_in) - s[s_H].unroll(i_out, 5) - - # If CPU option - s[s_H].parallel(k_out) - - # Inspect IR - #print(hcl.lower(s)) - - # Build the code - solve_pde = hcl.build(s) - - #print(f) - - # Prepare numpy array for graph computation - V_0 = hcl.asarray(shape) - V_1= hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - - - t_minh = hcl.asarray(np.zeros(1)) - - # List thetas - list_theta = np.reshape(g.vs[2], g.pts_each_dim[2]) - list_theta = hcl.asarray(list_theta) - - - # Variables used for timing - execution_time = 0 - lookback_time = 0 - - print("I'm here\n") - # Test the executable from heteroCL: - while lookback_time <= lookback_length: - # Start timing - start = time.time() - - # Printing some info - #print("Look back time is (s): {:.5f}".format(lookback_time)) - - # Run the execution and pass input into graph - solve_pde(V_1, V_0, list_theta, t_minh) - - if lookback_time != 0: # Exclude first time of the computation - execution_time += time.time() - start - lookback_time += np.asscalar(t_minh.asnumpy()) - - # Some information printing - #print(t_minh) - print("Computational time to integrate (s): {:.5f}".format(time.time() - start)) - - - #V = V_1.asnumpy() - #V = np.swapaxes(V, 0,2) - #V = np.swapaxes(V, 1,2) - #probe = probe.asnumpy() - #probe = np.swapaxes(probe, 0, 2) - #probe = np.swapaxes(probe, 1, 2) - #print(V) - #V_1 = V_1.asnumpy() - - # Time info printing - print("Total kernel time (s): {:.5f}".format(execution_time)) - print("Finished solving\n") - - # Plotting - print("Plotting beautiful plots. Please wait\n") - fig = go.Figure(data=go.Isosurface( - x=g.mg_X.flatten(), - y=g.mg_Y.flatten(), - z=g.mg_T.flatten(), - value=V_1.asnumpy().flatten(), - colorscale='jet', - isomin=0, - surface_count=1, - isomax=0, - caps=dict(x_show=True, y_show=True) - )) - fig.show() - - print("Please check the plot on your browser.") - -if __name__ == '__main__': - main() diff --git a/odp/drafts/test_4d.py b/odp/drafts/test_4d.py deleted file mode 100644 index 426ad7ab..00000000 --- a/odp/drafts/test_4d.py +++ /dev/null @@ -1,313 +0,0 @@ -import heterocl as hcl -import numpy as np -import time -import plotly.graph_objects as go -from GridProcessing import Grid -from ShapesFunctions import * -from CustomGraphFunctions import * -from InvertPendulum import * -from argparse import ArgumentParser - - -""" USER INTERFACES -- Define grid - -- Generate initial values for grid using shape functions - -- Time length for computations - -- Run -""" - -# What value to use for grid -g = grid(np.array([-3.0, -1.0, -3.0, -1.0]), np.array([3.0, 1.0, 3.0, 1.0]), 4 ,np.array([60,60,60, 60])) # Leave out periodic field -# Use the grid to initialize initial value function -my_shape = Rectangle4D(g, [[-0.05, 0.05], [-0.01, 0.01], [0.99, 1.01], [-0.01, 0.01]]) -# Define my object -myPendulum = inverted_pendulum_2d() - -# Look-back lenght and time step -lookback_length = 1.00 -t_step = 0.05 - - - - -def graph_4D(V_new, V_init, deriv_diff1, deriv_diff2, deriv_diff3, deriv_diff4, x, t): - # Maximum derivative for each dim - max_deriv1 = hcl.scalar(-1e9, "max_deriv1") - max_deriv2 = hcl.scalar(-1e9, "max_deriv2") - max_deriv3 = hcl.scalar(-1e9, "max_deriv3") - max_deriv4 = hcl.scalar(-1e9, "max_deriv4") - - # Min derivative for each dim - min_deriv1 = hcl.scalar(1e9, "min_deriv1") - min_deriv2 = hcl.scalar(1e9, "min_deriv2") - min_deriv3 = hcl.scalar(1e9, "min_deriv3") - min_deriv4 = hcl.scalar(1e9, "min_deriv4") - - # These variables are used to dissipation calculation - max_alpha1 = hcl.scalar(-1e9, "max_alpha1") - max_alpha2 = hcl.scalar(-1e9, "max_alpha2") - max_alpha3 = hcl.scalar(-1e9, "max_alpha3") - max_alpha4 = hcl.scalar(-1e9, "max_alpha4") - - def step_bound(): # Function to calculate time step - stepBoundInv = hcl.scalar(0, "stepBoundInv") - stepBound = hcl.scalar(0, "stepBound") - stepBoundInv[0] = max_alpha1[0]/g.dx[0] + max_alpha2[0]/g.dx[1] + max_alpha3[0]/g.dx[2] + max_alpha4[0]/g.dx[3] - - stepBound[0] = 0.8/stepBoundInv[0] - with hcl.if_(stepBound > t_step): - stepBound[0] = t_step - time = stepBound[0] - return time - - # Calculate Hamiltonian for every grid point in V_init - with hcl.Stage("Hamiltonian"): - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - #Variables to calculate dV_dx - dV_dx1_L = hcl.scalar(0, "dV_dx1_L") - dV_dx1_R = hcl.scalar(0, "dV_dx1_R") - dV_dx1 = hcl.scalar(0, "dV_dx1") - dV_dx2_L = hcl.scalar(0, "dV_dx2_L") - dV_dx2_R = hcl.scalar(0, "dV_dx2_R") - dV_dx2 = hcl.scalar(0, "dV_dx2") - dV_dx3_L = hcl.scalar(0, "dV_dx3_L") - dV_dx3_R = hcl.scalar(0, "dV_dx3_R") - dV_dx3 = hcl.scalar(0, "dV_dx3") - dV_dx4_L = hcl.scalar(0, "dV_dx4_L") - dV_dx4_R = hcl.scalar(0, "dV_dx4_R") - dV_dx4 = hcl.scalar(0, "dV_dx4") - - # No tensor slice operation - #dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - dV_dx1_L[0], dV_dx1_R[0] = spa_derivX1_4d(i, j, k, l, V_init, g) - dV_dx2_L[0], dV_dx2_R[0] = spa_derivX2_4d(i, j, k, l, V_init, g) - dV_dx3_L[0], dV_dx3_R[0] = spa_derivX3_4d(i, j, k, l, V_init, g) - dV_dx4_L[0], dV_dx4_R[0] = spa_derivX4_4d(i, j, k, l, V_init, g) - - # Saves spatial derivative diff into tables - deriv_diff1[i, j, k, l] = dV_dx1_R[0] - dV_dx1_L[0] - deriv_diff2[i, j, k, l] = dV_dx2_R[0] - dV_dx2_L[0] - deriv_diff3[i, j, k, l] = dV_dx3_R[0] - dV_dx3_L[0] - deriv_diff4[i, j, k, l] = dV_dx4_R[0] - dV_dx4_L[0] - - # Calculate average gradient - dV_dx1[0] = (dV_dx1_L + dV_dx1_R) / 2 - dV_dx2[0] = (dV_dx2_L + dV_dx2_R) / 2 - dV_dx3[0] = (dV_dx3_L + dV_dx3_R) / 2 - dV_dx4[0] = (dV_dx4_L + dV_dx4_R) / 2 - - - # Find optimal control - uOpt = myPendulum.opt_ctrl(x, (dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0])) - - # Find rates of changes based on dynamics equation - dx1_dt, dx2_dt, dx3_dt, dx4_dt = myPendulum.dynamics(x, uOpt) - - # Calculate Hamiltonian terms: - V_new[i, j, k, l] = - myPendulum.Hamiltonian((dx1_dt, dx2_dt, dx3_dt, dx4_dt), (dV_dx1, dV_dx2, dV_dx3, dV_dx4)) - - # Get derivMin - with hcl._if(dV_dx1_L[0] < min_deriv1): - min_deriv1[0] = dV_dx1_L[0] - with hcl._if(dV_dx1_R[0] < min_deriv1): - min_deriv1[0] = dV_dx1_R[0] - - with hcl._if(dV_dx2_L[0] < min_deriv2): - min_deriv2[0] = dV_dx2_L[0] - with hcl._if(dV_dx2_R[0] < min_deriv2): - min_deriv2[0] = dV_dx2_R[0] - - with hcl._if(dV_dx3_L[0] < min_deriv3): - min_deriv3[0] = dV_dx3_L[0] - with hcl._if(dV_dx3_R[0] < min_deriv3): - min_deriv3[0] = dV_dx3_R[0] - - with hcl._if(dV_dx4_L[0] < min_deriv4): - min_deriv4[0] = dV_dx4_L[0] - with hcl._if(dV_dx4_R[0] < min_deriv4): - min_deriv4[0] = dV_dx4_R[0] - - # Get derivMax - with hcl._if(dV_dx1_L[0] > max_deriv1): - max_deriv1[0] = dV_dx1_L[0] - with hcl._if(dV_dx1_R[0] > max_deriv1): - max_deriv1[0] = dV_dx1_R[0] - - with hcl._if(dV_dx2_L[0] > max_deriv2): - max_deriv2[0] = dV_dx2_L[0] - with hcl._if(dV_dx2_R[0] > max_deriv2): - max_deriv2[0] = dV_dx2_R[0] - - with hcl._if(dV_dx3_L[0] > max_deriv3): - max_deriv3[0] = dV_dx3_L[0] - with hcl._if(dV_dx3_R[0] > max_deriv3): - max_deriv3[0] = dV_dx3_R[0] - - with hcl._if(dV_dx4_L[0] > max_deriv4): - max_deriv4[0] = dV_dx4_L[0] - with hcl._if(dV_dx4_R[0] > max_deriv4): - max_deriv4[0] = dV_dx4_R[0] - - # Calculate dissipation amount - with hcl.Stage("Dissipation"): - # Find LOWER BOUND optimal control - uOptL = myPendulum.opt_ctrl(x, (min_deriv1[0], min_deriv2[0], min_deriv3[0], min_deriv4[0])) - # Find UPPER BOUND optimal control - uOptU = myPendulum.opt_ctrl(x, (max_deriv1[0], max_deriv2[0], max_deriv3[0], max_deriv4[0])) - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - dx_L1, dx_L2, dx_L3, dx_L4 = myPendulum.dynamics(x, uOptL) - dx_U1, dx_U2, dx_U3, dx_U4 = myPendulum.dynamics(x, uOptU) - - alpha1 = my_max(my_abs(dx_L1), my_abs(dx_U1)) - alpha2 = my_max(my_abs(dx_L1), my_abs(dx_U1)) - alpha3 = my_max(my_abs(dx_L3), my_abs(dx_U3)) - alpha4 = my_max(my_abs(dx_L4), my_abs(dx_U4)) - - diss = hcl.scalar(0, "diss") - diss[0] = 0.5*(deriv_diff1[i, j, k, l]*alpha1 + deriv_diff2[i, j, k, l]*alpha2 + deriv_diff3[i, j, k, l]* alpha3 + deriv_diff4[i, j, k, l]* alpha4) - - # Finally - V_new[i, j, k, l] = -(V_new[i, j, k, l] - diss[0]) - # Get maximum alphas in each dimension - - # Calculate alphas - with hcl.if_(alpha1 > max_alpha1): - max_alpha1[0] = alpha1 - with hcl.if_(alpha2 > max_alpha2): - max_alpha2[0] = alpha2 - with hcl.if_(alpha3 > max_alpha3): - max_alpha3[0] = alpha3 - with hcl.if_(alpha4 > max_alpha4): - max_alpha4[0] = alpha4 - - - # Determine time step - hcl.update(t, lambda x: step_bound()) - # Integrate - result = hcl.update(V_new, lambda i, j, k: V_init[i,j,k] + V_new[i,j,k] * t[0]) - # Copy V_new to V_init - hcl.update(V_init, lambda i,j,k: V_new[i,j,k] ) - return result - -def main(): - ################### PARSING ARGUMENTS FROM USERS ##################### - - parser = ArgumentParser() - parser.add_argument("-p", "--plot", default=False, type=bool) - args = parser.parse_args() - - hcl.init() - hcl.config.init_dtype = hcl.Float() - - ################## DATA SHAPE PREPARATION FOR GRAPH FORMATION #################### - V_f = hcl.placeholder(tuple(g.pts_each_dim), name="V_f", dtype = hcl.Float()) - V_init = hcl.placeholder(tuple(g.pts_each_dim), name="V_init", dtype=hcl.Float()) - x = hcl.placeholder((4, g.pts_each_dim[0]), name="x", dtype=hcl.Float()) - t = hcl.placeholder((1,), name="t", dtype=hcl.Float()) - - # Deriv diff tensor - deriv_diff1 = hcl.Tensor((tuple(g.pts_each_dim)), name="deriv_diff1") - deriv_diff2 = hcl.Tensor((tuple(g.pts_each_dim)), name="deriv_diff2") - deriv_diff3 = hcl.Tensor((tuple(g.pts_each_dim)), name="deriv_diff3") - deriv_diff4 = hcl.Tensor((tuple(g.pts_each_dim)), name="deriv_diff4") - - ################# INITIALIZE DATA TO BE INPUT INTO GRAPH ########################## - - V_0 = hcl.asarray(my_shape) - V_1= hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - t_minh = hcl.asarray(np.zeros(1)) - - x = np.zeros(4, g.pts_each_dim[0]) - for i in range(0,4): - for j in range(0, g.pts_each_dim[i]): - x[i,j] = g.xs[i][j] - - # Convert x to hcl array type - x = hcl.asarray(x) - - ##################### CREATE SCHEDULE############## - - # Create schedule - s = hcl.create_schedule([V_f, V_init, x, t], graph_4D) - - # Inspect the LLVM code - print(hcl.lower(s)) - - ##################### CODE OPTIMIZATION HERE ########################### - - # Accessing the hamiltonian stage - graph_4D.Hamiltonian - - # - - - ################ GET EXECUTABLE AND USE THE EXECUTABLE ############ - # Get executable - solve_pde = hcl.build(s) - - - # Variables used for timing - execution_time = 0 - lookback_time = 0 - while lookback_time <= lookback_length: - # Start timing - start = time.time() - - # Printing some info - #print("Look back time is (s): {:.5f}".format(lookback_time)) - - # Run the execution and pass input into graph - solve_pde(V_1, V_0, list_theta, t_minh) - - if lookback_time != 0: # Exclude first time of the computation - execution_time += time.time() - start - lookback_time += np.asscalar(t_minh.asnumpy()) - - # Some information printing - #print(t_minh) - print("Computational time to integrate (s): {:.5f}".format(time.time() - start)) - - - V_1 = V_1.asnumpy() - V_1 = np.swapaxes(V_1, 0,2) - #V = np.swapaxes(V, 1,2) - #probe = probe.asnumpy() - #probe = np.swapaxes(probe, 0, 2) - #probe = np.swapaxes(probe, 1, 2) - #print(V) - #V_1 = V_1.asnumpy() - - - # Time info printing - print("Total kernel time (s): {:.5f}".format(execution_time)) - print("Finished solving\n") - - ##################### PLOTTING ##################### - if args.plot: - print("Plotting beautiful plots. Please wait\n") - fig = go.Figure(data=go.Isosurface( - x=g.mg_X.flatten(), - y=g.mg_Y.flatten(), - z=g.mg_T.flatten(), - value=V_1.flatten(), - colorscale='jet', - isomin=0, - surface_count=1, - isomax=0, - caps=dict(x_show=True, y_show=True) - )) - fig.show() - print("Please check the plot on your browser.") - - -if __name__ == '__main__': - main() diff --git a/odp/drafts/test_6d.py b/odp/drafts/test_6d.py deleted file mode 100644 index 8b4183a4..00000000 --- a/odp/drafts/test_6d.py +++ /dev/null @@ -1,543 +0,0 @@ -import heterocl as hcl -import numpy as np -import time -import plotly.graph_objects as go -from GridProcessing import Grid -from ShapesFunctions import * -from CustomGraphFunctions import * -from ROV_WaveBwds_6D import * -from argparse import ArgumentParser - -import scipy.io as sio - - -""" USER INTERFACES -- Define grid - -- Generate initial values for grid using shape functions - -- Time length for computations - -- Run -""" - -# Grid field in this order: x_a, z_a, u_r, w_r, x, z - -g = grid(np.array([-5.0, -5.0, -0.5, -0.7, -5.0, 2.0]), np.array([5.0, 5.0, 0.5, 0.7, 5.0, 12.0]), 6, np.array([25,25,25, 25, 25, 25])) # Leave out periodic field -# Use the grid to initialize initial value function -my_shape = Cylinder6D(g, [3, 4, 5, 6]) -# Define my object -myROV_6D = ROV_WaveBwds_6D() - -# Look-back lenght and time step -lookback_length = 20.00 -t_step = 0.2 - -tau = np.arange(start = 0, stop = lookback_length + t_step, step = t_step) -print("I'm here \n") - - - -# Note that t has 2 elements t1, t2 -def graph_6D(V_new, V_init, deriv_diff1, deriv_diff2, deriv_diff3, deriv_diff4, deriv_diff5, deriv_diff6, - x1, x2, x3, x4, x5, x6 ,t): - # Maximum derivative for each dim - max_deriv1 = hcl.scalar(-1e9, "max_deriv1") - max_deriv2 = hcl.scalar(-1e9, "max_deriv2") - max_deriv3 = hcl.scalar(-1e9, "max_deriv3") - max_deriv4 = hcl.scalar(-1e9, "max_deriv4") - max_deriv5 = hcl.scalar(-1e9, "max_deriv5") - max_deriv6 = hcl.scalar(-1e9, "max_deriv6") - - # Min derivative for each dim - min_deriv1 = hcl.scalar(1e9, "min_deriv1") - min_deriv2 = hcl.scalar(1e9, "min_deriv2") - min_deriv3 = hcl.scalar(1e9, "min_deriv3") - min_deriv4 = hcl.scalar(1e9, "min_deriv4") - min_deriv5 = hcl.scalar(1e9, "min_deriv5") - min_deriv6 = hcl.scalar(1e9, "min_deriv6") - - # These variables are used to dissipation calculation - max_alpha1 = hcl.scalar(-1e9, "max_alpha1") - max_alpha2 = hcl.scalar(-1e9, "max_alpha2") - max_alpha3 = hcl.scalar(-1e9, "max_alpha3") - max_alpha4 = hcl.scalar(-1e9, "max_alpha4") - max_alpha5 = hcl.scalar(-1e9, "max_alpha5") - max_alpha6 = hcl.scalar(-1e9, "max_alpha6") - - def step_bound(): # Function to calculate time step - stepBoundInv = hcl.scalar(0, "stepBoundInv") - stepBound = hcl.scalar(0, "stepBound") - stepBoundInv[0] = max_alpha1[0]/g.dx[0] + max_alpha2[0]/g.dx[1] + max_alpha3[0]/g.dx[2] + max_alpha4[0]/g.dx[3] \ - + max_alpha5[0]/g.dx[4] + max_alpha6[0]/g.dx[5] - - stepBound[0] = 0.8/stepBoundInv[0] - with hcl.if_(stepBound > t[1] - t[0]): - stepBound[0] = t[1] - t[0] - - # Update the lower time ranges - t[0] = t[0] + stepBound[0] - return stepBound[0] - - # Calculate Hamiltonian for every grid point in V_init - with hcl.Stage("Hamiltonian"): - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - with hcl.for_(0, V_init.shape[4], name="m") as m: - with hcl.for_(0, V_init.shape[5], name="n") as n: - #Variables to calculate dV_dx - dV_dx1_L = hcl.scalar(0, "dV_dx1_L") - dV_dx1_R = hcl.scalar(0, "dV_dx1_R") - dV_dx1 = hcl.scalar(0, "dV_dx1") - dV_dx2_L = hcl.scalar(0, "dV_dx2_L") - dV_dx2_R = hcl.scalar(0, "dV_dx2_R") - dV_dx2 = hcl.scalar(0, "dV_dx2") - dV_dx3_L = hcl.scalar(0, "dV_dx3_L") - dV_dx3_R = hcl.scalar(0, "dV_dx3_R") - dV_dx3 = hcl.scalar(0, "dV_dx3") - dV_dx4_L = hcl.scalar(0, "dV_dx4_L") - dV_dx4_R = hcl.scalar(0, "dV_dx4_R") - dV_dx4 = hcl.scalar(0, "dV_dx4") - dV_dx5_L = hcl.scalar(0, "dV_dx5_L") - dV_dx5_R = hcl.scalar(0, "dV_dx5_R") - dV_dx5 = hcl.scalar(0, "dV_dx5") - dV_dx6_L = hcl.scalar(0, "dV_dx6_L") - dV_dx6_R = hcl.scalar(0, "dV_dx6_R") - dV_dx6 = hcl.scalar(0, "dV_dx6") - - # No tensor slice operation - #dV_dx_L[0], dV_dx_R[0] = spa_derivX(i, j, k) - dV_dx1_L[0], dV_dx1_R[0] = spa_derivX6_6d(i, j, k, l, m, n, V_init, g) - dV_dx2_L[0], dV_dx2_R[0] = spa_derivX5_6d(i, j, k, l, m, n, V_init, g) - dV_dx3_L[0], dV_dx3_R[0] = spa_derivX4_6d(i, j, k, l, m, n, V_init, g) - dV_dx4_L[0], dV_dx4_R[0] = spa_derivX3_6d(i, j, k, l, m, n, V_init, g) - dV_dx5_L[0], dV_dx5_R[0] = spa_derivX2_6d(i, j, k, l, m, n, V_init, g) - dV_dx6_L[0], dV_dx6_R[0] = spa_derivX1_6d(i, j, k, l, m, n, V_init, g) - - # Saves spatial derivative diff into tables - deriv_diff1[i, j, k, l, m, n] = dV_dx1_R[0] - dV_dx1_L[0] - deriv_diff2[i, j, k, l, m, n] = dV_dx2_R[0] - dV_dx2_L[0] - deriv_diff3[i, j, k, l, m, n] = dV_dx3_R[0] - dV_dx3_L[0] - deriv_diff4[i, j, k, l, m, n] = dV_dx4_R[0] - dV_dx4_L[0] - deriv_diff5[i, j, k, l, m, n] = dV_dx5_R[0] - dV_dx5_L[0] - deriv_diff6[i, j, k, l, m, n] = dV_dx6_R[0] - dV_dx6_L[0] - - #Calculate average gradient - dV_dx1[0] = (dV_dx1_L + dV_dx1_R) / 2 - dV_dx2[0] = (dV_dx2_L + dV_dx2_R) / 2 - dV_dx3[0] = (dV_dx3_L + dV_dx3_R) / 2 - dV_dx4[0] = (dV_dx4_L + dV_dx4_R) / 2 - dV_dx5[0] = (dV_dx5_L + dV_dx5_R) / 2 - dV_dx6[0] = (dV_dx6_L + dV_dx6_R) / 2 - - - # Find optimal control - uOpt = myROV_6D.opt_ctrl(t,(dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0], dV_dx6[0])) - # Find optimal disturbance - dOpt = myROV_6D.opt_dstb((dV_dx1[0], dV_dx2[0], dV_dx3[0], dV_dx4[0], dV_dx5[0], dV_dx6[0])) - - # Find rates of changes based on dynamics equation - dx1_dt, dx2_dt, dx3_dt, dx4_dt, dx5_dt, dx6_dt = myROV_6D.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]), uOpt, dOpt) - - # # Calculate Hamiltonian terms: - V_new[i, j, k, l, m, n] = - myROV_6D.Hamiltonian((dx1_dt, dx2_dt, dx3_dt, dx4_dt, dx5_dt, dx6_dt), (dV_dx1, dV_dx2, dV_dx3, dV_dx4, dV_dx5, dV_dx6)) - - # Get derivMin - with hcl.if_(dV_dx1_L[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] < min_deriv1[0]): - min_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] < min_deriv2[0]): - min_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] < min_deriv3[0]): - min_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] < min_deriv4[0]): - min_deriv4[0] = dV_dx4_R[0] - - with hcl.if_(dV_dx5_L[0] < min_deriv5[0]): - min_deriv5[0] = dV_dx5_L[0] - with hcl.if_(dV_dx5_R[0] < min_deriv5[0]): - min_deriv5[0] = dV_dx5_R[0] - - with hcl.if_(dV_dx6_L[0] < min_deriv6[0]): - min_deriv6[0] = dV_dx6_L[0] - with hcl.if_(dV_dx6_R[0] < min_deriv6[0]): - min_deriv6[0] = dV_dx6_R[0] - - # Get derivMax - with hcl.if_(dV_dx1_L[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_L[0] - with hcl.if_(dV_dx1_R[0] > max_deriv1[0]): - max_deriv1[0] = dV_dx1_R[0] - - with hcl.if_(dV_dx2_L[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_L[0] - with hcl.if_(dV_dx2_R[0] > max_deriv2[0]): - max_deriv2[0] = dV_dx2_R[0] - - with hcl.if_(dV_dx3_L[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_L[0] - with hcl.if_(dV_dx3_R[0] > max_deriv3[0]): - max_deriv3[0] = dV_dx3_R[0] - - with hcl.if_(dV_dx4_L[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_L[0] - with hcl.if_(dV_dx4_R[0] > max_deriv4[0]): - max_deriv4[0] = dV_dx4_R[0] - - with hcl.if_(dV_dx5_L[0] > max_deriv5[0]): - max_deriv5[0] = dV_dx5_L[0] - with hcl.if_(dV_dx5_R[0] > max_deriv5[0]): - max_deriv5[0] = dV_dx5_R[0] - - with hcl.if_(dV_dx6_L[0] > max_deriv6[0]): - max_deriv6[0] = dV_dx6_L[0] - with hcl.if_(dV_dx6_R[0] > max_deriv6[0]): - max_deriv6[0] = dV_dx6_R[0] - - # Calculate dissipation amount - with hcl.Stage("Dissipation"): - uOptL1 = hcl.scalar(0, "uOptL1") - uOptL2 = hcl.scalar(0, "uOptL2") - uOptL3 = hcl.scalar(0, "uOptL3") - uOptL4 = hcl.scalar(0, "uOptL4") - - - uOptU1 = hcl.scalar(0, "uOptU1") - uOptU2 = hcl.scalar(0, "uOptU2") - uOptU3 = hcl.scalar(0, "uOptU3") - uOptU4 = hcl.scalar(0, "uOptU4") - - dOptL1 = hcl.scalar(0, "dOptL1") - dOptL2 = hcl.scalar(0, "dOptL2") - dOptL3 = hcl.scalar(0, "dOptL3") - dOptL4 = hcl.scalar(0, "dOptL4") - - dOptU1 = hcl.scalar(0, "dOptU1") - dOptU2 = hcl.scalar(0, "dOptU2") - dOptU3 = hcl.scalar(0, "dOptU3") - dOptU4 = hcl.scalar(0, "dOptU4") - - # Storing alphas - alpha1 = hcl.scalar(0, "alpha1") - alpha2 = hcl.scalar(0, "alpha2") - alpha3 = hcl.scalar(0, "alpha3") - alpha4 = hcl.scalar(0, "alpha4") - alpha5 = hcl.scalar(0, "alpha5") - alpha6 = hcl.scalar(0, "alpha6") - - - # Find LOWER BOUND optimal control - uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0] = myROV_6D.opt_ctrl(t, (min_deriv1[0], min_deriv2[0], min_deriv3[0], min_deriv4[0], min_deriv5[0], min_deriv6[0])) - # Find UPPER BOUND optimal control - uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0] = myROV_6D.opt_ctrl(t, (max_deriv1[0], max_deriv2[0], max_deriv3[0], max_deriv4[0], max_deriv5[0], max_deriv6[0])) - # Find LOWER BOUND optimal disturbance - dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0] = myROV_6D.opt_dstb((min_deriv1[0], min_deriv2[0], min_deriv3[0], min_deriv4[0], min_deriv5[0], min_deriv6[0])) - # Find UPPER BOUND optimal disturbance - dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0] = myROV_6D.opt_dstb((max_deriv1[0], max_deriv2[0], max_deriv3[0], max_deriv4[0], min_deriv5[0], min_deriv6[0])) - - with hcl.for_(0, V_init.shape[0], name="i") as i: - with hcl.for_(0, V_init.shape[1], name="j") as j: - with hcl.for_(0, V_init.shape[2], name="k") as k: - with hcl.for_(0, V_init.shape[3], name="l") as l: - with hcl.for_(0, V_init.shape[4], name="m") as m: - with hcl.for_(0, V_init.shape[5], name="n") as n: - dx_LL1 = hcl.scalar(0, "dx_LL1") - dx_LL2 = hcl.scalar(0, "dx_LL2") - dx_LL3 = hcl.scalar(0, "dx_LL3") - dx_LL4 = hcl.scalar(0, "dx_LL4") - dx_LL5 = hcl.scalar(0, "dx_LL5") - dx_LL6 = hcl.scalar(0, "dx_LL6") - - dx_UL1 = hcl.scalar(0, "dx_UL1") - dx_UL2 = hcl.scalar(0, "dx_UL2") - dx_UL3 = hcl.scalar(0, "dx_UL3") - dx_UL4 = hcl.scalar(0, "dx_UL4") - dx_UL5 = hcl.scalar(0, "dx_UL5") - dx_UL6 = hcl.scalar(0, "dx_UL6") - # - dx_LU1 = hcl.scalar(0, "dx_LU1") - dx_LU2 = hcl.scalar(0, "dx_LU2") - dx_LU3 = hcl.scalar(0, "dx_LU3") - dx_LU4 = hcl.scalar(0, "dx_LU4") - dx_LU5 = hcl.scalar(0, "dx_LU5") - dx_LU6 = hcl.scalar(0, "dx_LU6") - - dx_UU1 = hcl.scalar(0, "dx_UU1") - dx_UU2 = hcl.scalar(0, "dx_UU2") - dx_UU3 = hcl.scalar(0, "dx_UU3") - dx_UU4 = hcl.scalar(0, "dx_UU4") - dx_UU5 = hcl.scalar(0, "dx_UU5") - dx_UU6 = hcl.scalar(0, "dx_UU6") - - # Get upper bound and lower bound rates of changes - dx_LL1[0], dx_LL2[0], dx_LL3[0], dx_LL4[0], dx_LL5[0], dx_LL6[0] = myROV_6D.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n]) \ - , (uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0]), (dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0])) - # Get absolute value of each - dx_LL1[0] = my_abs(dx_LL1[0]) - dx_LL2[0] = my_abs(dx_LL2[0]) - dx_LL3[0] = my_abs(dx_LL3[0]) - dx_LL4[0] = my_abs(dx_LL4[0]) - dx_LL5[0] = my_abs(dx_LL5[0]) - dx_LL6[0] = my_abs(dx_LL6[0]) - - dx_UL1[0], dx_UL2[0], dx_UL3[0], dx_UL4[0], dx_UL5[0], dx_UL6[0] = myROV_6D.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n])\ - , (uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0]), (dOptL1[0], dOptL2[0], dOptL3[0], dOptL4[0])) - # Get absolute value of each - dx_UL1[0] = my_abs(dx_UL1[0]) - dx_UL2[0] = my_abs(dx_UL2[0]) - dx_UL3[0] = my_abs(dx_UL3[0]) - dx_UL4[0] = my_abs(dx_UL4[0]) - dx_UL5[0] = my_abs(dx_UL5[0]) - dx_UL6[0] = my_abs(dx_UL6[0]) - - # Set maximum alphas - alpha1[0] = my_max(dx_UL1[0], dx_LL1[0]) - alpha2[0] = my_max(dx_UL2[0], dx_LL2[0]) - alpha3[0] = my_max(dx_UL3[0], dx_LL3[0]) - alpha4[0] = my_max(dx_UL4[0], dx_LL4[0]) - alpha5[0] = my_max(dx_UL5[0], dx_LL5[0]) - alpha6[0] = my_max(dx_UL6[0], dx_LL6[0]) - - dx_LU1[0], dx_LU2[0], dx_LU3[0], dx_LU4[0], dx_LU5[0], dx_LU6[0] = myROV_6D.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n])\ - , (uOptL1[0], uOptL2[0], uOptL3[0], uOptL4[0]), (dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0])) - # Get absolute value of each - dx_LU1[0] = my_abs(dx_LU1[0]) - dx_LU2[0] = my_abs(dx_LU2[0]) - dx_LU3[0] = my_abs(dx_LU3[0]) - dx_LU4[0] = my_abs(dx_LU4[0]) - dx_LU5[0] = my_abs(dx_LU5[0]) - dx_LU6[0] = my_abs(dx_LU6[0]) - - alpha1[0] = my_max(alpha1[0], dx_LU1[0]) - alpha2[0] = my_max(alpha2[0], dx_LU2[0]) - alpha3[0] = my_max(alpha3[0], dx_LU3[0]) - alpha4[0] = my_max(alpha4[0], dx_LU4[0]) - alpha5[0] = my_max(alpha5[0], dx_LU5[0]) - alpha6[0] = my_max(alpha6[0], dx_LU6[0]) - - dx_UU1[0], dx_UU2[0], dx_UU3[0], dx_UU4[0], dx_UU5[0], dx_UU6[0] = myROV_6D.dynamics(t, (x1[i], x2[j], x3[k], x4[l], x5[m], x6[n])\ - , (uOptU1[0], uOptU2[0], uOptU3[0], uOptU4[0]), (dOptU1[0], dOptU2[0], dOptU3[0], dOptU4[0])) - dx_UU1[0] = my_abs(dx_UU1[0]) - dx_UU2[0] = my_abs(dx_UU2[0]) - dx_UU3[0] = my_abs(dx_UU3[0]) - dx_UU4[0] = my_abs(dx_UU4[0]) - dx_UU5[0] = my_abs(dx_UU5[0]) - dx_UU6[0] = my_abs(dx_UU6[0]) - - alpha1[0] = my_max(alpha1[0], dx_UU1[0]) - alpha2[0] = my_max(alpha2[0], dx_UU2[0]) - alpha3[0] = my_max(alpha3[0], dx_UU3[0]) - alpha4[0] = my_max(alpha4[0], dx_UU4[0]) - alpha5[0] = my_max(alpha5[0], dx_UU5[0]) - alpha6[0] = my_max(alpha6[0], dx_UU6[0]) - - diss = hcl.scalar(0, "diss") - diss[0] = 0.5*(deriv_diff1[i, j, k, l, m, n]*alpha1[0] + deriv_diff2[i, j, k, l, m, n]*alpha2[0] \ - + deriv_diff3[i, j, k, l, m, n]* alpha3[0] + deriv_diff4[i, j, k, l, m, n]* alpha4[0] \ - + deriv_diff5[i, j, k, l, m, n]* alpha5[0] + deriv_diff6[i, j, k, l, m, n]* alpha6[0]) - - # Finally - V_new[i, j, k, l, m, n] = -(V_new[i, j, k, l, m, n] - diss[0]) - # Get maximum alphas in each dimension - - # Calculate alphas - with hcl.if_(alpha1 > max_alpha1): - max_alpha1[0] = alpha1[0] - with hcl.if_(alpha2 > max_alpha2): - max_alpha2[0] = alpha2[0] - with hcl.if_(alpha3 > max_alpha3): - max_alpha3[0] = alpha3[0] - with hcl.if_(alpha4 > max_alpha4): - max_alpha4[0] = alpha4[0] - with hcl.if_(alpha5 > max_alpha5): - max_alpha5[0] = alpha5[0] - with hcl.if_(alpha6 > max_alpha6): - max_alpha6[0] = alpha6[0] - - - # Determine time step - delta_t = hcl.compute((1,), lambda x: step_bound(), name="delta_t") - #hcl.update(t, lambda x: t[x] + delta_t[x]) - # Integrate - result = hcl.update(V_new, lambda i, j, k, l, m, n: V_init[i, j, k, l, m, n] + V_new[i, j, k, l, m, n] * delta_t[0]) - # Copy V_new to V_init - hcl.update(V_init, lambda i, j, k, l, m, n: V_new[i, j, k, l, m, n]) - return result - -def main(): - ################### PARSING ARGUMENTS FROM USERS ##################### - - parser = ArgumentParser() - parser.add_argument("-p", "--plot", default=False, type=bool) - # Print out LLVM option only - parser.add_argument("-l", "--llvm", default=False, type=bool) - args = parser.parse_args() - - hcl.init() - hcl.config.init_dtype = hcl.Float() - - ################## DATA SHAPE PREPARATION FOR GRAPH FORMATION #################### - V_f = hcl.placeholder(tuple(g.pts_each_dim), name="V_f", dtype = hcl.Float()) - V_init = hcl.placeholder(tuple(g.pts_each_dim), name="V_init", dtype=hcl.Float()) - #x = hcl.placeholder((6, g.pts_each_dim[0]), name="x", dtype=hcl.Float()) - t = hcl.placeholder((2,), name="t", dtype=hcl.Float()) - - # Deriv diff tensor - deriv_diff1 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff1") - deriv_diff2 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff2") - deriv_diff3 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff3") - deriv_diff4 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff4") - deriv_diff5 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff5") - deriv_diff6 = hcl.placeholder((tuple(g.pts_each_dim)), name="deriv_diff6") - - # Positions vector - x1 = hcl.placeholder((g.pts_each_dim[0],), name="x1", dtype=hcl.Float()) - x2 = hcl.placeholder((g.pts_each_dim[1],), name="x2", dtype=hcl.Float()) - x3 = hcl.placeholder((g.pts_each_dim[2],), name="x3", dtype=hcl.Float()) - x4 = hcl.placeholder((g.pts_each_dim[3],), name="x4", dtype=hcl.Float()) - x5 = hcl.placeholder((g.pts_each_dim[4],), name="x5", dtype=hcl.Float()) - x6 = hcl.placeholder((g.pts_each_dim[5],), name="x6", dtype=hcl.Float()) - - - ##################### CREATE SCHEDULE############## - - # Create schedule - s = hcl.create_schedule( - [V_f, V_init, deriv_diff1, deriv_diff2, deriv_diff3, deriv_diff4, deriv_diff5, deriv_diff6, x1, x2, x3, x4, x5, x6, t], graph_6D) - - # Inspect the LLVM code - print(hcl.lower(s)) - - - - ################# INITIALIZE DATA TO BE INPUT INTO GRAPH ########################## - - print("Initializing\n") - - V_0 = hcl.asarray(my_shape) - V_1= hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - - list_x1 = np.reshape(g.vs[0], g.pts_each_dim[0]) - list_x2 = np.reshape(g.vs[1], g.pts_each_dim[1]) - list_x3 = np.reshape(g.vs[2], g.pts_each_dim[2]) - list_x4 = np.reshape(g.vs[3], g.pts_each_dim[3]) - list_x5 = np.reshape(g.vs[4], g.pts_each_dim[4]) - list_x6 = np.reshape(g.vs[5], g.pts_each_dim[5]) - - # Convert to hcl array type - list_x1 = hcl.asarray(list_x1) - list_x2 = hcl.asarray(list_x2) - list_x3 = hcl.asarray(list_x3) - list_x4 = hcl.asarray(list_x4) - list_x5 = hcl.asarray(list_x5) - list_x6 = hcl.asarray(list_x6) - - # Initialize deriv diff tensor - deriv_diff1 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff2 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff3 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff4 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff5 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - deriv_diff6 = hcl.asarray(np.zeros(tuple(g.pts_each_dim))) - - - ##################### CODE OPTIMIZATION HERE ########################### - print("Optimizing\n") - - # Accessing the hamiltonian stage - s_H = graph_6D.Hamiltonian - s_D = graph_6D.Dissipation - - # - s[s_H].parallel(s_H.i) - s[s_D].parallel(s_D.i) - - # Inspect IR - #if args.llvm: - # print(hcl.lower(s)) - - ################ GET EXECUTABLE AND USE THE EXECUTABLE ############ - print("Running\n") - - # Get executable - solve_pde = hcl.build(s) - - # Variables used for timing - execution_time = 0 - lookback_time = 0 - - tNow = tau[0] - for i in range (1, len(tau)): - #tNow = tau[i-1] - t_minh= hcl.asarray(np.array((tNow, tau[i]))) - while tNow <= tau[i] - 1e-4: - # Start timing - start = time.time() - - # Run the execution and pass input into graph - solve_pde(V_1, V_0, deriv_diff1, deriv_diff2, deriv_diff3, deriv_diff4, deriv_diff5, deriv_diff6, - list_x1, list_x2, list_x3, list_x4, list_x5, list_x6, t_minh) - - tNow = np.asscalar((t_minh.asnumpy())[0]) - - if lookback_time != 0: # Exclude first time of the computation - execution_time += time.time() - start - - # Some information printing - print(t_minh) - print("Computational time to integrate (s): {:.5f}".format(time.time() - start)) - - # Saving data into disk - if tNow >= tau[i] - 1e-4: - print("Saving files\n") - sio.savemat('/local-scratch/ROV_6d_TEB/V_value_{:d}.mat'.format(i), {'V_array': V_1.asnumpy()}) - - - #print(V_1.asnumpy()) - # - # V_1 = V_1.asnumpy() - # # V_1 = np.swapaxes(V_1, 0,2) - # #V = np.swapaxes(V, 1,2) - # #probe = probe.asnumpy() - # #probe = np.swapaxes(probe, 0, 2) - # #probe = np.swapaxes(probe, 1, 2) - # #print(V) - # #V_1 = V_1.asnumpy() - # - # - # Time info printing - print("Total kernel time (s): {:.5f}".format(execution_time)) - print("Finished solving\n") - - ##################### PLOTTING ##################### - if args.plot: - print("Plotting beautiful plots. Please wait\n") - fig = go.Figure(data=go.Isosurface( - x=g.mg_X.flatten(), - y=g.mg_Y.flatten(), - z=g.mg_T.flatten(), - value=V_1.flatten(), - colorscale='jet', - isomin=0, - surface_count=1, - isomax=0, - caps=dict(x_show=True, y_show=True) - )) - fig.show() - print("Please check the plot on your browser.") - - -if __name__ == '__main__': - main() diff --git a/odp/dynamics/DubinsCapture.py b/odp/dynamics/DubinsCapture.py deleted file mode 100644 index 3814f3a7..00000000 --- a/odp/dynamics/DubinsCapture.py +++ /dev/null @@ -1,91 +0,0 @@ -import heterocl as hcl - -class DubinsCapture: - def __init__(self, x=[0,0,0], wMax=1.0, speed=1.0, dMax=1.0, uMode="max", dMode="min"): - self.x = x - self.wMax = wMax - self.speed = speed - self.dMax = dMax - self.uMode = uMode - self.dMode = dMode - - def opt_ctrl(self, t, state, spat_deriv): - """ - :param spat_deriv: tuple of spatial derivative in all dimensions - state: x1, x2, x3 - t: time - :return: a tuple of optimal disturbances - """ - - opt_w = hcl.scalar(self.wMax, "opt_w") - # Just create and pass back, even though they're not used - in3 = hcl.scalar(0, "in3") - in4 = hcl.scalar(0, "in4") - - #a_term = spat_deriv[0] * self.x[1] - spat_deriv[1]*self.x[0] - spat_deriv[2] - - # Declare a variable - a_term = hcl.scalar(0, "a_term") - # use the scalar by indexing 0 everytime - a_term[0] = spat_deriv[0] * state[1] - spat_deriv[1] * state[0] - spat_deriv[2] - - with hcl.if_(a_term >= 0): - with hcl.if_(self.uMode == "min"): - opt_w[0] = -opt_w[0] - with hcl.elif_(a_term < 0): - with hcl.if_(self.uMode == "max"): - opt_w[0] = -opt_w[0] - return (opt_w[0], in3[0], in4[0]) - - def opt_dstb(self, t, state, spat_deriv): - """ - :param spat_deriv: tuple of spatial derivative in all dimensions - state: x1, x2, x3 - t: time - :return: a tuple of optimal disturbances - """ - - # Graph takes in 4 possible inputs, by default, for now - d1 = hcl.scalar(self.dMax, "d1") - d2 = hcl.scalar(0, "d2") - # Just create and pass back, even though they're not used - d3 = hcl.scalar(0, "d3") - - # Declare a variable - b_term = hcl.scalar(0, "b_term") - # use the scalar by indexing 0 everytime - b_term[0] = spat_deriv[2] - - with hcl.if_(b_term[0] >= 0): - with hcl.if_(self.dMode == "min"): - d1[0] = -d1[0] - with hcl.elif_(b_term[0] < 0): - with hcl.if_(self.dMode == "max"): - d1[0] = -d1[0] - return (d1[0], d2[0], d3[0]) - - def dynamics(self, t, state, uOpt, dOpt): - x_dot = hcl.scalar(0, "x_dot") - y_dot = hcl.scalar(0, "y_dot") - theta_dot = hcl.scalar(0, "theta_dot") - - x_dot[0] = -self.speed + self.speed*hcl.cos(state[2]) + uOpt[0]*state[1] - y_dot[0] = self.speed*hcl.sin(state[2]) - uOpt[0]*state[0] - theta_dot[0] = dOpt[0] - uOpt[0] - - return (x_dot[0], y_dot[0], theta_dot[0]) - - # The below function can have whatever form or parameters users want - # These functions are not used in HeteroCL program, hence is pure Python code and - # can be used after the value function has been obtained. - def optCtrl_inPython(self, state, spat_deriv): - a_term = spat_deriv[0] * state[1] - spat_deriv[1] * state[0] - spat_deriv[2] - - opt_w = self.wMax - if a_term >= 0: - if self.uMode == "min": - opt_w = -self.wMax - else: - if self.uMode == "max": - opt_w = -self.wMax - return opt_w \ No newline at end of file diff --git a/odp/dynamics/DubinsCar.py b/odp/dynamics/DubinsCar.py deleted file mode 100644 index 703e2db9..00000000 --- a/odp/dynamics/DubinsCar.py +++ /dev/null @@ -1,47 +0,0 @@ -import heterocl as hcl -import numpy as np - -class DubinsCar: - def __init__(self, x=[0,0,0], wMax=1, speed=1, dMax=[0,0,0], uMode="min", dMode="max"): - self.x = x - self.wMax = wMax - self.speed = speed - self.dMax = dMax - self.uMode = uMode - self.dMode = dMode - - def opt_ctrl(self, t, state, spat_deriv): - opt_w = hcl.scalar(self.wMax, "opt_w") - # Just create and pass back, even though they're not used - in3 = hcl.scalar(0, "in3") - in4 = hcl.scalar(0, "in4") - with hcl.if_(spat_deriv[2] > 0): - with hcl.if_(self.uMode == "min"): - opt_w[0] = -opt_w - with hcl.elif_(spat_deriv[2] < 0): - with hcl.if_(self.uMode == "max"): - opt_w[0] = -opt_w - return (opt_w[0], in3[0], in4[0]) - - def opt_dstb(self, t, state, spat_deriv): - """ - :param spat_deriv: tuple of spatial derivative in all dimensions - :return: a tuple of optimal disturbances - """ - # Graph takes in 4 possible inputs, by default, for now - d1 = hcl.scalar(0, "d1") - d2 = hcl.scalar(0, "d2") - # Just create and pass back, even though they're not used - d3 = hcl.scalar(0, "d3") - return (d1[0], d2[0], d3[0]) - - def dynamics(self, t, state, uOpt, dOpt): - x_dot = hcl.scalar(0, "x_dot") - y_dot = hcl.scalar(0, "y_dot") - theta_dot = hcl.scalar(0, "theta_dot") - - x_dot[0] = self.speed*hcl.cos(state[2]) - y_dot[0] = self.speed*hcl.sin(state[2]) - theta_dot[0] = uOpt[0] - - return (x_dot[0], y_dot[0], theta_dot[0]) diff --git a/odp/dynamics/DubinsCar4D.py b/odp/dynamics/DubinsCar4D.py deleted file mode 100644 index fc603f45..00000000 --- a/odp/dynamics/DubinsCar4D.py +++ /dev/null @@ -1,121 +0,0 @@ -import heterocl as hcl - -""" 4D DUBINS CAR DYNAMICS IMPLEMENTATION - x_dot = v * cos(theta) + d_1 - y_dot = v * sin(theta) + d_2 - v_dot = a - theta_dot = w - """ -class DubinsCar4D: - def __init__(self, x=[0,0,0,0], uMin = [-1,-1], uMax = [1,1], dMin = [-0.25,-0.25], - dMax=[0.25,0.25], uMode="min", dMode="max"): - """Creates a Dublin Car with the following states: - X position, Y position, speed, heading - The controls are the acceleration and turn rate (angular speed) - The disturbances are the noise in the velocity components. - Args: - x (list, optional): Initial state . Defaults to [0,0,0,0]. - uMin (list, optional): Lowerbound of user control. Defaults to [-1,-1]. - uMax (list, optional): Upperbound of user control. - Defaults to [1,1]. - dMin (list, optional): Lowerbound of disturbance to user control, . Defaults to [-0.25,-0.25]. - dMax (list, optional): Upperbound of disturbance to user control. Defaults to [0.25,0.25]. - uMode (str, optional): Accepts either "min" or "max". - * "min" : have optimal control reach goal - * "max" : have optimal control avoid goal - Defaults to "min". - dMode (str, optional): Accepts whether "min" or "max" and should be opposite of uMode. - Defaults to "max". - """ - self.x = x - self.uMax = uMax - self.uMin = uMin - self.dMax = dMax - self.dMin = dMin - assert(uMode in ["min", "max"]) - self.uMode = uMode - if uMode == "min": - assert(dMode == "max") - else: - assert(dMode == "min") - self.dMode = dMode - - def opt_ctrl(self, t, state, spat_deriv): - """ - :param t: time t - :param state: tuple of coordinates - :param spat_deriv: tuple of spatial derivative in all dimensions - :return: - """ - # System dynamics - # x_dot = v * cos(theta) + d_1 - # y_dot = v * sin(theta) + d_2 - # v_dot = a - # theta_dot = w - - # Graph takes in 4 possible inputs, by default, for now - opt_a = hcl.scalar(self.uMax[0], "opt_a") - opt_w = hcl.scalar(self.uMax[1], "opt_w") - # Just create and pass back, even though they're not used - in3 = hcl.scalar(0, "in3") - in4 = hcl.scalar(0, "in4") - - if self.uMode == "min": - with hcl.if_(spat_deriv[2] > 0): - opt_a[0] = self.uMin[0] - with hcl.if_(spat_deriv[3] > 0): - opt_w[0] = self.uMin[1] - else: - with hcl.if_(spat_deriv[2] < 0): - opt_a[0] = self.uMin[0] - with hcl.if_(spat_deriv[3] < 0): - opt_w[0] = self.uMin[1] - # return 3, 4 even if you don't use them - return (opt_a[0] ,opt_w[0], in3[0], in4[0]) - - def opt_dstb(self, t, state, spat_deriv): - """ - :param spat_deriv: tuple of spatial derivative in all dimensions - :return: a tuple of optimal disturbances - """ - # Graph takes in 4 possible inputs, by default, for now - d1 = hcl.scalar(0, "d1") - d2 = hcl.scalar(0, "d2") - # Just create and pass back, even though they're not used - d3 = hcl.scalar(0, "d3") - d4 = hcl.scalar(0, "d4") - - #with hcl.if_(self.dMode == "max"): - if self.dMode == "max": - with hcl.if_(spat_deriv[0] > 0): - d1[0] = self.dMax[0] - with hcl.elif_(spat_deriv[0] < 0): - d1[0] = self.dMin[0] - with hcl.if_(spat_deriv[1] > 0): - d2[0] = self.dMax[1] - with hcl.elif_(spat_deriv[1] < 0): - d2[0] = self.dMin[1] - else: - with hcl.if_(spat_deriv[0] > 0): - d1[0] = self.dMin[0] - with hcl.elif_(spat_deriv[0] < 0): - d1[0] = self.dMax[0] - with hcl.if_(spat_deriv[1] > 0): - d2[0] = self.dMin[1] - with hcl.elif_(spat_deriv[1] < 0): - d2[0] = self.dMax[1] - - return (d1[0], d2[0], d3[0], d4[0]) - - def dynamics(self, t, state, uOpt, dOpt): - x_dot = hcl.scalar(0, "x_dot") - y_dot = hcl.scalar(0, "y_dot") - v_dot = hcl.scalar(0, "v_dot") - theta_dot = hcl.scalar(0, "theta_dot") - - x_dot[0] = state[2] * hcl.cos(state[3]) + dOpt[0] - y_dot[0] = state[2] * hcl.sin(state[3]) + dOpt[1] - v_dot[0] = uOpt[0] - theta_dot[0] = uOpt[1] - - return (x_dot[0], y_dot[0], v_dot[0] ,theta_dot[0]) diff --git a/odp/dynamics/DubinsCar4D2.py b/odp/dynamics/DubinsCar4D2.py deleted file mode 100644 index a448415c..00000000 --- a/odp/dynamics/DubinsCar4D2.py +++ /dev/null @@ -1,184 +0,0 @@ -import heterocl as hcl -import math - -""" -4D DUBINS CAR DYNAMICS IMPLEMENTATION -used to model dynamics of Jetracer - -x_dot = v * cos(theta) -y_dot = v * sin(theta) -v_dot = a -theta_dot = v * tan(delta) / L - -delta := steering angle -L := wheelbase of car - -(6.2) https://arxiv.org/pdf/1711.03449.pdf -""" - -class DubinsCar4D2: - def __init__( - self, - x=[0, 0, 0, 0], - uMin=[-1.5, -math.pi / 18], - uMax=[1.5, math.pi / 18], - dMin=[0.0, 0.0], - dMax=[0.0, 0.0], - uMode="max", - dMode="min", - ): - - """Creates a Dublin Car with the following states: - X position, Y position, acceleration, heading - - The first element of user control and disturbance is acceleration - The second element of user control and disturbance is heading - - - Args: - x (list, optional): Initial state . Defaults to [0,0,0,0]. - uMin (list, optional): Lowerbound of user control. Defaults to [-1,-1]. - uMax (list, optional): Upperbound of user control. - Defaults to [1,1]. - dMin (list, optional): Lowerbound of disturbance to user control, . Defaults to [-0.25,-0.25]. - dMax (list, optional): Upperbound of disturbance to user control. Defaults to [0.25,0.25]. - uMode (str, optional): Accepts either "min" or "max". - * "min" : have optimal control reach goal - * "max" : have optimal control avoid goal - Defaults to "min". - dMode (str, optional): Accepts whether "min" or "max" and should be opposite of uMode. - Defaults to "max". - """ - self.x = x - self.uMax = uMax - self.uMin = uMin - self.dMax = dMax - self.dMin = dMin - assert uMode in ["min", "max"] - self.uMode = uMode - if uMode == "min": - assert dMode == "max" - else: - assert dMode == "min" - self.dMode = dMode - - def opt_ctrl(self, t, state, spat_deriv): - """ - :param t: time t - :param state: tuple of coordinates - :param spat_deriv: tuple of spatial derivative in all dimensions - :return: - """ - # System dynamics - # x_dot = v * cos(theta) + d_1 - # y_dot = v * sin(theta) + d_2 - # v_dot = a - # theta_dot = v * tan(delta) / L - - # Graph takes in 4 possible inputs, by default, for now - opt_a = hcl.scalar(self.uMax[0], "opt_a") - opt_w = hcl.scalar(self.uMax[1], "opt_w") - # Just create and pass back, even though they're not used - in3 = hcl.scalar(0, "in3") - in4 = hcl.scalar(0, "in4") - - - if self.uMode == "min": - with hcl.if_(spat_deriv[2] > 0): - opt_a[0] = self.uMin[0] - with hcl.if_(spat_deriv[3] > 0): - opt_w[0] = self.uMin[1] - else: - with hcl.if_(spat_deriv[2] < 0): - opt_a[0] = self.uMin[0] - with hcl.if_(spat_deriv[3] < 0): - opt_w[0] = self.uMin[1] - # return 3, 4 even if you don't use them - return (opt_a[0], opt_w[0], in3[0], in4[0]) - - - def opt_dstb(self, t, state, spat_deriv): - """ - :param spat_deriv: tuple of spatial derivative in all dimensions - :return: a tuple of optimal disturbances - """ - # Graph takes in 4 possible inputs, by default, for now - d1 = hcl.scalar(0, "d1") - d2 = hcl.scalar(0, "d2") - # Just create and pass back, even though they're not used - d3 = hcl.scalar(0, "d3") - d4 = hcl.scalar(0, "d4") - - #with hcl.if_(self.dMode == "max"): - if self.dMode == "max": - with hcl.if_(spat_deriv[0] > 0): - d1[0] = self.dMax[0] - with hcl.elif_(spat_deriv[0] < 0): - d1[0] = self.dMin[0] - with hcl.if_(spat_deriv[1] > 0): - d2[0] = self.dMax[1] - with hcl.elif_(spat_deriv[1] < 0): - d2[0] = self.dMin[1] - # w - else: - with hcl.if_(spat_deriv[0] > 0): - d1[0] = self.dMin[0] - with hcl.elif_(spat_deriv[0] < 0): - d1[0] = self.dMax[0] - with hcl.if_(spat_deriv[1] > 0): - d2[0] = self.dMin[1] - with hcl.elif_(spat_deriv[1] < 0): - d2[0] = self.dMax[1] - return (d1[0], d2[0], d3[0], d4[0]) - - def dynamics(self, t, state, uOpt, dOpt): - # wheelbase of Tamiya TT02 - L = hcl.scalar(0.3, "L") - - x_dot = hcl.scalar(0, "x_dot") - y_dot = hcl.scalar(0, "y_dot") - v_dot = hcl.scalar(0, "v_dot") - theta_dot = hcl.scalar(0, "theta_dot") - - x_dot[0] = state[2] * hcl.cos(state[3]) + dOpt[0] - y_dot[0] = state[2] * hcl.sin(state[3]) + dOpt[1] - v_dot[0] = uOpt[0] - theta_dot[0] = state[2] * (hcl.sin(uOpt[1]) / hcl.cos(uOpt[1])) / L[0] - - return (x_dot[0], y_dot[0], v_dot[0], theta_dot[0]) - - # The below function can have whatever form or parameters users want - # These functions are not used in HeteroCL program, hence is pure Python code and - # can be used after the value function has been obtained. - - def optCtrl_inPython(self, spat_deriv): - """ - :param t: time t - :param state: tuple of coordinates - :param spat_deriv: tuple of spatial derivative in all dimensions - :return: - """ - # System dynamics - # x_dot = v * cos(theta) + d_1 - # y_dot = v * sin(theta) + d_2 - # v_dot = a - # theta_dot = v * tan(delta) / L - opt_a = self.uMax[0] - opt_w = self.uMax[1] - - # The initialized control only change sign in the following cases - if self.uMode == "min": - if spat_deriv[2] > 0: - opt_a = self.uMin[0] - if spat_deriv[3] > 0: - opt_w = self.uMin[1] - else: - if spat_deriv[2] < 0: - opt_a = self.uMin[0] - if spat_deriv[3] < 0: - opt_w = self.uMin[1] - - return opt_a, opt_w - - - diff --git a/odp/dynamics/DubinsCar5DAvoid.py b/odp/dynamics/DubinsCar5DAvoid.py deleted file mode 100644 index 35a83639..00000000 --- a/odp/dynamics/DubinsCar5DAvoid.py +++ /dev/null @@ -1,86 +0,0 @@ -import heterocl as hcl -import numpy as np - -""" -DubinsCar5D avoidance System - x_1_dot = -x_4 + x_5*cos(x_3) + u_theta * x_2 - x_2_dot = x_5*sin(x_3) - u_theta * x_1 - x_3_dot = d_theta - u_theta - x_4_dot = u_v - x_5_dot = d_v - |u_theta| <= u_theta_max - |u_v| <= u_v_max - |d_theta| <= d_theta_max - |d_v| <= d_v_max -""" -def my_sign(x): - sign = hcl.scalar(0, "sign", dtype=hcl.Float()) - with hcl.if_(x == 0): - sign[0] = 0 - with hcl.if_(x > 0): - sign[0] = 1 - with hcl.if_(x < 0): - sign[0] = -1 - return sign[0] - -class DubinsCar5DAvoid: - def __init__(self, x=[0,0,0,0,0], u_theta_max = 1, u_v_max = 1, d_theta_max=1, d_v_max=1, uMode="min", dMode="max"): - self.x = x - self.u_theta_max = u_theta_max - self.u_v_max = u_v_max - self.d_theta_max = d_theta_max - self.d_v_max = d_v_max - self.uMode = uMode - self.dMode = dMode - - def opt_ctrl(self, t, state, spat_deriv): - opt_u_theta = hcl.scalar(0, "opt_u_theta") - opt_u_v = hcl.scalar(0, "opt_u_v") - # Just create and pass back, even though they're not used - in3 = hcl.scalar(0, "in3") - in4 = hcl.scalar(0, "in4") - in5 = hcl.scalar(0, "in5") - - with hcl.if_(self.uMode == "max"): - # use computeGraphs/CustomGraphFunctions#my_sign instead of sign - opt_u_theta[0] = my_sign(spat_deriv[0]*self.x[1] - spat_deriv[1]*self.x[0] - spat_deriv[2]) * self.u_theta_max - opt_u_v[0] = my_sign(spat_deriv[3]) * self.u_v_max - - with hcl.if_(self.uMode == "min"): - opt_u_theta[0] = -my_sign(spat_deriv[0]*self.x[1] - spat_deriv[1]*self.x[0] - spat_deriv[2]) * self.u_theta_max - opt_u_v[0] = -my_sign(spat_deriv[3]) * self.u_v_max - - return (opt_u_theta[0], opt_u_v[0], in3, in4, in5) - - def opt_dstb(self, t, state, spat_deriv): - opt_d_theta = hcl.scalar(0, "opt_d_theta") - opt_d_v = hcl.scalar(0, "opt_d_v") - # Just create and pass back, even though they're not used - d3 = hcl.scalar(0, "d3") - d4 = hcl.scalar(0, "d4") - d5 = hcl.scalar(0, "d5") - - with hcl.if_(self.dMode == "max"): - opt_d_theta[0] = my_sign(spat_deriv[2])*self.d_theta_max - opt_d_v[0] = my_sign(spat_deriv[4])*self.d_v_max - - with hcl.if_(self.dMode == "min"): - opt_d_theta[0] = -my_sign(spat_deriv[2])*self.d_theta_max - opt_d_v[0] = -my_sign(spat_deriv[4])*self.d_v_max - - return (opt_d_theta[0], opt_d_v[0], d3, d4, d5) - - def dynamics(self, t, state, uOpt, dOpt): - x1_dot = hcl.scalar(0, "x_1_dot") - x2_dot = hcl.scalar(0, "x_2_dot") - x3_dot = hcl.scalar(0, "x_3_dot") - x4_dot = hcl.scalar(0, "x_4_dot") - x5_dot = hcl.scalar(0, "x_5_dot") - - x1_dot[0] = -state[3] + state[4] * hcl.cos(state[2]) + uOpt[0] * state[1] - x2_dot[0] = state[4] * hcl.sin(state[2]) - uOpt[0] * state[0] - x3_dot[0] = dOpt[0] - uOpt[0] - x4_dot[0] = uOpt[1] - x5_dot[0] = dOpt[1] - - return (x1_dot[0], x2_dot[0], x3_dot[0], x4_dot[0], x5_dot[0]) diff --git a/odp/dynamics/Humannoid6D_sys1.py b/odp/dynamics/Humannoid6D_sys1.py deleted file mode 100644 index 0d5a7291..00000000 --- a/odp/dynamics/Humannoid6D_sys1.py +++ /dev/null @@ -1,139 +0,0 @@ -import heterocl as hcl -import numpy as np - -class Humanoid_6D: - def __init__(self, x=[0, 0, 0, 0, 0, 0], uMin=np.array([-0.5*0.1, -5.0, -1.0]), uMax=np.array([0.5*0.1, 5.0, 1.0]), - dMin=np.array([0.0, 0.0, 0.0, 0.0]), dMax=np.array([0.0, 0.0, 0.0, 0.0]), - dims=6, uMode="min", dMode="max"): - self.x = x - self.uMode = uMode - self.dMode = dMode - - # Object properties - self.x = x - - # Control bounds - self.uMin = uMin - self.uMax = uMax - - # Disturbance bounds - self.dMin = dMin - self.dMax = dMax - - self.dims = dims - - # Some constants - self.r_f = 0.1 - self.a_z_max = 5 - self.a_x_max = 1 - self.J = 0.125 - self.g = -9.81 - self.L = 1.2 - - def dynamics(self, t,state, uOpt, dOpt): - """ - - :param t: time - :param state: tuple of grid coordinates in 6 dimensions - :param uOpt: tuple of optimal control - :param dOpt: tuple of optimal disturbances - :return: tuple of time derivates in all dimensions - """ - - # Set of differential equations describing the system - # x1_dot = x2 - # x2_dot = ( g + u2) * (x1 + u1) /x3 + u3 - # x3_dot = x4 - # x4_dot = u2 - # x5_dot = x6 - # x6_dot = ( x3 / J ) * u3 - - x1_dot = hcl.scalar(0, "x1_dot") - x2_dot = hcl.scalar(0, "x2_dot") - x3_dot = hcl.scalar(0, "x3_dot") - x4_dot = hcl.scalar(0, "x4_dot") - x5_dot = hcl.scalar(0, "x5_dot") - x6_dot = hcl.scalar(0, "x6_dot") - - x1_dot[0] = state[1] - x2_dot[0] = (self.g + uOpt[1])*(state[0] + uOpt[0])/state[2] + uOpt[2] - x3_dot[0] = state[3] - x4_dot[0] = uOpt[1] - x5_dot[0] = state[5] - x6_dot[0] = state[2] * uOpt[2]/ self.J - return (x1_dot[0], x2_dot[0], x3_dot[0], x4_dot[0], x5_dot[0], x6_dot[0]) - - def opt_ctrl(self, t, state, spat_deriv): - """ - :param t: time t - :param state: tuple of coordinates in 6 dimensions - :param spat_deriv: spatial derivative in all dimensions - :return: tuple of optimal control - """ - - # Optimal control 1, 2, 3 - uOpt1 = hcl.scalar(0, "uOpt1") - uOpt2 = hcl.scalar(0, "uOpt2") - uOpt3 = hcl.scalar(0, "uOpt3") - - SumUU = hcl.scalar(0, "SumUU") - SumUL = hcl.scalar(0, "SumUL") - SumLU = hcl.scalar(0, "SumLU") - SumLL = hcl.scalar(0, "SumLL") - parSum= hcl.scalar(0, "parSum") - - with hcl.if_(self.uMode == "min"): - # everything containing (u1, u2) in Hamiltonian, for all combinations of u1 and u2 - SumUU[0] = spat_deriv[1]*(self.g + self.uMax[1]) * (state[0] + self.uMax[0])/state[2] + \ - spat_deriv[3] * self.uMax[1] - SumUL[0] = spat_deriv[1]*(self.g + self.uMax[1]) * (state[0] + self.uMin[0])/state[2] + \ - spat_deriv[3] * self.uMax[1] - SumLU[0] = spat_deriv[1]*(self.g + self.uMin[1]) * (state[0] + self.uMax[0])/state[2] + \ - spat_deriv[3] * self.uMin[1] - SumLL[0] = spat_deriv[1]*(self.g + self.uMin[1]) * (state[0] + self.uMin[0])/state[2] + \ - spat_deriv[3] * self.uMin[1] - - # try every combination of u1 and u2 and take minimum - with hcl.if_(SumUU[0] > SumUL[0]): - uOpt1[0] = self.uMin[0] - uOpt2[0] = self.uMax[1] - SumUU[0] = SumUL[0] - - with hcl.elif_(SumUU[0] < SumUL[0]): - uOpt1[0] = self.uMax[0] - uOpt2[0] = self.uMax[1] - - with hcl.if_(SumUU[0] > SumLU[0]): - uOpt1[0] = self.uMax[0] - uOpt2[0] = self.uMin[1] - SumUU[0] = SumLU[0] - - with hcl.if_(SumUU[0] > SumLL[0]): - uOpt1[0] = self.uMin[0] - uOpt2[0] = self.uMin[1] - - # Find u3 - # everything multiplied by u3 in Hamiltonian - parSum[0] = spat_deriv[1] + spat_deriv[5]*state[2]/self.J - - with hcl.if_(parSum[0] > 0): - uOpt3[0] = self.uMin[2] - - with hcl.elif_(parSum[0] < 0): - uOpt3[0] = self.uMax[2] - - return (uOpt1[0], uOpt2[0], uOpt3[0]) - - def opt_dstb(self, spat_deriv): - """ - :param spat_deriv: spatial derivative in all dimensions - :return: tuple of optimal disturbance - """ - dOpt1 = hcl.scalar(0, "dOpt1") - dOpt2 = hcl.scalar(0, "dOpt2") - dOpt3 = hcl.scalar(0, "dOpt3") - dOpt4 = hcl.scalar(0, "dOpt4") - dOpt5 = hcl.scalar(0, "dOpt5") - dOpt6 = hcl.scalar(0, "dOpt6") - return (dOpt1[0], dOpt2[0], dOpt3[0], dOpt4[0], dOpt5[0], dOpt6[0]) - diff --git a/odp/dynamics/ROV_WaveBwds_6D.py b/odp/dynamics/ROV_WaveBwds_6D.py deleted file mode 100644 index 8c6c1af9..00000000 --- a/odp/dynamics/ROV_WaveBwds_6D.py +++ /dev/null @@ -1,181 +0,0 @@ -import heterocl as hcl -import numpy as np -import math -from odp.computeGraphs.CustomGraphFunctions import my_abs - -class ROV_WaveBwds_6D: - def __init__(self, x=[0, 0, 0, 0, 0, 0], uMin=np.array([-6, -15]), uMax=np.array([6, 15]), pMin=np.array([-0.2, -0.15]), pMax=np.array([0.2, 0.15]), - dMin=np.array([-0.02, -0.02, -0.01, -0.01]), dMax=np.array([0.02, 0.02, 0.01, 0.01]), - dims=6, uMode="min", dMode="max"): - self.x = x - self.uMode = uMode - self.dMode = dMode - - # Object properties - self.x = x - - # Control bounds - self.uMin = uMin - self.uMax = uMax - - # Planner bounds - self.pMin = pMin - self.pMax = pMax - - # Disturbance bounds - self.dMin = dMin - self.dMax = dMax - - self.dims = dims - - # Define some constants - self.m = 116 # Mass - self.b = 116.2 # Displaced mass - self.X_udot = -167.6 # Added mass x - self.Z_wdot = -383 # Addeed mass z - self.X_u = 26.9 # linear damping x - self.Z_w = 0 # linear damping z - self.X_uu = 241.3 #quadratic damping x - self.Z_ww = 256.6 # quadratic damping z - self.A = 2 # wave amplitude - self.omega = 0.5*math.pi # wave frequency - self.g = 9.81 # gravity - self.k = pow(self.omega,2)/self.g # wavenumber - self.W = self.m * self.g # weight of vehicle - self.Buoy = self.b * self.g # buoyancy - self.B = np.array([[3.2,0.0], [0.6, 1.0]]) - - def opt_ctrl(self, t, state, spat_deriv): - uOpt1 = hcl.scalar(0, "uOpt1") - uOpt2 = hcl.scalar(0, "uOpt2") - uOpt3 = hcl.scalar(0, "uOpt3") - uOpt4 = hcl.scalar(0, "uOpt4") - - parSum1 = hcl.scalar(0, "parSum1") - parSum2 = hcl.scalar(0, "parSum2") - - with hcl.if_(self.uMode == "min"): - with hcl.if_(spat_deriv[0] > 0): - uOpt3[0] = -self.pMax[0] - with hcl.elif_(spat_deriv[0] < 0): - uOpt3[0] = -self.pMin[0] - - with hcl.if_(spat_deriv[1] > 0): - uOpt4[0] = -self.pMax[1] - with hcl.elif_(spat_deriv[1] < 0): - uOpt4[0] = -self.pMin[1] - - parSum1[0] = (1/(self.m - self.X_udot)) * spat_deriv[2] * self.B[0,0] + (1/(self.m - self.Z_wdot)) * spat_deriv[3] * self.B[1,0] - with hcl.if_(parSum1[0] > 0): - uOpt1[0] = self.uMin[0] - with hcl.elif_(parSum1[0] < 0): - uOpt1[0] = self.uMax[0] - - parSum2[0] = (1/(self.m - self.X_udot)) * spat_deriv[2] * self.B[0,1] + (1/(self.m - self.Z_wdot)) * spat_deriv[3] * self.B[1,1] - with hcl.if_(parSum2[0] > 0): - uOpt2[0] = self.uMin[1] - with hcl.elif_(parSum2[0] < 0): - uOpt2[0] = self.uMax[1] - - return (uOpt1[0], uOpt2[0], uOpt3[0], uOpt4[0]) - - def opt_dstb(self, t, state, spat_deriv): - dOpt1 = hcl.scalar(0, "dOpt1") - dOpt2 = hcl.scalar(0, "dOpt2") - dOpt3 = hcl.scalar(0, "dOpt3") - dOpt4 = hcl.scalar(0, "dOpt4") - - with hcl.if_(self.dMode == "max"): - with hcl.if_(spat_deriv[0] > 0): - dOpt1[0] = self.dMax[0] - with hcl.elif_(spat_deriv[0] < 0): - dOpt1[0] = self.dMin[0] - - with hcl.if_(spat_deriv[1] > 0): - dOpt2[0] = self.dMax[1] - with hcl.elif_(spat_deriv[1] < 0): - dOpt2[0] = self.dMin[1] - - with hcl.if_(spat_deriv[2] > 0): - dOpt3[0] = self.dMax[2] - with hcl.elif_(spat_deriv[2] < 0): - dOpt3[0] = self.dMin[2] - - with hcl.if_(spat_deriv[3] > 0): - dOpt4[0] = self.dMax[3] - with hcl.elif_(spat_deriv[3] < 0): - dOpt4[0] = self.dMin[3] - - with hcl.elif_(self.dMode == "min"): - with hcl.if_(spat_deriv[0] > 0): - dOpt1[0] = self.dMin[0] - with hcl.elif_(spat_deriv[0] < 0): - dOpt1[0] = self.dMax[0] - - with hcl.if_(spat_deriv[1] > 0): - dOpt2[0] = self.dMin[1] - with hcl.elif_(spat_deriv[1] < 0): - dOpt2[0] = self.dMax[1] - - with hcl.if_(spat_deriv[2] > 0): - dOpt3[0] = self.dMin[2] - with hcl.elif_(spat_deriv[2] < 0): - dOpt3[0] = self.dMax[2] - - with hcl.if_(spat_deriv[3] > 0): - dOpt4[0] = self.dMin[3] - with hcl.elif_(spat_deriv[3] < 0): - dOpt4[0] = self.dMax[3] - - return (dOpt1[0], dOpt2[0], dOpt3[0], dOpt4[0]) - - def dynamics(self, t, state, uOpt, dOpt): # Assume order of state is (x_a, z_a, u_r, w_r, x, z) - # Some constants for convenience - G1 = hcl.scalar(0, "G1") - F1 = hcl.scalar(0, "F1") - sigma = hcl.scalar(0, "sigma") - Phi_11 = hcl.scalar(0, "Phi_11") - Phi_12 = hcl.scalar(0, "Phi_12") - Phi_21 = hcl.scalar(0, "Phi_21") - Phi_22 = hcl.scalar(0, "Phi_22") - - x1_dot = hcl.scalar(0, "x1_dot") - x2_dot = hcl.scalar(0, "x2_dot") - x3_dot = hcl.scalar(0, "x3_dot") - x4_dot = hcl.scalar(0, "x4_dot") - x5_dot = hcl.scalar(0, "x5_dot") - x6_dot = hcl.scalar(0, "x6_dot") - - # Get the values - G1[0] = self.A * self.omega * hcl.exp(-self.k * state[5]) - F1[0] = self.k * G1[0] - sigma[0] = self.k * state[4] - self.omega * (-t[0]) - - Phi_11[0] = F1[0] * (-hcl.sin(sigma[0])) - Phi_12[0] = F1[0] * hcl.cos(sigma[0]) - Phi_21[0] = Phi_12[0] - Phi_22[0] = -Phi_11[0] - - # Question: What is B matrix - x1_dot[0] = state[2] + G1[0] * hcl.cos(sigma[0]) + dOpt[0] - uOpt[2] - x2_dot[0] = state[3] + G1[0] * (-hcl.sin(sigma[0])) + dOpt[1] - uOpt[3] - - x3_dot[0] = (1/(self.m - self.X_udot))*(-Phi_11[0]*(self.b - self.X_udot)* state[2] + (self.b - self.m)*(G1[0] * self.omega * hcl.sin(sigma[0])) +\ - Phi_11[0] * (state[2] + G1*hcl.cos(sigma[0])) + Phi_21[0]*(state[3] + G1[0]*(-hcl.sin(sigma[0]))) - (self.X_u + self.X_uu * my_abs(state[2]))*state[2] + \ - self.B[0,0]*uOpt[0] + self.B[0,1]*uOpt[1]) + dOpt[2] - - x4_dot[0] = (1/(self.m - self.Z_wdot))*(-Phi_22*(self.b - self.Z_wdot)*state[3] + \ - (self.b - self.m) * (G1 * self.omega * hcl.cos(sigma[0])) + \ - Phi_12[0] * (state[2] + G1 * hcl.cos(sigma[0])) + \ - Phi_22[0] * (state[3] + G1 * (-hcl.sin(sigma[0]))) - \ - (-(self.W - self.Buoy)) - (self.Z_w + self.Z_ww * my_abs(state[3])) * state[3] + \ - self.B[1,0] * uOpt[0] + self.B[1,1] * uOpt[1]) + \ - dOpt[3] - - x5_dot[0] = state[2] + G1[0] * hcl.cos(sigma[0]) + dOpt[0] - x6_dot[0] = state[3] + G1[0] * (-hcl.sin(sigma[0])) + dOpt[1] - return (x1_dot[0], x2_dot[0], x3_dot[0], x4_dot[0], x5_dot[0], x6_dot[0]) - - def Hamiltonian(self, t_deriv, spatial_deriv): - return t_deriv[0] * spatial_deriv[0] + t_deriv[1] * spatial_deriv[1] + t_deriv[2] * spatial_deriv[2] + t_deriv[3] * spatial_deriv[3] \ - + t_deriv[4] * spatial_deriv[4] + t_deriv[5] * spatial_deriv[5] diff --git a/odp/dynamics/__init__.py b/odp/dynamics/__init__.py index d8e33bc1..bd678e72 100644 --- a/odp/dynamics/__init__.py +++ b/odp/dynamics/__init__.py @@ -1,7 +1,3 @@ -from odp.dynamics.DubinsCapture import DubinsCapture -from odp.dynamics.DubinsCar import DubinsCar -from odp.dynamics.DubinsCar4D import DubinsCar4D -from odp.dynamics.DubinsCar4D2 import DubinsCar4D2 -from odp.dynamics.DubinsCar5DAvoid import DubinsCar5DAvoid -from odp.dynamics.Humannoid6D_sys1 import Humanoid_6D -from odp.dynamics.ROV_WaveBwds_6D import ROV_WaveBwds_6D +from .base import * +from .bicycle5d import * +from .dubins3d import * \ No newline at end of file diff --git a/odp/dynamics/base.py b/odp/dynamics/base.py new file mode 100644 index 00000000..6e6c7603 --- /dev/null +++ b/odp/dynamics/base.py @@ -0,0 +1,79 @@ +from abc import ABC, abstractmethod +import numpy as np + +__all__ = ['DynamicsBase'] + +class DynamicsBase(ABC): + + def __init__(self, ctrl_range, dstb_range, mode='reach'): + super().__init__() + + self.ctrl_range = np.asarray(ctrl_range) + assert self.ctrl_range.shape[1] == self.ctrl_dims + + self.dstb_range = np.asarray(dstb_range) + assert self.dstb_range.shape[1] == self.dstb_dims + + modes = {'reach': {"uMode": "min", "dMode": "max"}, + 'avoid': {"uMode": "max", "dMode": "min"}} + self.mode = modes[mode] + + @property + @abstractmethod + def state_dims(self) -> int: pass + + @property + @abstractmethod + def ctrl_dims(self) -> int: pass + + @property + @abstractmethod + def dstb_dims(self) -> int: pass + + @abstractmethod + def opt_dstb(self, d, dv, t, x): + """ + Update optimal disturbance. + + Args: + d (hcl.tensor): optimal disturbance to be updated + t (hcl.tensor): 2-element tensor with current time step and next. + x (hcl.tensor): state + dv (hcl.tensor): spatial derivative (dV/dx) + + Returns: None + """ + pass + + @abstractmethod + def opt_ctrl(self, u, dv, t, x): + """ + Update optimal control. + + Args: + u (hcl.tensor): optimal control to be updated + t (hcl.tensor): 2-element tensor with current time step and next. + x (hcl.tensor): state + dv (hcl.tensor): spatial derivative (dV/dx) + + Returns: None + """ + pass + + @abstractmethod + def dynamics(self, dx, t, x, u, d): + """ + Update state change. + + Similar to opt_dstb. + + Args: + dx (hcl.tensor): state derivative (dx/dt) to be updated + t (hcl.tensor): 2-element tensor with current time step and next. + x (hcl.tensor): state + u (hcl.tensor): control input + d (hcl.tensor): disturbance + + Returns: None + """ + pass diff --git a/odp/dynamics/bicycle4d.py b/odp/dynamics/bicycle4d.py new file mode 100644 index 00000000..940c40ca --- /dev/null +++ b/odp/dynamics/bicycle4d.py @@ -0,0 +1,96 @@ +import heterocl as hcl +import numpy as np + +from .base import DynamicsBase + +__all__ = ['Bicycle4D'] + + +class Bicycle4D(DynamicsBase): + + state_dims = 4 + ctrl_dims = 2 + dstb_dims = state_dims + + wheelbase = 0.32 + + X, Y, YAW, VEL = range(state_dims) + STEERING, VELOCITY = range(ctrl_dims) + + def __init__(self, ctrl_range, dstb_range, mode='reach', *, wheelbase): + super().__init__(ctrl_range, dstb_range, mode) + + self.wheelbase = wheelbase + + def dynamics(self, dx, t, x, u, d): + + # x_dot = v * cos(theta) + d_1 + dx[self.X] = (x[self.VEL] * hcl.cos(x[self.YAW]) + + d[self.X]) + + # y_dot = v * sin(theta) + d_2 + dx[self.Y] = (x[self.VEL] * hcl.sin(x[self.YAW]) + + d[self.Y]) + + # theta_dot = (v * tan(u1))/L + d3 + hcl_tan = lambda a: hcl.sin(a) / hcl.cos(a) + dx[self.YAW] = (x[self.VEL] * hcl_tan(u[self.STEERING])/self.wheelbase + + d[self.YAW]) + + # v_dot = u2 + d4 + dx[self.VEL] = u[self.VELOCITY] + d[self.VEL] + + def opt_ctrl(self, u, dv, t, x): + + uMin, uMax = self.ctrl_range + + if self.mode['uMode'] == "max": + # Steering + with hcl.if_(0 <= x[self.VEL]): + with hcl.if_(0 <= dv[self.YAW]): + u[self.STEERING] = uMax[self.STEERING] + with hcl.else_(): + u[self.STEERING] = uMin[self.STEERING] + with hcl.else_(): + with hcl.if_(0 <= dv[self.YAW]): + u[self.STEERING] = uMin[self.STEERING] + with hcl.else_(): + u[self.STEERING] = uMax[self.STEERING] + # Velocity + with hcl.if_(0 <= dv[self.VEL]): + u[self.VELOCITY] = uMax[self.VELOCITY] + with hcl.else_(): + u[self.VELOCITY] = uMin[self.VELOCITY] + else: + # Steering + with hcl.if_(0 <= x[self.VEL]): + with hcl.if_(0 <= dv[self.YAW]): + u[self.STEERING] = uMin[self.STEERING] + with hcl.else_(): + u[self.STEERING] = uMax[self.STEERING] + with hcl.else_(): + with hcl.if_(0 <= dv[self.YAW]): + u[self.STEERING] = uMax[self.STEERING] + with hcl.else_(): + u[self.STEERING] = uMin[self.STEERING] + # Velocity + with hcl.if_(0 <= dv[self.VEL]): + u[self.VELOCITY] = uMin[self.VELOCITY] + with hcl.else_(): + u[self.VELOCITY] = uMax[self.VELOCITY] + + def opt_dstb(self, d, dv, t, x): + + dMin, dMax = self.dstb_range + + for i in range(self.dstb_dims): + if self.mode['dMode'] == "max": + with hcl.if_(0 <= dv[i]): + d[i] = dMax[i] + with hcl.else_(): + d[i] = dMin[i] + else: + with hcl.if_(0 <= dv[i]): + d[i] = dMin[i] + with hcl.else_(): + d[i] = dMax[i] diff --git a/odp/dynamics/bicycle5d.py b/odp/dynamics/bicycle5d.py new file mode 100644 index 00000000..9c80a864 --- /dev/null +++ b/odp/dynamics/bicycle5d.py @@ -0,0 +1,99 @@ +import heterocl as hcl +import numpy as np + +from .base import DynamicsBase + +__all__ = ['Bicycle5D'] + + +class Bicycle5D(DynamicsBase): + + state_dims = 5 + ctrl_dims = 2 + dstb_dims = state_dims + + wheelbase = 0.32 + + X, Y, YAW, DELTA, VEL = range(state_dims) + STEERING, ACCELERATION = range(ctrl_dims) + + def __init__(self, ctrl_range, dstb_range, mode='reach', *, wheelbase): + super().__init__(ctrl_range, dstb_range, mode) + + self.wheelbase = wheelbase + + def dynamics(self, dx, t, x, u, d): + + # x_dot = v * cos(yaw) + d_1 + dx[self.X] = (x[self.VEL] * hcl.cos(x[self.YAW]) + + d[self.X]) + + # y_dot = v * sin(yaw) + d_2 + dx[self.Y] = (x[self.VEL] * hcl.sin(x[self.YAW]) + + d[self.Y]) + + # yaw_dot = (v * tan(delta))/L + d3 + hcl_tan = lambda a: hcl.sin(a) / hcl.cos(a) + dx[self.YAW] = (x[self.VEL] * hcl_tan(x[self.DELTA])/self.wheelbase + + d[self.YAW]) + + # delta_dot = u1 + d4 + dx[self.DELTA] = u[self.STEERING] # + d[self.DELTA] + + # v_dot = u2 + d5 + dx[self.VEL] = u[self.ACCELERATION] # + d[self.VEL] + + def opt_ctrl(self, u, dv, t, x): + + uMin, uMax = self.ctrl_range + + if self.mode['uMode'] == "max": + # Steering + with hcl.if_(0 <= x[self.VEL]): + with hcl.if_(0 <= dv[self.YAW]): + u[self.STEERING] = uMax[self.STEERING] + with hcl.else_(): + u[self.STEERING] = uMin[self.STEERING] + with hcl.else_(): + with hcl.if_(0 <= dv[self.YAW]): + u[self.STEERING] = uMin[self.STEERING] + with hcl.else_(): + u[self.STEERING] = uMax[self.STEERING] + # Velocity + with hcl.if_(0 <= dv[self.VEL]): + u[self.ACCELERATION] = uMax[self.ACCELERATION] + with hcl.else_(): + u[self.ACCELERATION] = uMin[self.ACCELERATION] + else: + # Steering + with hcl.if_(0 <= x[self.VEL]): + with hcl.if_(0 <= dv[self.YAW]): + u[self.STEERING] = uMin[self.STEERING] + with hcl.else_(): + u[self.STEERING] = uMax[self.STEERING] + with hcl.else_(): + with hcl.if_(0 <= dv[self.YAW]): + u[self.STEERING] = uMax[self.STEERING] + with hcl.else_(): + u[self.STEERING] = uMin[self.STEERING] + # Velocity + with hcl.if_(0 <= dv[self.VEL]): + u[self.ACCELERATION] = uMin[self.ACCELERATION] + with hcl.else_(): + u[self.ACCELERATION] = uMax[self.ACCELERATION] + + def opt_dstb(self, d, dv, t, x): + + dMin, dMax = self.dstb_range + + for i in range(self.dstb_dims): + if self.mode['dMode'] == "max": + with hcl.if_(0 <= dv[i]): + d[i] = dMax[i] + with hcl.else_(): + d[i] = dMin[i] + else: + with hcl.if_(0 <= dv[i]): + d[i] = dMin[i] + with hcl.else_(): + d[i] = dMax[i] diff --git a/odp/dynamics/dubins3d.py b/odp/dynamics/dubins3d.py new file mode 100644 index 00000000..aa43f1b9 --- /dev/null +++ b/odp/dynamics/dubins3d.py @@ -0,0 +1,116 @@ +import heterocl as hcl +import numpy as np + +from .base import DynamicsBase + +__all__ = ['DubinsCar', 'DubinsCapture'] + + +class DubinsCar3D(DynamicsBase): + + state_dims = 3 + ctrl_dims = 1 + dstb_dims = 0 + + X, Y, THETA = range(state_dims) + TURN, = range(ctrl_dims) + + def __init__(self, mode='reach', *, speed=1., max_turn_rate=1.): + super().__init__(ctrl_range=[[-max_turn_rate], + [+max_turn_rate]], + dstb_range=[[], []], + mode=mode) + + self.speed = speed + self.max_turn_rate = max_turn_rate + + def dynamics(self, dx, t, x, u, d): + + # x_dot = v * cos(theta) + dx[self.X] = self.speed * hcl.cos(x[self.THETA]) + + # y_dot = v * sin(theta) + dx[self.Y] = self.speed * hcl.sin(y[self.THETA]) + + # theta_dot = u + dx[self.THETA] = u[self.TURN] + + def opt_ctrl(self, u, dv, t, x): + + uMin, uMax = self.ctrl_range + + if self.mode['uMode'] == 'max': + with hcl.if_(0 <= dv[self.THETA]): + u[self.TURN] = uMax[self.TURN] + with hcl.else_(): + u[self.TURN] = uMin[self.TURN] + else: + with hcl.if_(dv[self.THETA] < 0): + u[self.TURN] = uMax[self.TURN] + with hcl.else_(): + u[self.TURN] = uMax[self.TURN] + + def opt_dstb(self, d, dv, t, x): + pass + +class DubinsCapture(DynamicsBase): + + state_dims = 3 + ctrl_dims = 1 + dstb_dims = 2 + + def __init__(self, mode='reach', *, speed=1., max_turn_rate=1., max_disturbance=1.): + super().__init__(ctrl_range=[[-max_turn_rate], + [+max_turn_rate]], + dstb_range=[[-max_disturbance] * self.dstb_dims, + [+max_disturbance] * self.dstb_dims], + mode=mode) + + self.speed = speed + self.max_turn_rate = max_turn_rate + self.max_disturbance = max_disturbance + + def dynamics(self, dx, t, x, u, d): + dx[0] = -self.speed + self.speed*hcl.cos(x[2]) + u[0]*x[1] + dx[1] = + self.speed*hcl.sin(x[2]) - u[0]*x[0] + dx[2] = d[0] - u[0] + + def opt_ctrl(self, u, dv, t, x): + + uMin, uMax = self.ctrl_range + + # Declare a variable + a_term = hcl.scalar(0, "a_term") + a_term.v = dv[0]*x[1] - dv[1]*x[0] - dv[2] + + u[0] = uMax[0] + + if self.mode['uMode'] == 'max': + with hcl.if_(0 <= a_term.v): + u[0] = uMax[0] + with hcl.else_(): + u[0] = uMin[0] + else: + with hcl.if_(a_term.v < 0): + u[0] = uMax[0] + with hcl.else_(): + u[0] = uMin[0] + + def opt_dstb(self, d, dv, t, x): + + dMin, dMax = self.dstb_range + + # Declare a variable + b_term = hcl.scalar(0, "b_term") + b_term.v = dv[2] + + if self.mode['dMode'] == 'max': + with hcl.if_(0 <= b_term.v): + d[0] = dMax[0] + with hcl.else_(): + d[0] = dMin[0] + else: + with hcl.if_(b_term.v < 0): + d[0] = dMax[0] + with hcl.else_(): + d[0] = dMin[0] diff --git a/odp/dynamics/dubins4d.py b/odp/dynamics/dubins4d.py new file mode 100644 index 00000000..dadd747a --- /dev/null +++ b/odp/dynamics/dubins4d.py @@ -0,0 +1,197 @@ +import heterocl as hcl +import numpy as np + +from .base import DynamicsBase + +__all__ = ['DubinsCar4D', 'DubinsCar4D2'] + + +class DubinsCar4D(DynamicsBase): + """ 4D DUBINS CAR DYNAMICS IMPLEMENTATION + x_dot = v * cos(theta) + d_1 + y_dot = v * sin(theta) + d_2 + v_dot = a + theta_dot = w + """ + + state_dims = 4 + ctrl_dims = 2 + dstb_dims = 2 + + X, Y, V, THETA = range(state_dims) + ACC, TURN = range(ctrl_dims) + + def __init__(self, + ctrl_range=[[-1, -1], + [+1, +1]], + dstb_range=[[-0.25, -0.25], + [+0.25, +0.25]], + mode='reach'): + super().__init__(ctrl_range, dstb_range, mode) + + def dynamics(self, dx, t, x, u, d): + # x_dot = v * cos(theta) + d_1 + dx[self.X] = (x[self.V] * hcl.cos(x[self.THETA]) + + d[self.X]) + + # y_dot = v * sin(theta) + d_2 + dx[self.Y] = (x[self.V] * hcl.sin(x[self.THETA]) + + d[self.Y]) + + # v_dot = a + dx[self.V] = u[self.ACC] + + # theta_dot = w + dx[self.THETA] = u[self.TURN] + + def dynamics(self, t, state, uOpt, dOpt): + x_dot = hcl.scalar(0, "x_dot") + y_dot = hcl.scalar(0, "y_dot") + v_dot = hcl.scalar(0, "v_dot") + theta_dot = hcl.scalar(0, "theta_dot") + + x_dot[0] = state[2] * hcl.cos(state[3]) + dOpt[0] + y_dot[0] = state[2] * hcl.sin(state[3]) + dOpt[1] + v_dot[0] = uOpt[0] + theta_dot[0] = uOpt[1] + + return (x_dot[0], y_dot[0], v_dot[0] ,theta_dot[0]) + + + def opt_ctrl(self, u, dv, t, x): + + uMin, uMax = self.ctrl_range + + if self.mode['uMode'] == "max": + # Acceleration + with hcl.if_(dv[self.THETA] < 0): + u[self.ACC] = uMin[self.ACC] + with hcl.else_(): + u[self.ACC] = uMax[self.ACC] + # Turn rate + with hcl.if_(dv[self.THETA] < 0): + u[self.TURN] = uMin[self.TURN] + with hcl.else_(): + u[self.TURN] = uMax[self.TURN] + else: + # Acceleration + with hcl.if_(dv[self.V] > 0): + u[self.ACC] = uMin[self.ACC] + with hcl.else_(): + u[self.ACC] = uMax[self.ACC] + # Turn rate + with hcl.if_(dv[self.THETA] > 0): + u[self.TURN] = uMin[self.TURN] + with hcl.else_(): + u[self.TURN] = uMax[self.TURN] + + + def opt_dstb(self, d, dv, t, x): + + dMin, dMax = self.dstb_range + + for i in range(self.dstb_dims): + if self.mode['dMode'] == "max": + with hcl.if_(0 <= dv[i]): + d[i] = dMax[i] + with hcl.else_(): + d[i] = dMin[i] + else: + with hcl.if_(0 <= dv[i]): + d[i] = dMin[i] + with hcl.else_(): + d[i] = dMax[i] + + +class DubinsCar4D2(DynamicsBase): + """ + 4D DUBINS CAR DYNAMICS IMPLEMENTATION + used to model dynamics of Jetracer + + x_dot = v * cos(theta) + y_dot = v * sin(theta) + v_dot = a + theta_dot = v * tan(delta) / L + + delta := steering angle + L := wheelbase of car + + (6.2) https://arxiv.org/pdf/1711.03449.pdf + """ + + state_dims = 4 + ctrl_dims = 2 + dstb_dims = 2 + + X, Y, V, THETA = range(state_dims) + ACC, TURN = range(ctrl_dims) + + def __init__(self, + ctrl_range=[[-1.5, -np.pi/18], + [+1.5, +np.pi/18]], + dstb_range=[[-0.0, -0.0], + [+0.0, +0.0]], + mode='reach', + *, + wheelbase=0.3): # wheelbase of Tamiya TT02 + super().__init__(ctrl_range, dstb_range, mode) + + self.wheelbase = wheelbase + + def dynamics(self, dx, t, x, u, d): + # x_dot = v * cos(theta) + dx[self.X] = (x[self.V] * hcl.cos(x[self.THETA]) + d[self.X]) + + # y_dot = v * sin(theta) + dx[self.Y] = (x[self.V] * hcl.sin(x[self.THETA]) + d[self.Y]) + + # v_dot = a + dx[self.V] = (u[self.ACC] + d[self.V]) + + # theta_dot = v * tan(u1) / L + hcl_tan = lambda a: hcl.sin(a) / hcl.cos(a) + dx[self.THETA] = (x[self.V] * hcl_tan(u[self.TURN]) / self.wheelbase + d[self.THETA]) + + def opt_ctrl(self, u, dv, t, x): + + uMin, uMax = self.ctrl_range + + if self.mode['uMode'] == "max": + # Acceleration + with hcl.if_(0 <= dv[self.V]): + u[self.ACC] = uMax[self.ACC] + with hcl.else_(): + u[self.ACC] = uMin[self.ACC] + # Turn rate + with hcl.if_(0 <= dv[self.THETA]): + u[self.TURN] = uMax[self.TURN] + with hcl.else_(): + u[self.TURN] = uMin[self.TURN] + else: + # Acceleration + with hcl.if_(0 <= dv[self.V]): + u[self.ACC] = uMin[self.ACC] + with hcl.else_(): + u[self.ACC] = uMax[self.ACC] + # Turn rate + with hcl.if_(0 <= dv[self.THETA]): + u[self.TURN] = uMin[self.TURN] + with hcl.else_(): + u[self.TURN] = uMax[self.TURN] + + def opt_dstb(self, d, dv, t, x): + + dMin, dMax = self.dstb_range + + for i in range(self.dstb_dims): + if self.mode['dMode'] == "max": + with hcl.if_(0 <= dv[i]): + d[i] = dMax[i] + with hcl.else_(): + d[i] = dMin[i] + else: + with hcl.if_(0 <= dv[i]): + d[i] = dMin[i] + with hcl.else_(): + d[i] = dMax[i] + diff --git a/odp/grid.py b/odp/grid.py new file mode 100644 index 00000000..bea2e6cd --- /dev/null +++ b/odp/grid.py @@ -0,0 +1,105 @@ +import numpy as np + +class Grid: + """ + Fields: + shape (tuple[int, ...]): Number of points in each dimension axis. + pts_each_dim (None): Deprecated, use shape. + ndims (int): Number of dimensions in grid. + dims (None): Deprecated, use ndims. + max_bounds (np.ndarray): Upper bounds of each dimension. + max (None): Deprecated, use max_bounds. + min_bounds (np.ndarray): Lower bounds of each dimension. + min (None): Deprecated, use min_bounds. + periodic_dims (Optional[list[bool]]): + Boolean switches for each axes if periodic or not. Defaults to all + false, i.e. non-periodic. + pDim (None): Deprecated, use periodic_dims. + dx (np.ndarray): Discretization step for each dimension. + """ + + def __init__(self, shape, max_bounds, min_bounds, periodic_dims=None): + """ + + Args: + shape (list): The number of points for each dimension in the grid. + max_bounds (list): The upper bounds of each dimension in the grid. + min_bounds (list): The lower bounds of each dimension in the grid. + periodic_dims(list, optional): + Boolean switches for each axes if periodic or not. Defaults to + all false, i.e. non-periodic. + """ + + self.shape = tuple(map(int, shape)) + self.ndims = len(shape) + + self.max_bounds = np.asarray(max_bounds) + self.min_bounds = np.asarray(min_bounds) + self.periodic_dims = [] if periodic_dims is None else periodic_dims + + # Exclude the upper bounds for periodic dimensions is not included + # e.g. [-pi, pi) + for dim in self.periodic_dims: + self.max_bounds[dim] = (self.min_bounds[dim] + + ((self.max_bounds[dim] - self.min_bounds[dim]) + * (1 - 1/self.shape[dim]))) + self.dx = (self.max_bounds - self.min_bounds) / (np.array(self.shape) - 1.0) + + """ + Below is re-shaping the self.vs so that we can make use of broadcasting + self.vs[i] is reshape into (1,1, ... , shape[i], ..., 1) such that shape[i] is used in ith position + """ + self.vs = [] + """ + self.grid_points is same as self.vs; however, it is not reshaped. + self.grid_points[i] is a numpy array with length shape[i] + """ + self.grid_points = [] + for i in range(self.ndims): + tmp = np.linspace(self.min_bounds[i], self.max_bounds[i], + num=self.shape[i]) + broadcast_map = np.ones(self.ndims, dtype=int) + broadcast_map[i] = self.shape[i] + self.grid_points.append(tmp) + + # in order to add our range of points to our grid + # we need to modify the shape of tmp in order to match + # the size of the grid for one of the axis + tmp = np.reshape(tmp, tuple(broadcast_map)) + self.vs.append(tmp) + + def get_index(self, state): + """ Returns a tuple of the closest index of each state in the grid + + Args: + state (tuple): state of dynamic object + """ + index = [] + + for i, s in enumerate(state): + idx = np.searchsorted(self.grid_points[i], s) + if idx > 0 and ( + idx == len(self.grid_points[i]) + or np.fabs(s - self.grid_points[i][idx - 1]) + < np.fabs(s - self.grid_points[i][idx]) + ): + index.append(idx - 1) + else: + index.append(idx) + + return tuple(index) + + def get_value(self, V, state): + """Obtain the approximate value of a state + + Assumes that the state is within the bounds of the grid + + Args: + V (np.array): value function of solved HJ PDE + state (tuple): state of dynamic object + + Returns: + [float]: V(state) + """ + index = self.get_index(state) + return V[index] diff --git a/odp/math.py b/odp/math.py new file mode 100644 index 00000000..8b8c7362 --- /dev/null +++ b/odp/math.py @@ -0,0 +1,103 @@ +import heterocl as hcl + +def min(a, *args): + result = hcl.scalar(a, "min") + for a in args: + with hcl.if_(a < result.v): + result.v = a + return result.v + +def max(a, *args): + result = hcl.scalar(a, "max") + for a in args: + with hcl.if_(result.v < a): + result.v = a + return result.v + +def abs(x): + result = hcl.scalar(0, "abs") + with hcl.if_(x > 0): + result.v = x + with hcl.else_(): + result.v = -x + return result.v + +def sign(x): + result = hcl.scalar(0, "sign") + with hcl.if_(x == 0): + result.v = 0 + with hcl.if_(x > 0): + result.v = 1 + with hcl.if_(x < 0): + result.v = -1 + return result.v + +def red_sum(x): + # rax = hcl.reduce_axis(0, x.shape[0]) + # y = hcl.compute((1,), lambda _: hcl.sum(x[rax], axis=rax)) + y = hcl.scalar(0) + def body(i): + y.v += x[i] + hcl.mutate(x.shape, body) + return y.v + +def red_max(x): + rax = hcl.reduce_axis(0, x.shape[0]) + y = hcl.compute((1,), lambda _: hcl.max(x[rax], axis=rax)) + return y.v + +def dot(x1, x2): + assert x1.shape == x2.shape, 'Different shapes' + y = hcl.compute(x1.shape, lambda i: x1[i] * x2[i]) + return red_sum(y) + # rax = hcl.reduce_axis(0, y.shape[0]) + # d = hcl.compute((1,), lambda _: hcl.sum(y[rax], axis=rax)) + # return d.v + +''' +def _freduce_sum(inp, out): + pass + +def sum(a, axis=None, out=None): + """Sum along tensor axes. Similar API to `numpy.sum()`.""" + + all_axes = list(range(len(a.shape))) + + if axis is None: + axis = all_axes + elif isinstance(axis, int): + axis = [axis] + elif isinstance(axis, tuple): + axis = list(axis) + elif not isinstance(axis, list): + raise TypeError('Invalid type for axis argument') + + # *_axes = the index that identify an axis, e.g. 1 for the col axis of a matrix + # *_idxs = the indices that identify an element in a tensor + # out_shape = shape of resulting tensor + # raxes = hcl objects for reduction axes + + red_axes = list(axis) + raxes = [hcl.reduce_axis(0, a.shape[i], name=f'sum_rax{i}') for i in red_axes] + + out_axes = tuple(filter(lambda i: i not in axis, all_axes)) + out_shape = tuple(map(lambda i: a.shape[i], out_axes)) if out_axes else (1,) + + def rebuild_index(out_idxs): + """Rebuild the indices again (for input tensor).""" + idxs = tuple() + for ax in all_axes: + ## There should only be one possible concatenation for each iteration, check by assertion below + # if ax is an out axis + idxs += tuple(out_idxs[i] for i, out_ax in enumerate(out_axes) if ax == out_ax) + # if ax is an reduce axis + idxs += tuple(raxes[i] for i, red_ax in enumerate(red_axes) if ax == red_ax) + # This fails if out_axes and red_axes are not disjunct + assert len(idxs) == len(all_axes), 'Combined index from red_axes and out_axes (should be unreachable)' + return idxs + + out = hcl.compute(out_shape, lambda *_: 0) + reducer = hcl.reducer(out, lambda x, y: x + y, name='sum_reducer') + + return hcl.compute(out_shape, lambda *idxs: reducer(a[*rebuild_index(idxs)], axis=raxes), name='sum_result') +''' diff --git a/odp/plot.py b/odp/plot.py new file mode 100644 index 00000000..03ca7565 --- /dev/null +++ b/odp/plot.py @@ -0,0 +1,121 @@ +from copy import deepcopy + +import numpy as np +import matplotlib.pyplot as plt +import plotly.graph_objects as go + + +class PlotOptions: + def __init__(self, do_plot=True, plot_type="3d_plot", plotDims=[], slicesCut=[], min_isosurface = 0, max_isosurface = 0): + if plot_type not in ["2d_plot", "3d_plot"]: + raise Exception("Illegal plot type !") + + if plot_type == "2d_plot" : + if len(plotDims) != 2: + raise Exception("Make sure that dim_plot size is 2 !!") + + if plot_type == "3d_plot" : + if len(plotDims) != 3: + raise Exception("Make sure that dim_plot size is 3 !!") + + self.do_plot = do_plot + self.dims_plot = plotDims + self.plot_type = plot_type + self.slices = slicesCut + self.min_isosurface = min_isosurface + self.max_isosurface = max_isosurface + + +def plot_isosurface(grid, V, plot_option): + dims_plot = plot_option.dims_plot + idx = [slice(None)] * grid.ndims + slice_idx = 0 + + dims_list = list(range(grid.ndims)) + for i in dims_list: + if i not in dims_plot: + idx[i] = plot_option.slices[slice_idx] + slice_idx += 1 + + if len(dims_plot) != 3 and len(dims_plot) != 2: + raise Exception('dims_plot length should be equal to 3\n') + + if len(dims_plot) == 3: + # Plot 3D isosurface + dim1, dim2, dim3 = dims_plot[0], dims_plot[1], dims_plot[2] + complex_x = complex(0, grid.shape[dim1]) + complex_y = complex(0, grid.shape[dim2]) + complex_z = complex(0, grid.shape[dim3]) + mg_X, mg_Y, mg_Z = np.mgrid[grid.min_bounds[dim1]:grid.max_bounds[dim1]:complex_x, + grid.min_bounds[dim2]:grid.max_bounds[dim2]:complex_y, + grid.min_bounds[dim3]:grid.max_bounds[dim3]:complex_z] + + my_V = V[tuple(idx)] + + if (my_V > 0.0).all(): + print("Implicit surface will not be shown since all values are positive ") + if (my_V < 0.0).all(): + print("Implicit surface will not be shown since all values are negative ") + + print("Plotting beautiful plots. Please wait\n") + fig = go.Figure(data=go.Isosurface( + x=mg_X.flatten(), + y=mg_Y.flatten(), + z=mg_Z.flatten(), + value=my_V.flatten(), + colorscale='jet', + isomin=plot_option.min_isosurface, + surface_count=1, + isomax=plot_option.max_isosurface, + caps=dict(x_show=True, y_show=True) + )) + fig.show() + print("Please check the plot on your browser.") + + if len(dims_plot) == 2: + dim1, dim2 = dims_plot[0], dims_plot[1] + complex_x = complex(0, grid.shape[dim1]) + complex_y = complex(0, grid.shape[dim2]) + mg_X, mg_Y = np.mgrid[grid.min_bounds[dim1]:grid.max_bounds[dim1]:complex_x, + grid.min_bounds[dim2]:grid.max_bounds[dim2]:complex_y] + + my_V = V[tuple(idx)] + + if (my_V > 0.0).all(): + print("Implicit surface will not be shown since all values are positive ") + if (my_V < 0.0).all(): + print("Implicit surface will not be shown since all values are negative ") + + print("Plotting beautiful 2D plots. Please wait\n") + fig = go.Figure(data=go.Contour( + x=mg_X.flatten(), + y=mg_Y.flatten(), + z=my_V.flatten(), + zmin=0.0, + ncontours=1, + contours_coloring='none', # former: lines + name="Reachable Set", # zero level + line_width=1.5, + line_color='magenta', + zmax=0.0, + ), layout=go.Layout(plot_bgcolor='rgba(0,0,0,0)')) # ,paper_bgcolor='rgba(0,0,0,0)' + + fig.show() + print("Please check the plot on your browser.") + +def hj_plot(val_func, grid, steer_idx, vel_idx, time_idx): + po = PlotOptions(do_plot=True, + plot_type="3d_plot", + plotDims=[0,1, 2], + slicesCut=[steer_idx, vel_idx]) + plot_isosurface(grid, val_func[:, :, :, :, :, time_idx], plot_option = po) + + +def xy_plot(val_func, grid, heading_idx, steer_idx, vel_idx, time_idx, cmap="Purples"): + values = deepcopy(val_func[:, :, heading_idx, steer_idx, vel_idx, time_idx]) + values[values>0.0] = float("nan") + values = -values + plt.xlabel("x [m]") + plt.ylabel("y [m]") + plt.gca().invert_yaxis() + plt.imshow(values, cmap=cmap, alpha=1) \ No newline at end of file diff --git a/odp/plot_scripts/extract_ROV_4D.py b/odp/plot_scripts/extract_ROV_4D.py deleted file mode 100644 index 7e826e50..00000000 --- a/odp/plot_scripts/extract_ROV_4D.py +++ /dev/null @@ -1,12 +0,0 @@ -import numpy as np -import scipy.io as sio - -for i in range(1, 101): - fileName = '/local-scratch/ROV_6d_TEB/V_value_{:d}'.format(i) - fileRead = sio.loadmat(fileName) - V = fileRead['V_array'] - V = np.amax(V, axis = (2,3)) - print("Saving file {:d}".format(i)) - sio.savemat('/local-scratch/ROV_4D_TEB/V_value_{:d}.mat'.format(i), {'V_array': V}) - -print('Finished converting') diff --git a/odp/plot_scripts/extract_ROV_4D.py~ b/odp/plot_scripts/extract_ROV_4D.py~ deleted file mode 100644 index 6ad03ffe..00000000 --- a/odp/plot_scripts/extract_ROV_4D.py~ +++ /dev/null @@ -1,2 +0,0 @@ -import numpy as np -import scipy.io as sio diff --git a/odp/plot_scripts/plot_ROV_6D.py b/odp/plot_scripts/plot_ROV_6D.py deleted file mode 100644 index 1b8ea597..00000000 --- a/odp/plot_scripts/plot_ROV_6D.py +++ /dev/null @@ -1,84 +0,0 @@ -import scipy.io as sio -import numpy as np - -import matplotlib.pyplot as plt - -file_read1 = sio.loadmat('/local-scratch/ROV_6d_TEB/V_value_100.mat') -""" -V = file_read1['V_array'] -V = np.amax(V, axis=(2,3,4,5)) - - -print("Read t = 20 array") -print(V.shape) -print("Getting maximum values") -# plotting preparation -x_alpha = np.linspace(-5.0, 5.0, num = 25) -z_alpha = np.linspace(-5.0, 5.0, num = 25) -X, Y = np.meshgrid(x_alpha, z_alpha) - -fig = plt.figure(figsize = (6,5)) -left, bottom, width, height = 0.1, 0.1, 0.8, 0.8 -ax = fig.add_axes([left, bottom, width, height]) - -cp = ax.contourf(X, Y, V) -plt.colorbar(cp) - -ax.set_xlabel('x_alpha') -ax.set_ylabel('z_alpha') -#plt.show() -fig.savefig('max_at_t = {:d}.png'.format(10))""" -count = 9 -for i in [7]: - for j in [7, 19]: - for k in [7, 19]: - for l in [10, 20]: - count += 1 - V = file_read1['V_array'] - V = V[:, :, i, j, k, l] - - # plotting preparation - x_alpha = np.linspace(-5.0, 5.0, num = 25) - z_alpha = np.linspace(-5.0, 5.0, num = 25) - X, Y = np.meshgrid(x_alpha, z_alpha) - - fig = plt.figure(figsize = (6,5)) - left, bottom, width, height = 0.1, 0.1, 0.8, 0.8 - ax = fig.add_axes([left, bottom, width, height]) - - cp = ax.contourf(X, Y, V) - plt.colorbar(cp) - if l == 10: - val4 = 6 - elif l == 15: - val4 = 8 - elif l == 20: - val4 = 10 - - if k == 7: - val3 = -2.5 - elif k == 12: - val3 = 0 - elif k == 19: - val3 = 2.5 - - if j == 7: - val2 = -0.35 - elif j == 19: - val2 = 0.35 - elif j == 12: - val2 = 0.0 - if i == 7: - val1 = -0.25 - elif i == 19: - val1 = 0.25 - elif i == 12: - val1 = 0.0 - #ax.clabel(cp, inline= True, fontsize=10) - ax.set_title('Distances at t = 20s, u_r = {:2f}, w_r = {:2f}, x, = {:2f}, z = {:2f}'.format(val1, val2, val3, val4)) - ax.set_xlabel('x_alpha') - ax.set_ylabel('z_alpha') - #plt.show() - print("Saving plots") - fig.savefig('plot{:d}.png'.format(count)) - diff --git a/odp/plot_scripts/plot_ROV_6D.py~ b/odp/plot_scripts/plot_ROV_6D.py~ deleted file mode 100644 index 04437385..00000000 --- a/odp/plot_scripts/plot_ROV_6D.py~ +++ /dev/null @@ -1,57 +0,0 @@ -import scipy.io as sio -import numpy as np - -import matplotlib.pyplot as plt - -file_read1 = sio.loadmat('/local-scratch/ROV_6d_TEB/V_value_50.mat') - -V = file_read1['V_array'] - -print("Read t = 20 array") -print(V.shape) -print("Getting maximum values") -count =0 -for i in [7, 19]: - for j in [7, 19]: - for k in [7, 19]: - for l in [10, 20]: - count += 1 - V = file_read1['V_array'] - V = V[:, :, i, j, k, l] - - # plotting preparation - x_alpha = np.linspace(-5.0, 5.0, num = 25) - z_alpha = np.linspace(-5.0, 5.0, num = 25) - X, Y = np.meshgrid(x_alpha, z_alpha) - - fig = plt.figure(figsize = (6,5)) - left, bottom, width, height = 0.1, 0.1, 0.8, 0.8 - ax = fig.add_axes([left, bottom, width, height]) - - cp = ax.contourf(X, Y, V) - plt.colorbar(cp) - if l == 10: - val4 = 6 - else: - val4 = 10 - - if k == 7: - val3 = -2.5 - else: - val3 = 2.5 - if j == 7: - val2 = -0.35 - else: - val2 = 0.35 - if i == 7: - val1 = -0.25 - else: - val1 = 0.25 - - #ax.clabel(cp, inline= True, fontsize=10) - ax.set_title('Distances at t = 10s, u_r = {:2f}, w_r = {:2f}, x, = {:2f}, z = {:2f}'.format(val1, val2, val3, val4)) - ax.set_xlabel('x_alpha') - ax.set_ylabel('z_alpha') - #plt.show() - print("Saving plots") - fig.savefig('plot2{:d}.png'.format(count)) diff --git a/odp/plot_scripts/results_plotting.py b/odp/plot_scripts/results_plotting.py deleted file mode 100644 index ccfa649a..00000000 --- a/odp/plot_scripts/results_plotting.py +++ /dev/null @@ -1,26 +0,0 @@ -import numpy as np -import matplotlib.pyplot as plt - - -# Read files -f = open("para_opt_res.txt", "r") - - -#fig = plt.figure() - -for k in [1,2,4,5,10]: - for j in [1,2,4,5,10]: - result = [] - for i in [1,2,4,5,10]: - value = f.readline() - result.append(float(value)) - plt.bar([1,2,4,5,10], result, align='center', alpha=0.5) - print(result) - plt.xlabel('i split ratio') - plt.ylabel('time') - plt.ylim(ymax=0.01) - plt.title('k split ratio = ' + str(k) + ', j split ratio = ' + str(j)) - plt.xticks([1,2,4,5,10]) - file_name = "k" + str(k) + "_j" + str(j) + ".png" - plt.savefig(file_name) - plt.clf() diff --git a/odp/Shapes/ShapesFunctions.py b/odp/shapes.py similarity index 51% rename from odp/Shapes/ShapesFunctions.py rename to odp/shapes.py index e0fff7f8..335eaffd 100644 --- a/odp/Shapes/ShapesFunctions.py +++ b/odp/shapes.py @@ -1,45 +1,28 @@ import numpy as np +from .grid import Grid -def CylinderShape(grid, ignore_dims, center, radius): +def cylinder(grid: Grid, center, axes, radius): """Creates an axis align cylinder implicit surface function Args: grid (Grid): Grid object - ignore_dims (List) : List specifing axis where cylindar is aligned (0-indexed) - center (List) : List specifying the center of cylinder + ignore_dims (List): List specifing axis where cylinder is aligned (0-indexed) + center (List): List specifying the center of cylinder radius (float): Radius of cylinder Returns: np.ndarray: implicit surface function of the cylinder """ - data = np.zeros(grid.pts_each_dim) - for i in range(grid.dims): - if i not in ignore_dims: + data = np.zeros(grid.shape) + for i in range(grid.ndims): + if i not in axes: # This works because of broadcasting data = data + np.power(grid.vs[i] - center[i], 2) data = np.sqrt(data) - radius return data -# Range is a list of list of ranges -# def Rectangle4D(grid, range): -# data = np.zeros(grid.pts_each_dim) -# -# for i0 in (0, grid.pts_each_dim[0]): -# for i1 in (0, grid.pts_each_dim[1]): -# for i2 in (0, grid.pts_each_dim[2]): -# for i3 in (0, grid.pts_each_dim[3]): -# x0 = grid.xs[i0] -# x1 = grid.xs[i1] -# x2 = grid.xs[i2] -# x3 = grid.xs[i3] -# range_list = [-x0 + range[0][0], x0 - range[0][1], -# -x1 + range[1][0], x1 - range[1][1], -# -x2 + range[2][0], x2 - range[2][1], -# -x3 + range[3][0], x3 - range[3][1]] -# data[i0, i1, i2, i3] = min(range_list) -# return data - -def ShapeRectangle(grid, target_min, target_max): + +def rectangle(grid: Grid, target_min, target_max): data = np.maximum(grid.vs[0] - target_max[0], -grid.vs[0] + target_min[0]) for i in range(grid.dims): @@ -48,48 +31,50 @@ def ShapeRectangle(grid, target_min, target_max): return data -def Rect_Around_Point(grid, target_point): - return ShapeRectangle(grid, target_point - 1.5 * grid.dx, target_point + 1.5 * grid.dx) +def point(grid: Grid, target_point): + return rectangle(grid, target_point - 1.5 * grid.dx, target_point + 1.5 * grid.dx) -def Lower_Half_Space(grid, dim, value): + +def lower_half_space(grid: Grid, axis, value): """Creates an axis aligned lower half space Args: grid (Grid): Grid object - dim (int): Dimension of the half space (0-indexed) + axis (int): Dimension of the half space (0-indexed) value (float): Used in the implicit surface function for V < value Returns: np.ndarray: implicit surface function of the lower half space of size grid.pts_each_dim """ - data = np.zeros(grid.pts_each_dim) - for i in range(grid.dims): - if i == dim: + data = np.zeros(grid.shape) + for i in range(grid.ndims): + if i == axis: data += grid.vs[i] - value return data -def Upper_Half_Space(grid, dim, value): +def upper_half_space(grid: Grid, axis, value): """Creates an axis aligned upper half space Args: grid (Grid): Grid object - dim (int): Dimension of the half space (0-indexed) + axis (int): Dimension of the half space (0-indexed) value (float): Used in the implicit surface function for V > value Returns: np.ndarray: implicit surface function of the lower half space of size grid.pts_each_dim """ - data = np.zeros(grid.pts_each_dim) - for i in range(grid.dims): - if i == dim: + data = np.zeros(grid.shape) + for i in range(grid.ndims): + if i == axis: data += -grid.vs[i] + value return data -def Union(shape1, shape2): + +def union(shape, *shapes): """ Calculates the union of two shapes Args: @@ -99,9 +84,13 @@ def Union(shape1, shape2): Returns: np.ndarray: the element-wise minimum of two shapes """ - return np.minimum(shape1, shape2) + result = shape + for shape in shapes: + result = np.minimum(result, shape) + return result -def Intersection(shape1, shape2): + +def intersection(shape, *shapes): """ Calculates the intersection of two shapes Args: @@ -111,4 +100,8 @@ def Intersection(shape1, shape2): Returns: np.ndarray: the element-wise minimum of two shapes """ - return np.maximum(shape1, shape2) \ No newline at end of file + result = shape + for shape in shapes: + result = np.maximum(result, shape) + return result + diff --git a/odp/solver.py b/odp/solver.py index 5e51e248..b1b59005 100644 --- a/odp/solver.py +++ b/odp/solver.py @@ -2,360 +2,361 @@ import numpy as np import time -from odp.Plots import plot_isosurface - -# Backward reachable set computation library -from odp.computeGraphs import graph_3D, graph_4D, graph_5D, graph_6D -from odp.TimeToReach import TTR_3D, TTR_4D, TTR_5D - -# Value Iteration library -from odp.valueIteration import value_iteration_3D, value_iteration_4D, value_iteration_5D, value_iteration_6D - -def solveValueIteration(MDP_obj): - print("Welcome to optimized_dp \n") - # Initialize the HCL environment - hcl.init() - hcl.config.init_dtype = hcl.Float(32) - - ########################################## INITIALIZE ########################################## - - # Convert the python array to hcl type array - V_opt = hcl.asarray(np.zeros(MDP_obj._ptsEachDim)) - intermeds = hcl.asarray(np.ones(MDP_obj._actions.shape[0])) - trans = hcl.asarray(MDP_obj._trans) - gamma = hcl.asarray(MDP_obj._gamma) - epsilon = hcl.asarray(MDP_obj._epsilon) - count = hcl.asarray(np.zeros(1)) - maxIters = hcl.asarray(MDP_obj._maxIters) - actions = hcl.asarray(MDP_obj._actions) - bounds = hcl.asarray(MDP_obj._bounds) - goal = hcl.asarray(MDP_obj._goal) - ptsEachDim = hcl.asarray(MDP_obj._ptsEachDim) - sVals = hcl.asarray(np.zeros([MDP_obj._bounds.shape[0]])) - iVals = hcl.asarray(np.zeros([MDP_obj._bounds.shape[0]])) - interpV = hcl.asarray(np.zeros([1])) - useNN = hcl.asarray(MDP_obj._useNN) - - print(MDP_obj._bounds.shape[0]) - print(np.zeros([MDP_obj._bounds.shape[0]])) - if MDP_obj._bounds.shape[0] == 3: - fillVal = hcl.asarray(MDP_obj._fillVal) - f = value_iteration_3D(MDP_obj) - if MDP_obj._bounds.shape[0] == 4: - f = value_iteration_4D(MDP_obj) - if MDP_obj._bounds.shape[0] == 5: - f = value_iteration_5D(MDP_obj) - if MDP_obj._bounds.shape[0] == 6: - f = value_iteration_6D(MDP_obj) - - # Build the graph and use the executable - # Now use the executable - t_s = time.time() - if MDP_obj._bounds.shape[0] == 3: - iter = 0 - resweep = 1 - while iter < MDP_obj._maxIters and resweep == 1: - reSweep = hcl.asarray(np.zeros([1])) - print("Currently at iteration {}".format(iter)) - f(V_opt, actions, intermeds, trans, interpV, gamma, epsilon, reSweep, iVals, sVals, bounds, goal, ptsEachDim, count, - maxIters, useNN, fillVal) - iter += 1 - resweep = reSweep.asnumpy()[0] - else: - f(V_opt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, - maxIters, useNN) - t_e = time.time() - - V = V_opt.asnumpy() - c = count.asnumpy() - print("Finished in ", int(c[0]), " iterations") - print("Took ", t_e - t_s, " seconds") - - # # Write results to file - # if (MDP_obj.dir_path): - # dir_path = MDP_obj.dir_path - # else: - # dir_path = "./hcl_value_matrix_test/" - # - # if (MDP_obj.file_name): - # file_name = MDP_obj.file_name - # else: - # file_name = "hcl_value_iteration_" + str(int(c[0])) + "_iterations_by" + ( - # "_Interpolation" if MDP_obj._useNN[0] == 0 else "_NN") - # MDP_obj.writeResults(V, dir_path, file_name, just_values=True) - return V - -def HJSolver(dynamics_obj, grid, multiple_value, tau, compMethod, - plot_option, saveAllTimeSteps=False, - accuracy="low", untilConvergent=False, epsilon=2e-3): - - print("Welcome to optimized_dp \n") - if type(multiple_value) == list: - # We have both goal and obstacle set - target = multiple_value[0] # Target set - constraint = multiple_value[1] # Obstacle set - else: - target = multiple_value - constraint = None +from . import math as hcl_math +from .derivatives import spatial_derivative +from .grid import Grid +from .shapes import * + +class Solver: + + debug = False + interactive = False + + accuracy = 'low' - hcl.init() - hcl.config.init_dtype = hcl.Float(32) + _executable = None + + def __init__(self, grid, model, *, + interactive=True, + debug=False, + accuracy='low', + dtype=hcl.Float()): + + # Solver options + self.interactive = interactive + self.debug = debug + + if self.interactive: + print("== Welcome to optimized_dp ==") + + # Initialize the HCL environment + hcl.init(hcl.Float(32)) + + self.accuracy = accuracy + assert self.accuracy == 'low', 'This modification to odp only supports low accuracy' + + self.dtype = dtype + + self.grid = grid + self.model = model + + self.state_shape = (self.model.state_dims,) + self.ctrl_shape = (self.model.ctrl_dims,) + self.dstb_shape = (self.model.dstb_dims,) + + self.build() + + def __call__(self, *args): + """ + Run the solver. + + This method is intended to be overloaded. + """ + + # Run the executable + self._executable(*args) + + def build(self): + + if self.interactive: + print('Building...') + + vf = hcl.placeholder(self.grid.shape, name="vf", dtype=self.dtype) + t = hcl.placeholder((2,), name="t", dtype=self.dtype) + xs = [hcl.placeholder((axlen,), dtype=self.dtype, name=f'x_{i}') + for i, axlen in enumerate(self.grid.shape)] + args = [vf, t, *xs] - ################# INITIALIZE DATA TO BE INPUT INTO EXECUTABLE ########################## + if self.debug: + h = hcl.placeholder(self.grid.shape, name='h', dtype=self.dtype) + args = [h] + args - print("Initializing\n") + # lambda is necessary so that hcl can modify properties of the function object + program = lambda *args: self.entrypoint(*args) + self._sched = hcl.create_schedule(args, program) - if constraint is None: - print("No obstacles set !") - init_value = target - else: - print("Obstacles set exists !") - constraint_dim = constraint.ndim + if not self.debug: - # Time-varying obstacle sets - if constraint_dim > grid.dims: - constraint_i = constraint[...,0] + # Accessing the hamiltonian and dissipation stage + stage_hamiltonian = program.Hamiltonian + stage_dissipation = program.Dissipation + + # Thread parallelize hamiltonian and dissipation computation + self._sched[stage_hamiltonian].parallel(stage_hamiltonian.axis[0]) + self._sched[stage_dissipation].parallel(stage_dissipation.axis[0]) + + self._executable = hcl.build(self._sched) + + if self.interactive: + print(f'> {type(self).__name__} built!\n') + + def entrypoint(self, *args): + + if self.debug: + h_dbg, vf, t, *xs = args else: - # Time-invariant obstacle set - constraint_i = constraint - - init_value = np.maximum(target, -constraint_i) - - # Tensors input to our computation graph - V_0 = hcl.asarray(init_value) - V_1 = hcl.asarray(np.zeros(tuple(grid.pts_each_dim))) - - # Check which target set or initial value set - if compMethod["TargetSetMode"] != "minVWithVTarget" and compMethod["TargetSetMode"] != "maxVWithVTarget": - l0 = hcl.asarray(init_value) - else: - l0 = hcl.asarray(target) - - # For debugging purposes - probe = hcl.asarray(np.zeros(tuple(grid.pts_each_dim))) - - # Array for each state values - list_x1 = np.reshape(grid.vs[0], grid.pts_each_dim[0]) - list_x2 = np.reshape(grid.vs[1], grid.pts_each_dim[1]) - list_x3 = np.reshape(grid.vs[2], grid.pts_each_dim[2]) - if grid.dims >= 4: - list_x4 = np.reshape(grid.vs[3], grid.pts_each_dim[3]) - if grid.dims >= 5: - list_x5 = np.reshape(grid.vs[4], grid.pts_each_dim[4]) - if grid.dims >= 6: - list_x6 = np.reshape(grid.vs[5], grid.pts_each_dim[5]) - - # Convert state arrays to hcl array type - list_x1 = hcl.asarray(list_x1) - list_x2 = hcl.asarray(list_x2) - list_x3 = hcl.asarray(list_x3) - if grid.dims >= 4: - list_x4 = hcl.asarray(list_x4) - if grid.dims >= 5: - list_x5 = hcl.asarray(list_x5) - if grid.dims >= 6: - list_x6 = hcl.asarray(list_x6) - - # Get executable, obstacle check intial value function - if grid.dims == 3: - solve_pde = graph_3D(dynamics_obj, grid, compMethod["TargetSetMode"], accuracy) - - if grid.dims == 4: - solve_pde = graph_4D(dynamics_obj, grid, compMethod["TargetSetMode"], accuracy) - - if grid.dims == 5: - solve_pde = graph_5D(dynamics_obj, grid, compMethod["TargetSetMode"], accuracy) - - if grid.dims == 6: - solve_pde = graph_6D(dynamics_obj, grid, compMethod["TargetSetMode"], accuracy) - - """ Be careful, for high-dimensional array (5D or higher), saving value arrays at all the time steps may - cause your computer to run out of memory """ - if saveAllTimeSteps is True: - valfuncs = np.zeros(np.insert(tuple(grid.pts_each_dim), grid.dims, len(tau))) - valfuncs[..., -1 ] = V_0.asnumpy() - print(valfuncs.shape) - - - ################ USE THE EXECUTABLE ############ - # Variables used for timing - execution_time = 0 - iter = 0 - tNow = tau[0] - print("Started running\n") - - # Backward reachable set/tube will be computed over the specified time horizon - # Or until convergent ( which ever happens first ) - for i in range (1, len(tau)): - #tNow = tau[i-1] - t_minh= hcl.asarray(np.array((tNow, tau[i]))) + vf, t, *xs = args + + # Initialize intermediate tensors + dv_diff = hcl.compute(self.grid.shape + self.state_shape, lambda *_: 0, name='dv_diff') + dv_max = hcl.compute(self.state_shape, lambda _: -1e9, name='dv_max') + dv_min = hcl.compute(self.state_shape, lambda _: +1e9, name='dv_min') + max_alpha = hcl.compute(self.state_shape, lambda _: -1e9, name='max_alpha') + + # Initialize the Hamiltonian tensor + h = hcl.compute(self.grid.shape, lambda *idxs: vf[idxs], name='h') + + # Compute Hamiltonian term, max and min derivative + self.hamiltonian_stage(h, vf, t, xs, + dv_min=dv_min, dv_max=dv_max, dv_diff=dv_diff) + + if self.debug: + hcl.update(h_dbg, lambda *idxs: h[idxs]) + + # Compute artificial dissipation + self.dissipation_stage(h, t, xs, + dv_min=dv_min, dv_max=dv_max, dv_diff=dv_diff, + max_alpha=max_alpha) + + # Compute integration time step + delta_t = hcl.compute((1,), lambda _: self.time_step(t, max_alpha=max_alpha)) + + # First order Runge-Kutta (RK) integrator + hcl.update(vf, lambda *idxs: vf[idxs] + h[idxs] * delta_t.v) + + + def hamiltonian_stage(self, h, vf, t, xs, *, + dv_min, dv_max, dv_diff): + """Calculate Hamiltonian for every grid point in V_init""" + + def body(*idxs): + + u = hcl.compute(self.ctrl_shape, lambda _: 0, name='u') + d = hcl.compute(self.dstb_shape, lambda _: 0, name='d') + x = hcl.compute(self.state_shape, lambda _: 0, name='x') + dx = hcl.compute(self.state_shape, lambda _: 0, name='dx') + dv = hcl.compute(self.state_shape, lambda _: 0, name='dv_avg') + + # x_n = X_{n,i} where + # x = `x` The state tensor, + # X = `xs` The list of state space arrays, + # n = Current state dimension (in updating x), + # i = `idxs[n]` Index of current grid point in dimension `n`, + for n, i in enumerate(idxs): + x[n] = xs[n][i] + + for axis in range(self.grid.ndims): + + left = hcl.scalar(0, 'left') + right = hcl.scalar(0, 'right') + + # Compute the spatial derivative of the value function (dV/dx) + spatial_derivative(left, right, axis, vf, self.grid, *idxs) + + # do for both left/right derivatives + for deriv in (left, right): + with hcl.if_(deriv.v < dv_min[axis]): + dv_min[axis] = deriv.v + with hcl.if_(dv_max[axis] < deriv.v): + dv_max[axis] = deriv.v + + dv[axis] = (left.v + right.v) / 2 + + dv_diff[idxs + (axis,)] = right.v - left.v + + # Use the model's methods to solve optimal control + self.model.opt_ctrl(u, dv, t, x) + self.model.opt_dstb(d, dv, t, x) + + # Calculate dynamical rates of changes + self.model.dynamics(dx, t, x, u, d) + + # Calculate Hamiltonian terms + h[idxs] = -hcl_math.dot(dv, dx) + + hcl.mutate(vf.shape, body, name='Hamiltonian') + + def dissipation_stage(self, h, t, xs, *, + dv_min, dv_max, dv_diff, + max_alpha): + """Calculate the dissipation""" + + def body(*idxs): + + x = hcl.compute(self.state_shape, lambda _: 0, name='x') + + # Each has a combination of lower/upper bound on control and disturbance + dx_ll = hcl.compute(self.state_shape, lambda _: 0, name='dx_ll') + dx_lu = hcl.compute(self.state_shape, lambda _: 0, name='dx_lu') + dx_ul = hcl.compute(self.state_shape, lambda _: 0, name='dx_ul') + dx_uu = hcl.compute(self.state_shape, lambda _: 0, name='dx_uu') + + lower_opt_ctrl = hcl.compute(self.ctrl_shape, lambda _: 0, name='lower_opt_ctrl') + upper_opt_ctrl = hcl.compute(self.ctrl_shape, lambda _: 0, name='upper_opt_ctrl') + lower_opt_dstb = hcl.compute(self.dstb_shape, lambda _: 0, name='lower_opt_dstb') + upper_opt_dstb = hcl.compute(self.dstb_shape, lambda _: 0, name='upper_opt_dstb') + + for n, i in enumerate(idxs): + x[n] = xs[n][i] + + # Find LOWER BOUND optimal disturbance + self.model.opt_dstb(lower_opt_dstb, dv_min, t, x) + + # Find UPPER BOUND optimal disturbance + self.model.opt_dstb(upper_opt_dstb, dv_max, t, x) + + # Find LOWER BOUND optimal control + self.model.opt_ctrl(lower_opt_ctrl, dv_min, t, x) + + # Find UPPER BOUND optimal control + self.model.opt_ctrl(upper_opt_ctrl, dv_max, t, x) + + # Find magnitude of rates of changes + self.model.dynamics(dx_ll, t, x, lower_opt_ctrl, lower_opt_dstb) + hcl.update(dx_ll, lambda i: hcl_math.abs(dx_ll[i])) + + self.model.dynamics(dx_lu, t, x, lower_opt_ctrl, upper_opt_dstb) + hcl.update(dx_lu, lambda i: hcl_math.abs(dx_lu[i])) + + self.model.dynamics(dx_ul, t, x, upper_opt_ctrl, lower_opt_dstb) + hcl.update(dx_ul, lambda i: hcl_math.abs(dx_ul[i])) + + self.model.dynamics(dx_uu, t, x, upper_opt_ctrl, upper_opt_dstb) + hcl.update(dx_uu, lambda i: hcl_math.abs(dx_uu[i])) + + # Calulate alpha + alpha = hcl.compute(self.state_shape, + lambda i: hcl_math.max(dx_ll[i], dx_lu[i], + dx_ul[i], dx_uu[i]), + name='alpha') + + hcl.update(max_alpha, lambda i: hcl_math.max(max_alpha[i], alpha[i])) + + # Finally we update the hamiltonian + # dv_diff has shape x . Here we use dv_diff at the current grid point. + dv_diff_here = hcl.compute(self.state_shape, lambda n: dv_diff[idxs + (n,)]) + dissipation_v = hcl_math.dot(dv_diff_here, alpha) / 2 + h[idxs] = -(h[idxs] - dissipation_v) + + hcl.mutate(h.shape, body, name='Dissipation') + + def time_step(self, t, *, + max_alpha): + + step_bound = hcl.scalar(0, 'step_bound') + + tmp = hcl.scalar(0) + for i, res in enumerate(self.grid.dx): + tmp.v += max_alpha[i] / res + step_bound.v = 0.8 / tmp.v + + with hcl.if_(t[1] - t[0] < step_bound.v): + step_bound.v = t[1] - t[0] + + t[0] += step_bound.v + + return step_bound.v + + +class HJSolver(Solver): + + def __init__(self, grid, tau, model, **kwargs): - # taking obstacle at each timestep - if "ObstacleSetMode" in compMethod and constraint_dim > grid.dims: - constraint_i = constraint[...,i] - - while tNow <= tau[i] - 1e-4: - prev_arr = V_0.asnumpy() - # Start timing - iter += 1 - start = time.time() - - # Run the execution and pass input into graph - if grid.dims == 3: - solve_pde(V_1, V_0, list_x1, list_x2, list_x3, t_minh, l0) - if grid.dims == 4: - solve_pde(V_1, V_0, list_x1, list_x2, list_x3, list_x4, t_minh, l0, probe) - if grid.dims == 5: - solve_pde(V_1, V_0, list_x1, list_x2, list_x3, list_x4, list_x5 ,t_minh, l0) - if grid.dims == 6: - solve_pde(V_1, V_0, list_x1, list_x2, list_x3, list_x4, list_x5, list_x6, t_minh, l0) - - tNow = t_minh.asnumpy()[0] - - # Calculate computation time - execution_time += time.time() - start - - # If ObstacleSetMode is specified by user - if "ObstacleSetMode" in compMethod: - if compMethod["ObstacleSetMode"] == "maxVWithObstacle": - tmp_val = np.maximum(V_0.asnumpy(), -constraint_i) - elif compMethod["ObstacleSetMode"] == "minVWithObstacle": - tmp_val = np.minimum(V_0.asnumpy(), -constraint_i) - # Update final result - V_1 = hcl.asarray(tmp_val) - # Update input for next iteration - V_0 = hcl.asarray(tmp_val) - - # Some information printin - print(t_minh) - print("Computational time to integrate (s): {:.5f}".format(time.time() - start)) - - if untilConvergent is True: - # Compare difference between V_{t-1} and V_{t} and choose the max changes - diff = np.amax(np.abs(V_1.asnumpy() - prev_arr)) - print("Max difference between V_old and V_new : {:.5f}".format(diff)) - if diff < epsilon: - print("Result converged ! Exiting the compute loop. Have a good day.") - break - else: # if it didn't break because of convergent condition - if saveAllTimeSteps is True: - valfuncs[..., -1-i] = V_1.asnumpy() - continue - break # only if convergent condition is achieved - - - # Time info printing - print("Total kernel time (s): {:.5f}".format(execution_time)) - print("Finished solving\n") - - ##################### PLOTTING ##################### - if plot_option.do_plot : - # Only plots last value array for now - plot_isosurface(grid, V_1.asnumpy(), plot_option) - - if saveAllTimeSteps is True: - valfuncs[..., 0] = V_1.asnumpy() - return valfuncs - - return V_1.asnumpy() - -def TTRSolver(dynamics_obj, grid, init_value, epsilon, plot_option): - print("Welcome to optimized_dp \n") - ################# INITIALIZE DATA TO BE INPUT INTO EXECUTABLE ########################## - - print("Initializing\n") - hcl.init() - hcl.config.init_dtype = hcl.Float(32) - - # Convert initial distance value function to initial time-to-reach value function - init_value[init_value < 0] = 0 - init_value[init_value > 0] = 1000 - V_0 = hcl.asarray(init_value) - prev_val = np.zeros(init_value.shape) - - # Re-shape states vector - list_x1 = np.reshape(grid.vs[0], grid.pts_each_dim[0]) - list_x2 = np.reshape(grid.vs[1], grid.pts_each_dim[1]) - list_x3 = np.reshape(grid.vs[2], grid.pts_each_dim[2]) - if grid.dims >= 4: - list_x4 = np.reshape(grid.vs[3], grid.pts_each_dim[3]) - if grid.dims >= 5: - list_x5 = np.reshape(grid.vs[4], grid.pts_each_dim[4]) - if grid.dims >= 6: - list_x6 = np.reshape(grid.vs[5], grid.pts_each_dim[5]) - - # Convert states vector to hcl array type - list_x1 = hcl.asarray(list_x1) - list_x2 = hcl.asarray(list_x2) - list_x3 = hcl.asarray(list_x3) - if grid.dims >= 4: - list_x4 = hcl.asarray(list_x4) - if grid.dims >= 5: - list_x5 = hcl.asarray(list_x5) - if grid.dims >= 6: - list_x6 = hcl.asarray(list_x6) - - # Get executable - - if grid.dims == 3: - solve_TTR = TTR_3D(dynamics_obj, grid) - if grid.dims == 4: - solve_TTR = TTR_4D(dynamics_obj, grid) - if grid.dims == 5: - solve_TTR = TTR_5D(dynamics_obj, grid) - if grid.dims == 6: - solve_TTR = TTR_6D(dynamics_obj, grid) - print("Got Executable\n") - - # Print out code for different backend - # print(solve_pde) - - ################ USE THE EXECUTABLE ############ - error = 10000 - count = 0 - start = time.time() - while error > epsilon: - print("Iteration: {} Error: {}".format(count, error)) - count += 1 - if grid.dims == 3: - solve_TTR(V_0, list_x1, list_x2, list_x3) - if grid.dims == 4: - solve_TTR(V_0, list_x1, list_x2, list_x3, list_x4) - if grid.dims == 5: - solve_TTR(V_0, list_x1, list_x2, list_x3, list_x4, list_x5) - if grid.dims == 6: - solve_TTR(V_0, list_x1, list_x2, list_x3, list_x4, list_x5, list_x6 ) - - error = np.max(np.abs(prev_val - V_0.asnumpy())) - prev_val = V_0.asnumpy() - print("Total TTR computation time (s): {:.5f}".format(time.time() - start)) - print("Finished solving\n") - - ##################### PLOTTING ##################### - plot_isosurface(grid, V_0.asnumpy(), plot_option) - return V_0.asnumpy() - -def computeSpatDerivArray(grid, V, deriv_dim, accuracy="low"): - # Return a tensor same size as V that contains spatial derivatives at every state in V - hcl.init() - hcl.config.init_dtype = hcl.Float(32) - - # Need to make sure that value array has the same size as grid - assert list(V.shape) == list(grid.pts_each_dim) - - V_0 = hcl.asarray(V) - spatial_deriv = hcl.asarray(np.zeros(tuple(grid.pts_each_dim))) - - # Get executable, obstacle check intial value function - if grid.dims == 3: - compute_SpatDeriv = graph_3D(None, grid, "None", accuracy, - generate_SpatDeriv=True, deriv_dim=deriv_dim) - if grid.dims == 4: - compute_SpatDeriv = graph_4D(None, grid, "None", accuracy, - generate_SpatDeriv=True, deriv_dim=deriv_dim) - if grid.dims == 5: - compute_SpatDeriv = graph_5D(None, grid, "None", accuracy, - generate_SpatDeriv=True, deriv_dim=deriv_dim) - - compute_SpatDeriv(V_0, spatial_deriv) - return spatial_deriv.asnumpy() + + super().__init__(grid, model, **kwargs) + + def __call__(self, tau, *, + target, target_mode='min', + constraint=None, constraint_mode='max'): + + target_invariant = target.shape == self.grid.shape + assert target_invariant or target.shape == self.grid.shape + tau.shape + assert target_mode in ('max', 'min') + + if constraint is not None: + constraint_invariant = constraint.shape == self.grid.shape + assert constraint_invariant or constraint.shape == self.grid.shape + tau.shape + assert constraint_mode in ('max', 'min') + + # Tensor input to our computation graph + vf = target if target_invariant else target[..., -1] + t = np.flip(tau) + xs = [ax.flatten() for ax in self.grid.vs] + + # Extend over time axis + out = np.zeros(vf.shape + (len(t),)) + out[..., -1] = vf + + ################ USE THE EXECUTABLE ############ + # Variables used for timing + execution_time = 0 + now = t[-1] + + if self.interactive: + print("Running...") + line_length = 0 + + # Backward reachable set/tube will be computed over the specified time horizon + # Or until convergent ( which ever happens first ) + for i in reversed(range(0, len(t)-1)): + + vf = out[..., i+1].copy() + + pde_args = [vf, np.array([now, t[i]]), *xs] + pde_args = list(map(hcl.asarray, pde_args)) + + if self.debug: + h = hcl.asarray(np.zeros_like(vf)) + pde_args = [h] + pde_args + + while now <= t[i] - 1e-4: + + # Start timing + start = time.time() + + # Run the execution and pass input into graph + self._executable(*pde_args) + + # End timing + end = time.time() + + # Calculate computation time + execution_time += end - start + + # Get current time from within solver + if self.debug: + now = pde_args[2].asnumpy()[0] + else: + now = pde_args[1].asnumpy()[0] + + # Some information printing + if self.interactive: + line = f"> [{execution_time:.2f}: {i}] Integration time: {end - start:.5f} s - Now: {now:.5f}" + line_length = max(line_length, len(line)) + print(line, end="\r", flush=True) + + if self.debug: + h = pde_args[0].asnumpy() + vf = pde_args[1].asnumpy() + else: + vf = pde_args[0].asnumpy() + + op = np.minimum if target_mode == 'min' else np.maximum + vf = op(vf, target) if target_invariant else op(vf, target[..., i]) + + if constraint is not None: + op = np.minimum if constraint_mode == 'min' else np.maximum + vf = op(vf, -constraint) if constraint_invariant else op(vf, -constraint[..., i]) + + out[..., i] = vf + + # Time info printing + if self.interactive: + line = f"> Total kernel time: {execution_time:.2f} s" + line = line.ljust(line_length) + print(line, end="\n\n") + + # Flip time axis so that earliest time is first + # out = np.flip(out, axis=-1) + + return out diff --git a/odp/spatialDerivatives/first_orderENO3D.py b/odp/spatialDerivatives/first_orderENO3D.py deleted file mode 100644 index 6e0990ba..00000000 --- a/odp/spatialDerivatives/first_orderENO3D.py +++ /dev/null @@ -1,113 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * - -################## 3D SPATIAL DERIVATIVE FUNCTION ################# -def spa_derivX(i, j, k, V, g): - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 0 not in g.pDim: - with hcl.if_(i == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k] + my_abs(V[i + 1, j, k] - V[i, j, k]) * my_sign(\ - V[i, j, k]) - left_deriv[0] = (V[i, j, k] - left_boundary[0]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k] - V[i, j, k]) / g.dx[0] - with hcl.elif_(i == V.shape[0] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k] + my_abs(V[i, j, k] - V[i - 1, j, k]) * my_sign( - V[i, j, k]) - left_deriv[0] = (V[i, j, k] - V[i - 1, j, k]) / g.dx[0] - right_deriv[0] = (right_boundary[0] - V[i, j, k]) / g.dx[0] - with hcl.elif_(i != 0 and i != V.shape[0] - 1): - left_deriv[0] = (V[i, j, k] - V[i - 1, j, k]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k] - V[i, j, k]) / g.dx[0] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(i == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[V.shape[0] - 1, j, k] - left_deriv[0] = (V[i, j, k] - left_boundary[0]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k] - V[i, j, k]) / g.dx[0] - with hcl.elif_(i == V.shape[0] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[0, j, k] - left_deriv[0] = (V[i, j, k] - V[i - 1, j, k]) / g.dx[0] - right_deriv[0] = (right_boundary[0] - V[i, j, k]) / g.dx[0] - with hcl.elif_(i != 0 and i != V.shape[0] - 1): - left_deriv[0] = (V[i, j, k] - V[i - 1, j, k]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k] - V[i, j, k]) / g.dx[0] - return left_deriv[0], right_deriv[0] - - -def spa_derivY(i, j, k, V, g): - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 1 not in g.pDim: - with hcl.if_(j == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k] + my_abs(V[i, j + 1, k] - V[i, j, k]) * my_sign( - V[i, j, k]) - left_deriv[0] = (V[i, j, k] - left_boundary[0]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k] - V[i, j, k]) / g.dx[1] - with hcl.elif_(j == V.shape[1] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k] + my_abs(V[i, j, k] - V[i, j - 1, k]) * my_sign( - V[i, j, k]) - left_deriv[0] = (V[i, j, k] - V[i, j - 1, k]) / g.dx[1] - right_deriv[0] = (right_boundary[0] - V[i, j, k]) / g.dx[1] - with hcl.elif_(j != 0 and j != V.shape[1] - 1): - left_deriv[0] = (V[i, j, k] - V[i, j - 1, k]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k] - V[i, j, k]) / g.dx[1] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(j == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, V.shape[1] - 1, k] - left_deriv[0] = (V[i, j, k] - left_boundary[0]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k] - V[i, j, k]) / g.dx[1] - with hcl.elif_(j == V.shape[1] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, 0, k] - left_deriv[0] = (V[i, j, k] - V[i, j - 1, k]) / g.dx[1] - right_deriv[0] = (right_boundary[0] - V[i, j, k]) / g.dx[1] - with hcl.elif_(j != 0 and j != V.shape[1] - 1): - left_deriv[0] = (V[i, j, k] - V[i, j - 1, k]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k] - V[i, j, k]) / g.dx[1] - return left_deriv[0], right_deriv[0] - - -def spa_derivT(i, j, k, V, g): - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 2 not in g.pDim: - with hcl.if_(k == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k] + my_abs(V[i, j, k + 1] - V[i, j, k]) * my_sign( - V[i, j, k]) - left_deriv[0] = (V[i, j, k] - left_boundary[0]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1] - V[i, j, k]) / g.dx[2] - with hcl.elif_(k == V.shape[2] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k] + my_abs(V[i, j, k] - V[i, j, k - 1]) * my_sign( - V[i, j, k]) - left_deriv[0] = (V[i, j, k] - V[i, j, k - 1]) / g.dx[2] - right_deriv[0] = (right_boundary[0] - V[i, j, k]) / g.dx[2] - with hcl.elif_(k != 0 and k != V.shape[2] - 1): - left_deriv[0] = (V[i, j, k] - V[i, j, k - 1]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1] - V[i, j, k]) / g.dx[2] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(k == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, V.shape[2] - 1] - left_deriv[0] = (V[i, j, k] - left_boundary[0]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1] - V[i, j, k]) / g.dx[2] - with hcl.elif_(k == V.shape[2] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, 0] - left_deriv[0] = (V[i, j, k] - V[i, j, k - 1]) / g.dx[2] - right_deriv[0] = (right_boundary[0] - V[i, j, k]) / g.dx[2] - with hcl.elif_(k != 0 and k != V.shape[2] - 1): - left_deriv[0] = (V[i, j, k] - V[i, j, k - 1]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1] - V[i, j, k]) / g.dx[2] - return left_deriv[0], right_deriv[0] \ No newline at end of file diff --git a/odp/spatialDerivatives/first_orderENO4D.py b/odp/spatialDerivatives/first_orderENO4D.py deleted file mode 100644 index fb5c9f7d..00000000 --- a/odp/spatialDerivatives/first_orderENO4D.py +++ /dev/null @@ -1,151 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * - - -################## 4D SPATIAL DERIVATIVE FUNCTION ################# - -# Calculate derivative on the first derivative # -def spa_derivX4_4d(i, j, k, l, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 3 not in g.pDim: - with hcl.if_(l == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l] + my_abs(V[i, j, k, l + 1] - V[i, j, k, l]) * my_sign( - V[i, j, k, l]) - left_deriv[0] = (V[i, j, k, l] - left_boundary[0]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1] - V[i, j, k, l]) / g.dx[3] - with hcl.elif_(l == V.shape[3] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l] + my_abs(V[i, j, k, l] - V[i, j, k, l - 1]) * my_sign( - V[i, j, k, l]) - left_deriv[0] = (V[i, j, k, l] - V[i, j, k, l - 1]) / g.dx[3] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l]) / g.dx[3] - with hcl.elif_(l != 0 and l != V.shape[3] - 1): - left_deriv[0] = (V[i, j, k, l] - V[i, j, k, l - 1]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1] - V[i, j, k, l]) / g.dx[3] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(l == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, V.shape[3] - 1] - left_deriv[0] = (V[i, j, k, l] - left_boundary[0]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1] - V[i, j, k, l]) / g.dx[3] - with hcl.elif_(l == V.shape[3] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, 0] - left_deriv[0] = (V[i, j, k , l] - V[i, j, k, l - 1]) / g.dx[3] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l]) / g.dx[3] - with hcl.elif_(l != 0 and l != V.shape[3] - 1): - left_deriv[0] = (V[i, j, k, l] - V[i, j, k, l - 1]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1] - V[i, j, k, l]) / g.dx[3] - return left_deriv[0], right_deriv[0] - - -def spa_derivX3_4d(i, j, k, l, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 2 not in g.pDim: - with hcl.if_(k == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l] + my_abs(V[i, j, k + 1, l ] - V[i, j, k, l]) * my_sign( - V[i, j, k, l]) - left_deriv[0] = (V[i, j, k, l] - left_boundary[0]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l] - V[i, j, k, l]) / g.dx[2] - with hcl.elif_(k == V.shape[2] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l] + my_abs(V[i, j, k, l] - V[i, j, k - 1, l]) * my_sign( - V[i, j, k, l]) - left_deriv[0] = (V[i, j, k, l] - V[i, j, k - 1, l]) / g.dx[2] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l]) / g.dx[2] - with hcl.elif_(k != 0 and k != V.shape[2] - 1): - left_deriv[0] = (V[i, j, k, l] - V[i, j, k - 1, l]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l] - V[i, j, k, l]) / g.dx[2] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(k == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, V.shape[2] - 1, l] - left_deriv[0] = (V[i, j, k, l] - left_boundary[0]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l] - V[i, j, k, l]) / g.dx[2] - with hcl.elif_(k == V.shape[2] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, 0, l] - left_deriv[0] = (V[i, j, k , l] - V[i, j, k - 1, l]) / g.dx[2] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l]) / g.dx[2] - with hcl.elif_(k != 0 and k != V.shape[2] - 1): - left_deriv[0] = (V[i, j, k, l] - V[i, j, k - 1, l]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l] - V[i, j, k, l]) / g.dx[2] - return left_deriv[0], right_deriv[0] - -def spa_derivX2_4d(i, j, k, l, V, g): # - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 1 not in g.pDim: - with hcl.if_(j == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l] + my_abs(V[i, j + 1, k, l] - V[i, j, k, l]) * my_sign( - V[i, j, k, l]) - left_deriv[0] = (V[i, j, k, l] - left_boundary[0]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l] - V[i, j, k, l]) / g.dx[1] - with hcl.elif_(j == V.shape[1] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l] + my_abs(V[i, j, k, l] - V[i, j - 1, k, l]) * my_sign( - V[i, j, k, l]) - left_deriv[0] = (V[i, j, k, l] - V[i, j - 1, k, l]) / g.dx[1] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l]) / g.dx[1] - with hcl.elif_(j != 0 and j != V.shape[1] - 1): - left_deriv[0] = (V[i, j, k, l] - V[i, j - 1, k, l]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l] - V[i, j, k, l]) / g.dx[1] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(j == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, V.shape[1] - 1 , k, l] - left_deriv[0] = (V[i, j, k, l] - left_boundary[0]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l] - V[i, j, k, l]) / g.dx[1] - with hcl.elif_(j == V.shape[1] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, 0, k, l] - left_deriv[0] = (V[i, j, k, l] - V[i, j - 1, k, l]) / g.dx[1] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l]) / g.dx[1] - with hcl.elif_(j != 0 and j != V.shape[1] - 1): - left_deriv[0] = (V[i, j, k, l] - V[i, j - 1, k, l]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l] - V[i, j, k, l]) / g.dx[1] - return left_deriv[0], right_deriv[0] - -def spa_derivX1_4d(i, j, k, l, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 0 not in g.pDim: - with hcl.if_(i == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l] + my_abs(V[i + 1, j, k, l] - V[i, j, k, l]) * my_sign( - V[i, j, k, l]) - left_deriv[0] = (V[i, j, k, l] - left_boundary[0]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l] - V[i, j, k, l]) / g.dx[0] - with hcl.elif_(i == V.shape[0] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l] + my_abs(V[i, j, k, l] - V[i - 1, j, k, l]) * my_sign( - V[i, j, k, l]) - left_deriv[0] = (V[i, j, k, l] - V[i - 1, j, k, l]) / g.dx[0] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l]) / g.dx[0] - with hcl.elif_(i != 0 and i != V.shape[0] - 1): - left_deriv[0] = (V[i, j, k, l] - V[i -1, j, k, l]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l] - V[i, j, k, l]) / g.dx[0] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(i == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[V.shape[0] - 1, j, k, l] - left_deriv[0] = (V[i, j, k, l] - left_boundary[0]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l] - V[i, j, k, l]) / g.dx[0] - with hcl.elif_(i == V.shape[0] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[0, j, k, l] - left_deriv[0] = (V[i, j, k, l] - V[i - 1, j, k, l]) / g.dx[0] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l]) / g.dx[0] - with hcl.elif_(i != 0 and i != V.shape[0] - 1): - left_deriv[0] = (V[i, j, k, l] - V[i -1, j, k, l]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l] - V[i, j, k, l]) / g.dx[0] - return left_deriv[0], right_deriv[0] \ No newline at end of file diff --git a/odp/spatialDerivatives/first_orderENO5D.py b/odp/spatialDerivatives/first_orderENO5D.py deleted file mode 100644 index e925169f..00000000 --- a/odp/spatialDerivatives/first_orderENO5D.py +++ /dev/null @@ -1,187 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * - -############################## 5D DERIVATIVE FUNCTIONS ############################# -def spa_derivX5_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 4 not in g.pDim: - with hcl.if_(m == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m] + my_abs(V[i, j, k, l, m + 1] - V[i, j, k, l, m]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[4] - right_deriv[0] = (V[i, j, k, l, m + 1] - V[i, j, k, l, m]) / g.dx[4] - with hcl.elif_(m == V.shape[4] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m] + my_abs(V[i, j, k, l, m] - V[i, j, k, l, m - 1]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k, l, m - 1]) / g.dx[4] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[4] - with hcl.elif_(m != 0 and m != V.shape[4] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k, l, m - 1]) / g.dx[4] - right_deriv[0] = (V[i, j, k, l, m + 1] - V[i, j, k, l, m]) / g.dx[4] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(m == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, V.shape[4] - 1] - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[4] - right_deriv[0] = (V[i, j, k, l, m + 1] - V[i, j, k, l, m]) / g.dx[4] - with hcl.elif_(m == V.shape[4] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, 0] - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k, l, m - 1]) / g.dx[4] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[4] - with hcl.elif_(m != 0 and m != V.shape[4] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k, l, m - 1]) / g.dx[4] - right_deriv[0] = (V[i, j, k, l, m + 1] - V[i, j, k, l, m]) / g.dx[4] - return left_deriv[0], right_deriv[0] - - -def spa_derivX4_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 3 not in g.pDim: - with hcl.if_(l == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m] + my_abs(V[i, j, k, l + 1, m] - V[i, j, k, l, m]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1, m] - V[i, j, k, l, m]) / g.dx[3] - with hcl.elif_(l == V.shape[3] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m] + my_abs(V[i, j, k, l, m] - V[i, j, k, l - 1, m]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k, l - 1, m]) / g.dx[3] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[3] - with hcl.elif_(l != 0 and l != V.shape[3] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k, l - 1, m]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1, m] - V[i, j, k, l, m]) / g.dx[3] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(l == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, V.shape[3] - 1, m] - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1, m] - V[i, j, k, l, m]) / g.dx[3] - with hcl.elif_(l == V.shape[3] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, 0, m] - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k, l - 1, m]) / g.dx[3] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[3] - with hcl.elif_(l != 0 and l != V.shape[3] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k, l - 1, m]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1, m] - V[i, j, k, l, m]) / g.dx[3] - return left_deriv[0], right_deriv[0] - - -def spa_derivX3_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 2 not in g.pDim: - with hcl.if_(k == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m] + my_abs(V[i, j, k + 1, l, m] - V[i, j, k, l, m]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l, m] - V[i, j, k, l, m]) / g.dx[2] - with hcl.elif_(k == V.shape[2] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m] + my_abs(V[i, j, k, l, m] - V[i, j, k - 1, l, m]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k - 1, l, m]) / g.dx[2] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[2] - with hcl.elif_(k != 0 and k != V.shape[2] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k - 1, l, m]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l, m] - V[i, j, k, l, m]) / g.dx[2] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(k == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, V.shape[2] - 1, l, m] - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l, m] - V[i, j, k, l, m]) / g.dx[2] - with hcl.elif_(k == V.shape[2] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, 0, l, m] - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k - 1, l, m]) / g.dx[2] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[2] - with hcl.elif_(k != 0 and k != V.shape[2] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i, j, k - 1, l, m]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l, m] - V[i, j, k, l, m]) / g.dx[2] - return left_deriv[0], right_deriv[0] - - -def spa_derivX2_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 1 not in g.pDim: - with hcl.if_(j == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m] + my_abs(V[i, j + 1, k, l, m] - V[i, j, k, l, m]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l, m] - V[i, j, k, l, m]) / g.dx[1] - with hcl.elif_(j == V.shape[1] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m] + my_abs(V[i, j, k, l, m] - V[i, j - 1, k, l, m]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - V[i, j - 1, k, l, m]) / g.dx[1] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[1] - with hcl.elif_(j != 0 and j != V.shape[1] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i, j - 1, k, l, m]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l, m] - V[i, j, k, l, m]) / g.dx[1] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(j == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, V.shape[1] - 1, k, l, m] - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l, m] - V[i, j, k, l, m]) / g.dx[1] - with hcl.elif_(j == V.shape[1] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, 0, k, l, m] - left_deriv[0] = (V[i, j, k, l, m] - V[i, j - 1, k, l, m]) / g.dx[1] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[1] - with hcl.elif_(j != 0 and j != V.shape[1] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i, j - 1, k, l, m]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l, m] - V[i, j, k, l, m]) / g.dx[1] - return left_deriv[0], right_deriv[0] - - -def spa_derivX1_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - if 0 not in g.pDim: - with hcl.if_(i == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m] + my_abs(V[i + 1, j, k, l, m] - V[i, j, k, l, m]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l, m] - V[i, j, k, l, m]) / g.dx[0] - with hcl.elif_(i == V.shape[0] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m] + my_abs(V[i, j, k, l, m] - V[i - 1, j, k, l, m]) * my_sign( - V[i, j, k, l, m]) - left_deriv[0] = (V[i, j, k, l, m] - V[i - 1, j, k, l, m]) / g.dx[0] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[0] - with hcl.elif_(i != 0 and i != V.shape[0] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i - 1, j, k, l, m]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l, m] - V[i, j, k, l, m]) / g.dx[0] - return left_deriv[0], right_deriv[0] - else: - with hcl.if_(i == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[V.shape[0] - 1, j, k, l, m] - left_deriv[0] = (V[i, j, k, l, m] - left_boundary[0]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l, m] - V[i, j, k, l, m]) / g.dx[0] - with hcl.elif_(i == V.shape[0] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[0, j, k, l, m] - left_deriv[0] = (V[i, j, k, l, m] - V[i - 1, j, k, l, m]) / g.dx[0] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m]) / g.dx[0] - with hcl.elif_(i != 0 and i != V.shape[0] - 1): - left_deriv[0] = (V[i, j, k, l, m] - V[i - 1, j, k, l, m]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l, m] - V[i, j, k, l, m]) / g.dx[0] - return left_deriv[0], right_deriv[0] diff --git a/odp/spatialDerivatives/first_orderENO6D.py b/odp/spatialDerivatives/first_orderENO6D.py deleted file mode 100644 index fafc23e2..00000000 --- a/odp/spatialDerivatives/first_orderENO6D.py +++ /dev/null @@ -1,128 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * - -############################## 6D DERIVATIVE FUNCTIONS ############################# -def spa_derivX6_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - with hcl.if_(n == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k, l, m, n + 1] - V[i, j, k, l, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - left_boundary[0]) / g.dx[5] - right_deriv[0] = (V[i, j, k, l, m, n + 1] - V[i, j, k, l, m, n]) / g.dx[5] - with hcl.elif_(n == V.shape[5] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k, l, m, n] - V[i, j, k, l, m, n - 1]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j, k, l, m, n - 1]) / g.dx[5] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m, n]) / g.dx[5] - with hcl.elif_(n != 0 and n != V.shape[5] - 1): - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j, k, l, m, n - 1]) / g.dx[5] - right_deriv[0] = (V[i, j, k, l, m, n + 1] - V[i, j, k, l, m, n]) / g.dx[5] - return left_deriv[0], right_deriv[0] - - -def spa_derivX5_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - with hcl.if_(m == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k, l, m + 1, n] - V[i, j, k, l, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - left_boundary[0]) / g.dx[4] - right_deriv[0] = (V[i, j, k, l, m + 1, n] - V[i, j, k, l, m, n]) / g.dx[4] - with hcl.elif_(m == V.shape[4] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k, l, m, n] - V[i, j, k, l, m - 1, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j, k, l, m - 1, n]) / g.dx[4] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m, n]) / g.dx[4] - with hcl.elif_(m != 0 and m != V.shape[4] - 1): - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j, k, l, m - 1, n]) / g.dx[4] - right_deriv[0] = (V[i, j, k, l, m + 1, n] - V[i, j, k, l, m, n]) / g.dx[4] - return left_deriv[0], right_deriv[0] - - -def spa_derivX4_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - with hcl.if_(l == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k, l + 1, m, n] - V[i, j, k, l, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - left_boundary[0]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1, m, n] - V[i, j, k, l, m, n]) / g.dx[3] - with hcl.elif_(l == V.shape[3] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k, l, m, n] - V[i, j, k, l - 1, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j, k, l - 1, m, n]) / g.dx[3] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m, n]) / g.dx[3] - with hcl.elif_(l != 0 and l != V.shape[3] - 1): - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j, k, l - 1, m, n]) / g.dx[3] - right_deriv[0] = (V[i, j, k, l + 1, m, n] - V[i, j, k, l, m, n]) / g.dx[3] - return left_deriv[0], right_deriv[0] - - -def spa_derivX3_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - with hcl.if_(k == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k + 1, l, m, n] - V[i, j, k, l, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - left_boundary[0]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l, m, n] - V[i, j, k, l, m, n]) / g.dx[2] - with hcl.elif_(k == V.shape[2] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k, l, m, n] - V[i, j, k - 1, l, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j, k - 1, l, m, n]) / g.dx[2] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m, n]) / g.dx[2] - with hcl.elif_(k != 0 and k != V.shape[2] - 1): - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j, k - 1, l, m, n]) / g.dx[2] - right_deriv[0] = (V[i, j, k + 1, l, m, n] - V[i, j, k, l, m, n]) / g.dx[2] - return left_deriv[0], right_deriv[0] - - -def spa_derivX2_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - with hcl.if_(j == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j + 1, k, l, m, n] - V[i, j, k, l, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - left_boundary[0]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l, m, n] - V[i, j, k, l, m, n]) / g.dx[1] - with hcl.elif_(j == V.shape[1] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k, l, m, n] - V[i, j - 1, k, l, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j - 1, k, l, m, n]) / g.dx[1] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m, n]) / g.dx[1] - with hcl.elif_(j != 0 and j != V.shape[1] - 1): - left_deriv[0] = (V[i, j, k, l, m, n] - V[i, j - 1, k, l, m, n]) / g.dx[1] - right_deriv[0] = (V[i, j + 1, k, l, m, n] - V[i, j, k, l, m, n]) / g.dx[1] - return left_deriv[0], right_deriv[0] - - -def spa_derivX1_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - with hcl.if_(i == 0): - left_boundary = hcl.scalar(0, "left_boundary") - left_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i + 1, j, k, l, m, n] - V[i, j, k, l, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - left_boundary[0]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l, m, n] - V[i, j, k, l, m, n]) / g.dx[0] - with hcl.elif_(i == V.shape[0] - 1): - right_boundary = hcl.scalar(0, "right_boundary") - right_boundary[0] = V[i, j, k, l, m, n] + my_abs(V[i, j, k, l, m, n] - V[i - 1, j, k, l, m, n]) * my_sign( - V[i, j, k, l, m, n]) - left_deriv[0] = (V[i, j, k, l, m, n] - V[i - 1, j, k, l, m, n]) / g.dx[0] - right_deriv[0] = (right_boundary[0] - V[i, j, k, l, m, n]) / g.dx[0] - with hcl.elif_(i != 0 and i != V.shape[0] - 1): - left_deriv[0] = (V[i, j, k, l, m, n] - V[i - 1, j, k, l, m, n]) / g.dx[0] - right_deriv[0] = (V[i + 1, j, k, l, m, n] - V[i, j, k, l, m, n]) / g.dx[0] - return left_deriv[0], right_deriv[0] diff --git a/odp/spatialDerivatives/second_orderENO3D.py b/odp/spatialDerivatives/second_orderENO3D.py deleted file mode 100644 index 8ca5aa0b..00000000 --- a/odp/spatialDerivatives/second_orderENO3D.py +++ /dev/null @@ -1,454 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * - -################## 3D SPATIAL DERIVATIVE FUNCTION ################# -def secondOrderX(i, j, k, V, g): - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 0 - - u_i = V[i, j, k] - - with hcl.if_(i == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i + 1, j, k] - u_i_plus_2 = V[i + 2, j, k] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i - 1, j, k] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i + 1, j, k] - - u_i_minus_1 = V[i - 1, j, k] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i - 1, j, k] - - u_i_plus_1 = V[i + 1, j, k] - u_i_plus_2 = V[i + 2, j, k] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderY(i, j, k, V, g): - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 1 - - u_i = V[i, j, k] - - with hcl.if_(j == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j + 1, k] - u_i_plus_2 = V[i, j + 2, k] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j - 1, k] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j + 1, k] - - u_i_minus_1 = V[i, j - 1, k] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j - 1, k] - - u_i_plus_1 = V[i, j + 1, k] - u_i_plus_2 = V[i, j + 2, k] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderT(i, j, k, V, g): - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 2 - - u_i = V[i, j, k] - - with hcl.if_(k == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_minus_1[0] = V[i, j, V.shape[dim_idx] - 1] - - u_i_plus_1 = V[i, j, k + 1] - u_i_plus_2 = V[i, j, k + 2] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1[0] = V[i, j, 0] - u_i_plus_2[0] = V[i, j, 1] - - u_i_minus_1 = V[i, j, k - 1] - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k + 1] - u_i_plus_2[0] = V[i, j, 0] - - u_i_minus_1 = V[i, j, k - 1] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k - 1] - - u_i_plus_1 = V[i, j, k + 1] - u_i_plus_2 = V[i, j, k + 2] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] \ No newline at end of file diff --git a/odp/spatialDerivatives/second_orderENO4D.py b/odp/spatialDerivatives/second_orderENO4D.py deleted file mode 100644 index 5f786416..00000000 --- a/odp/spatialDerivatives/second_orderENO4D.py +++ /dev/null @@ -1,1178 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * - -################## 4D SPATIAL DERIVATIVE FUNCTION ################# - -# Calculate derivative on the first derivative # -def secondOrderX4_4d(i, j, k, l, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 3 - - u_i = V[i, j, k, l] - - if 3 not in g.pDim: - with hcl.if_(l == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j, k, l + 1] - u_i_plus_2 = V[i, j, k, l + 2] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(l == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j, k, l - 1] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(l == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k, l + 1] - - u_i_minus_1 = V[i, j, k, l - 1] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k, l - 1] - - u_i_plus_1 = V[i, j, k, l + 1] - u_i_plus_2 = V[i, j, k, l + 2] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - else: - with hcl.if_(l == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_minus_1[0] = V[i, j, k, V.shape[dim_idx] - 1] - - u_i_plus_1 = V[i, j, k, l + 1] - u_i_plus_2 = V[i, j, k, l + 2] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(l == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1[0] = V[i, j, k, 0] - u_i_plus_2[0] = V[i, j, k, 1] - - u_i_minus_1 = V[i, j, k, l - 1] - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(l == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k, l + 1] - u_i_plus_2[0] = V[i, j, k, 0] - - u_i_minus_1 = V[i, j, k, l - 1] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k, l - 1] - - u_i_plus_1 = V[i, j, k, l + 1] - u_i_plus_2 = V[i, j, k, l + 2] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX3_4d(i, j, k, l, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 2 - - u_i = V[i, j, k, l] - - if 2 not in g.pDim: - with hcl.if_(k == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j, k + 1, l] - u_i_plus_2 = V[i, j, k + 2, l] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j, k - 1, l] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k + 1, l] - - u_i_minus_1 = V[i, j, k - 1, l] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k - 1, l] - - u_i_plus_1 = V[i, j, k + 1, l] - u_i_plus_2 = V[i, j, k + 2, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - else: - with hcl.if_(k == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_minus_1[0] = V[i, j, V.shape[dim_idx] - 1, l] - - u_i_plus_1 = V[i, j, k + 1, l] - u_i_plus_2 = V[i, j, k + 2, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1[0] = V[i, j, 0, l] - u_i_plus_2[0] = V[i, j, 1, l] - - u_i_minus_1 = V[i, j, k - 1, l] - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k + 1, l] - u_i_plus_2[0] = V[i, j, 0, l] - - u_i_minus_1 = V[i, j, k - 1, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k - 1, l] - - u_i_plus_1 = V[i, j, k + 1, l] - u_i_plus_2 = V[i, j, k + 2, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - -def secondOrderX2_4d(i, j, k, l, V, g): # - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 1 - - u_i = V[i, j, k, l] - - if 1 not in g.pDim: - with hcl.if_(j == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j + 1, k, l] - u_i_plus_2 = V[i, j + 2, k, l] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j - 1, k, l] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j + 1, k, l] - - u_i_minus_1 = V[i, j - 1, k, l] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j - 1, k, l] - - u_i_plus_1 = V[i, j + 1, k, l] - u_i_plus_2 = V[i, j + 2, k, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - else: - with hcl.if_(j == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_minus_1[0] = V[i, V.shape[dim_idx] - 1, k, l] - - u_i_plus_1 = V[i, j + 1, k, l] - u_i_plus_2 = V[i, j + 2, k, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1[0] = V[i, 0, k, l] - u_i_plus_2[0] = V[i, 1, k, l] - - u_i_minus_1 = V[i, j - 1, k, l] - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j + 1, k, l] - u_i_plus_2[0] = V[i, 0, k, l] - - u_i_minus_1 = V[i, j - 1, k, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j - 1, k, l] - - u_i_plus_1 = V[i, j + 1, k, l] - u_i_plus_2 = V[i, j + 2, k, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - -def secondOrderX1_4d(i, j, k, l, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 0 - - u_i = V[i, j, k, l] - - if 0 not in g.pDim: - with hcl.if_(i == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i + 1, j, k, l] - u_i_plus_2 = V[i + 2, j, k, l] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i - 1, j, k, l] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i + 1, j, k, l] - - u_i_minus_1 = V[i - 1, j, k, l] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i - 1, j, k, l] - - u_i_plus_1 = V[i + 1, j, k, l] - u_i_plus_2 = V[i + 2, j, k, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - else: - with hcl.if_(i == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_minus_1[0] = V[V.shape[dim_idx] - 1, j, k, l] - - u_i_plus_1 = V[i + 1, j, k, l] - u_i_plus_2 = V[i + 2, j, k, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1[0] = V[0, j, k, l] - u_i_plus_2[0] = V[1, j, k, l] - - u_i_minus_1 = V[i - 1, j, k, l] - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i + 1, j, k, l] - u_i_plus_2[0] = V[0, j, k, l] - - u_i_minus_1 = V[i - 1, j, k, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i - 1, j, k, l] - - u_i_plus_1 = V[i + 1, j, k, l] - u_i_plus_2 = V[i + 2, j, k, l] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] \ No newline at end of file diff --git a/odp/spatialDerivatives/second_orderENO5D.py b/odp/spatialDerivatives/second_orderENO5D.py deleted file mode 100644 index 79ec3993..00000000 --- a/odp/spatialDerivatives/second_orderENO5D.py +++ /dev/null @@ -1,757 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * - -############################## 5D DERIVATIVE FUNCTIONS ############################# -def secondOrderX5_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 4 - - u_i = V[i, j, k, l, m] - - with hcl.if_(m == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j, k, l, m + 1] - u_i_plus_2 = V[i, j, k, l, m + 2] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(m == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j, k, l, m - 1] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(m == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k, l, m + 1] - - u_i_minus_1 = V[i, j, k, l, m - 1] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k, l, m - 1] - - u_i_plus_1 = V[i, j, k, l, m + 1] - u_i_plus_2 = V[i, j, k, l, m + 2] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX4_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 3 - - u_i = V[i, j, k, l, m] - - with hcl.if_(l == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j, k, l + 1, m] - u_i_plus_2 = V[i, j, k, l + 2, m] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(l == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j, k, l - 1, m] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(l == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k, l + 1, m] - - u_i_minus_1 = V[i, j, k, l - 1, m] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k, l - 1, m] - - u_i_plus_1 = V[i, j, k, l + 1, m] - u_i_plus_2 = V[i, j, k, l + 2, m] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX3_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 2 - - u_i = V[i, j, k, l, m] - - with hcl.if_(k == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j, k + 1, l, m] - u_i_plus_2 = V[i, j, k + 2, l, m] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j, k - 1, l, m] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k + 1, l, m] - - u_i_minus_1 = V[i, j, k - 1, l, m] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k - 1, l, m] - - u_i_plus_1 = V[i, j, k + 1, l, m] - u_i_plus_2 = V[i, j, k + 2, l, m] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX2_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 1 - - u_i = V[i, j, k, l, m] - - with hcl.if_(j == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j + 1, k, l, m] - u_i_plus_2 = V[i, j + 2, k, l, m] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j - 1, k, l, m] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j + 1, k, l, m] - - u_i_minus_1 = V[i, j - 1, k, l, m] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j - 1, k, l, m] - - u_i_plus_1 = V[i, j + 1, k, l, m] - u_i_plus_2 = V[i, j + 2, k, l, m] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX1_5d(i, j, k, l, m, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 0 - - u_i = V[i, j, k, l, m] - - with hcl.if_(i == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i + 1, j, k, l, m] - u_i_plus_2 = V[i + 2, j, k, l, m] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i - 1, j, k, l, m] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i + 1, j, k, l, m] - - u_i_minus_1 = V[i - 1, j, k, l, m] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i - 1, j, k, l, m] - - u_i_plus_1 = V[i + 1, j, k, l, m] - u_i_plus_2 = V[i + 2, j, k, l, m] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] diff --git a/odp/spatialDerivatives/second_orderENO6D.py b/odp/spatialDerivatives/second_orderENO6D.py deleted file mode 100644 index 6f8df86e..00000000 --- a/odp/spatialDerivatives/second_orderENO6D.py +++ /dev/null @@ -1,909 +0,0 @@ -import heterocl as hcl -from odp.computeGraphs.CustomGraphFunctions import * - -############################## 6D DERIVATIVE FUNCTIONS ############################# -def secondOrderX6_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 5 - - u_i = V[i, j, k, l, m, n] - - with hcl.if_(n == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j, k, l, m, n + 1] - u_i_plus_2 = V[i, j, k, l, m, n + 2] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(n == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j, k, l, m, n - 1] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(n == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k, l, m, n + 1] - - u_i_minus_1 = V[i, j, k, l, m, n - 1] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k, l, m, n - 1] - - u_i_plus_1 = V[i, j, k, l, m, n + 1] - u_i_plus_2 = V[i, j, k, l, m, n + 2] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX5_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 4 - - u_i = V[i, j, k, l, m, n] - - with hcl.if_(m == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j, k, l, m + 1, n] - u_i_plus_2 = V[i, j, k, l, m + 2, n] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(m == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j, k, l, m - 1, n] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(m == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k, l, m + 1, n] - - u_i_minus_1 = V[i, j, k, l, m - 1, n] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k, l, m - 1, n] - - u_i_plus_1 = V[i, j, k, l, m + 1, n] - u_i_plus_2 = V[i, j, k, l, m + 2, n] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX4_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 3 - - u_i = V[i, j, k, l, m, n] - - with hcl.if_(l == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j, k, l + 1, m, n] - u_i_plus_2 = V[i, j, k, l + 2, m, n] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(l == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j, k, l - 1, m, n] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(l == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k, l + 1, m, n] - - u_i_minus_1 = V[i, j, k, l - 1, m, n] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k, l - 1, m, n] - - u_i_plus_1 = V[i, j, k, l + 1, m, n] - u_i_plus_2 = V[i, j, k, l + 2, m, n] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX3_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 2 - - u_i = V[i, j, k, l, m, n] - - with hcl.if_(k == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j, k + 1, l, m, n] - u_i_plus_2 = V[i, j, k + 2, l, m, n] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j, k - 1, l, m, n] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(k == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j, k + 1, l, m, n] - - u_i_minus_1 = V[i, j, k - 1, l, m, n] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j, k - 1, l, m, n] - - u_i_plus_1 = V[i, j, k + 1, l, m, n] - u_i_plus_2 = V[i, j, k + 2, l, m, n] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX2_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 1 - - u_i = V[i, j, k, l, m, n] - - with hcl.if_(j == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i, j + 1, k, l, m, n] - u_i_plus_2 = V[i, j + 2, k, l, m, n] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i, j - 1, k, l, m, n] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(j == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i, j + 1, k, l, m, n] - - u_i_minus_1 = V[i, j - 1, k, l, m, n] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i, j - 1, k, l, m, n] - - u_i_plus_1 = V[i, j + 1, k, l, m, n] - u_i_plus_2 = V[i, j + 2, k, l, m, n] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - - -def secondOrderX1_6d(i, j, k, l, m, n, V, g): # Left -> right == Outer Most -> Inner Most - left_deriv = hcl.scalar(0, "left_deriv") - right_deriv = hcl.scalar(0, "right_deriv") - - dim_idx = 0 - - u_i = V[i, j, k, l, m, n] - - with hcl.if_(i == 0): - u_i_minus_1 = hcl.scalar(0, "u_i_minus_1") - - u_i_plus_1 = V[i + 1, j, k, l, m, n] - u_i_plus_2 = V[i + 2, j, k, l, m, n] - - u_i_minus_1[0] = u_i + my_abs(u_i_plus_1 - u_i) * my_sign(u_i) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1[0]) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 1): - u_i_plus_1 = hcl.scalar(0, "u_i_plus_1") - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_minus_1 = V[i - 1, j, k, l, m, n] - - u_i_plus_1[0] = u_i + my_abs(u_i - u_i_minus_1) * my_sign(u_i) - u_i_plus_2[0] = u_i_plus_1[0] + my_abs(u_i_plus_1[0] - u_i) * my_sign(u_i_plus_1[0]) - - D1_i_plus_half = (u_i_plus_1[0] - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1[0]) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.elif_(i == V.shape[dim_idx] - 2): - u_i_plus_2 = hcl.scalar(0, "u_i_plus_2") - - u_i_plus_1 = V[i + 1, j, k, l, m, n] - - u_i_minus_1 = V[i - 1, j, k, l, m, n] - - u_i_plus_2[0] = u_i_plus_1 + my_abs(u_i_plus_1 - u_i) * my_sign(u_i_plus_1) - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2[0] - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - u_i_minus_1 = V[i - 1, j, k, l, m, n] - - u_i_plus_1 = V[i + 1, j, k, l, m, n] - u_i_plus_2 = V[i + 2, j, k, l, m, n] - - D1_i_plus_half = (u_i_plus_1 - u_i) / g.dx[dim_idx] - D1_i_minus_half = (u_i - u_i_minus_1) / g.dx[dim_idx] - - Q1d_left = D1_i_minus_half - Q1d_right = D1_i_plus_half - - D2_i = 0.5 * ((D1_i_plus_half - D1_i_minus_half) / g.dx[dim_idx]) - - u_i_plus_1_plus_1 = u_i_plus_2 - D1_i_plus_1_plus_half = (u_i_plus_1_plus_1 - u_i_plus_1) / g.dx[dim_idx] - D1_i_plus_1_minus_half = D1_i_plus_half - D2_i_plus_1 = 0.5 * ((D1_i_plus_1_plus_half - D1_i_plus_1_minus_half) / g.dx[dim_idx]) - - with hcl.if_(my_abs(D2_i) <= my_abs(D2_i_plus_1)): - c = D2_i - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - with hcl.else_(): - c = D2_i_plus_1 - Q2d = c * g.dx[dim_idx] - - left_deriv[0] = Q1d_left + Q2d - right_deriv[0] = Q1d_right - Q2d - - return left_deriv[0], right_deriv[0] - diff --git a/odp/valueIteration/3D_Q_value_iteration.py b/odp/valueIteration/3D_Q_value_iteration.py deleted file mode 100644 index 802b6604..00000000 --- a/odp/valueIteration/3D_Q_value_iteration.py +++ /dev/null @@ -1,464 +0,0 @@ -import heterocl as hcl -import numpy as np -import time -import odp.valueIteration.user_definer_3D_Q as UD - - - -###################################### USER-DEFINED FUNCTIONS ###################################### - - -# Given state and action, return successor states and their probabilities -# sVals: the coordinates of state -# bounds: the lower and upper limits of the state space in each dimension -# trans: holds each successor state and the probability of reaching that state -def transition(sVals, action, bounds, trans, goal): - dx = hcl.scalar(0, "dx") - dy = hcl.scalar(0, "dy") - mag = hcl.scalar(0, "mag") - - # Check if moving from a goal state - dx[0] = sVals[0] - goal[0,0] - dy[0] = sVals[1] - goal[0,1] - mag[0] = hcl.sqrt((dx[0] * dx[0]) + (dy[0] * dy[0])) - with hcl.if_(hcl.and_(mag[0] <= 1.0, sVals[2] <= goal[1,1], sVals[2] >= goal[1,0])): - trans[0, 0] = 0 - # Check if moving from an obstacle - with hcl.elif_(hcl.or_(sVals[0] < bounds[0,0] + 0.2, sVals[0] > bounds[0,1] - 0.2)): - trans[0, 0] = 0 - with hcl.elif_(hcl.or_(sVals[1] < bounds[1,0] + 0.2, sVals[1] > bounds[1,1] - 0.2)): - trans[0, 0] = 0 - # Standard move - with hcl.else_(): - trans[0, 0] = 1.0 - trans[0, 1] = sVals[0] + (0.6 * action[0] * hcl.cos(sVals[2])) - trans[0, 2] = sVals[1] + (0.6 * action[0] * hcl.sin(sVals[2])) - trans[0, 3] = sVals[2] + (0.6 * action[1]) - # Adjust for periodic dimension - with hcl.while_(trans[0, 3] > 3.141592653589793): - trans[0, 3] -= 6.283185307179586 - with hcl.while_(trans[0, 3] < -3.141592653589793): - trans[0, 3] += 6.283185307179586 - - -# Return the reward for taking action from state -def reward(sVals, action, bounds, goal, trans): - dx = hcl.scalar(0, "dx") - dy = hcl.scalar(0, "dy") - mag = hcl.scalar(0, "mag") - rwd = hcl.scalar(0, "rwd") - - # Check if moving from a collision state, if so, assign a penalty - with hcl.if_(hcl.or_(sVals[0] < bounds[0,0] + 0.2, sVals[0] > bounds[0,1] - 0.2)): - rwd[0] = -400 - with hcl.elif_(hcl.or_(sVals[1] < bounds[1,0] + 0.2, sVals[1] > bounds[1,1] - 0.2)): - rwd[0] = -400 - with hcl.else_(): - # Check if moving from a goal state - dx[0] = sVals[0] - goal[0,0] - dy[0] = sVals[1] - goal[0,1] - mag[0] = hcl.sqrt((dx[0] * dx[0]) + (dy[0] * dy[0])) - with hcl.if_(hcl.and_(mag[0] <= 1.0, sVals[2] <= goal[1,1], sVals[2] >= goal[1,0])): - rwd[0] = 1000 - # Standard move - with hcl.else_(): - rwd[0] = 0 - return rwd[0] - - - -######################################### HELPER FUNCTIONS ######################################### - - -# Update the value function at position (i,j,k) -def updateQopt(i, j, k, a, iVals, sVals, Qopt, actions, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal): - r = hcl.scalar(0, "r") - p = hcl.scalar(0, "p") - # set iVals equal to (i,j,k) and sVals equal to the corresponding state values at (i,j,k) - updateStateVals(i, j, k, iVals, sVals, bounds, ptsEachDim) - # call the transition function to obtain the outcome(s) of action a from state (si,sj,sk) - transition(sVals, actions[a], bounds, trans, goal) - # initialize Qopt[i,j,k,a] with the immediate reward - r[0] = reward(sVals, actions[a], bounds, goal, trans) - Qopt[i,j,k,a] = r[0] - # maximize over successor Q-values - with hcl.for_(0, trans.shape[0], name="si") as si: - p[0] = trans[si,0] - sVals[0] = trans[si,1] - sVals[1] = trans[si,2] - sVals[2] = trans[si,3] - # Nearest neighbour - with hcl.if_(useNN[0] == 1): - # obtain the nearest neighbour successor state - stateToIndex(sVals, iVals, bounds, ptsEachDim) - # maximize over successor state Q-values - with hcl.if_(hcl.and_(iVals[0] < Qopt.shape[0], iVals[1] < Qopt.shape[1], iVals[2] < Qopt.shape[2])): - with hcl.if_(hcl.and_(iVals[0] >= 0, iVals[1] >= 0, iVals[2] >= 0)): - with hcl.for_(0, actions.shape[0], name="a_") as a_: - with hcl.if_((r[0] + (gamma[0] * (p[0] * Qopt[iVals[0],iVals[1],iVals[2],a_]))) > Qopt[i,j,k,a]): - Qopt[i,j,k,a] = r[0] + (gamma[0] * (p[0] * Qopt[iVals[0],iVals[1],iVals[2],a_])) - # Linear interpolation - with hcl.if_(useNN[0] == 0): - with hcl.if_(hcl.and_(sVals[0] <= bounds[0,1], sVals[1] <= bounds[1,1], sVals[2] <= bounds[2,1])): - with hcl.if_(hcl.and_(sVals[0] >= bounds[0,0], sVals[1] >= bounds[1,0], sVals[2] >= bounds[2,0])): - stateToIndexInterpolants(Qopt, sVals, actions, bounds, ptsEachDim, interpV, fillVal) - Qopt[i,j,k,a] += (gamma[0] * (p[0] * interpV[0])) - r[0] += Qopt[i,j,k,a] - -# Returns 0 if convergence has been reached -def evaluateConvergence(newQ, oldQ, epsilon, reSweep): - delta = hcl.scalar(0, "delta") - # Calculate the difference, if it's negative, make it positive - delta[0] = newQ[0] - oldQ[0] - with hcl.if_(delta[0] < 0): - delta[0] = delta[0] * -1 - with hcl.if_(delta[0] > epsilon[0]): - reSweep[0] = 1 - - -# convert state values into indeces using nearest neighbour -# NOTE: have to modify this to work with modular values -def stateToIndex(sVals, iVals, bounds, ptsEachDim): - iVals[0] = ((sVals[0] - bounds[0,0]) / (bounds[0,1] - bounds[0,0])) * (ptsEachDim[0] - 1) - iVals[1] = ((sVals[1] - bounds[1,0]) / (bounds[1,1] - bounds[1,0])) * (ptsEachDim[1] - 1) - iVals[2] = ((sVals[2] - bounds[2,0]) / (bounds[2,1] - bounds[2,0])) * (ptsEachDim[2] - 1) - # NOTE: add 0.5 to simulate rounding - iVals[0] = hcl.cast(hcl.Int(), iVals[0] + 0.5) - iVals[1] = hcl.cast(hcl.Int(), iVals[1] + 0.5) - iVals[2] = hcl.cast(hcl.Int(), iVals[2] + 0.5) - - -# convert indices into state values -def indexToState(iVals, sVals, bounds, ptsEachDim): - sVals[0] = bounds[0,0] + ( (bounds[0,1] - bounds[0,0]) * (iVals[0] / (ptsEachDim[0]-1)) ) - sVals[1] = bounds[1,0] + ( (bounds[1,1] - bounds[1,0]) * (iVals[1] / (ptsEachDim[1]-1)) ) - sVals[2] = bounds[2,0] + ( (bounds[2,1] - bounds[2,0]) * (iVals[2] / (ptsEachDim[2]-1)) ) - - -# set iVals equal to (i,j,k) and sVals equal to the corresponding state values at (i,j,k) -def updateStateVals(i, j, k, iVals, sVals, bounds, ptsEachDim): - iVals[0] = i - iVals[1] = j - iVals[2] = k - indexToState(iVals, sVals, bounds, ptsEachDim) - - -# given state values sVals, obtain the 8 possible successor states and their corresponding weight -def stateToIndexInterpolants(Qopt, sVals, actions, bounds, ptsEachDim, interpV, fillVal): - iMin = hcl.scalar(0, "iMin") - jMin = hcl.scalar(0, "jMin") - kMin = hcl.scalar(0, "kMin") - iMax = hcl.scalar(0, "iMax") - jMax = hcl.scalar(0, "jMax") - kMax = hcl.scalar(0, "kMax") - c000 = hcl.scalar(fillVal[0], "c000") - c001 = hcl.scalar(fillVal[0], "c001") - c010 = hcl.scalar(fillVal[0], "c010") - c011 = hcl.scalar(fillVal[0], "c011") - c100 = hcl.scalar(fillVal[0], "c100") - c101 = hcl.scalar(fillVal[0], "c101") - c110 = hcl.scalar(fillVal[0], "c110") - c111 = hcl.scalar(fillVal[0], "c111") - c00 = hcl.scalar(0, "c00") - c01 = hcl.scalar(0, "c01") - c10 = hcl.scalar(0, "c10") - c11 = hcl.scalar(0, "c11") - c0 = hcl.scalar(0, "c0") - c1 = hcl.scalar(0, "c1") - ia = hcl.scalar(0, "ia") - ja = hcl.scalar(0, "ja") - ka = hcl.scalar(0, "ka") - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - - # obtain unrounded index values - ia[0] = ((sVals[0] - bounds[0,0]) / (bounds[0,1] - bounds[0,0])) * (ptsEachDim[0] - 1) - ja[0] = ((sVals[1] - bounds[1,0]) / (bounds[1,1] - bounds[1,0])) * (ptsEachDim[1] - 1) - ka[0] = ((sVals[2] - bounds[2,0]) / (bounds[2,1] - bounds[2,0])) * (ptsEachDim[2] - 1) - - # obtain neighbouring state indeces in each direction - with hcl.if_(ia[0] < 0): - iMin[0] = hcl.cast(hcl.Int(), ia[0] - 1.0) - iMax[0] = hcl.cast(hcl.Int(), ia[0]) - with hcl.else_(): - iMin[0] = hcl.cast(hcl.Int(), ia[0]) - iMax[0] = hcl.cast(hcl.Int(), ia[0] + 1.0) - with hcl.if_(ja[0] < 0): - jMin[0] = hcl.cast(hcl.Int(), ja[0] - 1.0) - jMax[0] = hcl.cast(hcl.Int(), ja[0]) - with hcl.else_(): - jMin[0] = hcl.cast(hcl.Int(), ja[0]) - jMax[0] = hcl.cast(hcl.Int(), ja[0] + 1.0) - with hcl.if_(ka[0] < 0): - kMin[0] = hcl.cast(hcl.Int(), ka[0] - 1.0) - kMax[0] = hcl.cast(hcl.Int(), ka[0]) - with hcl.else_(): - kMin[0] = hcl.cast(hcl.Int(), ka[0]) - kMax[0] = hcl.cast(hcl.Int(), ka[0] + 1.0) - - # obtain weights in each direction - di[0] = ia[0] - iMin[0] - dj[0] = ja[0] - jMin[0] - dk[0] = ka[0] - kMin[0] - - # Obtain value of each neighbour state - # Qopt[iMin, jMin, kMin] - with hcl.if_(hcl.and_(iMin[0] < Qopt.shape[0], jMin[0] < Qopt.shape[1], kMin[0] < Qopt.shape[2])): - with hcl.if_(hcl.and_(iMin[0] >= 0, jMin[0] >= 0, kMin[0] >= 0)): - with hcl.for_(0, actions.shape[0], name="a_") as a_: - with hcl.if_(c000[0] < Qopt[iMin[0], jMin[0], kMin[0], a_]): - c000[0] = Qopt[iMin[0], jMin[0], kMin[0], a_] - # Qopt[iMin, jMin, kMax] - with hcl.if_(hcl.and_(iMin[0] < Qopt.shape[0], jMin[0] < Qopt.shape[1], kMax[0] < Qopt.shape[2])): - with hcl.if_(hcl.and_(iMin[0] >= 0, jMin[0] >= 0, kMax[0] >= 0)): - with hcl.for_(0, actions.shape[0], name="a_") as a_: - with hcl.if_(c001[0] < Qopt[iMin[0], jMin[0], kMax[0], a_]): - c001[0] = Qopt[iMin[0], jMin[0], kMax[0], a_] - # Qopt[iMin, jMax, kMin] - with hcl.if_(hcl.and_(iMin[0] < Qopt.shape[0], jMax[0] < Qopt.shape[1], kMin[0] < Qopt.shape[2])): - with hcl.if_(hcl.and_(iMin[0] >= 0, jMax[0] >= 0, kMin[0] >= 0)): - with hcl.for_(0, actions.shape[0], name="a_") as a_: - with hcl.if_(c010[0] < Qopt[iMin[0], jMax[0], kMin[0], a_]): - c010[0] = Qopt[iMin[0], jMax[0], kMin[0], a_] - # Qopt[iMin, jMax, kMax] - with hcl.if_(hcl.and_(iMin[0] < Qopt.shape[0], jMax[0] < Qopt.shape[1], kMax[0] < Qopt.shape[2])): - with hcl.if_(hcl.and_(iMin[0] >= 0, jMax[0] >= 0, kMax[0] >= 0)): - with hcl.for_(0, actions.shape[0], name="a_") as a_: - with hcl.if_(c011[0] < Qopt[iMin[0], jMax[0], kMax[0], a_]): - c011[0] = Qopt[iMin[0], jMax[0], kMax[0], a_] - # Qopt[iMax, jMin, kMin] - with hcl.if_(hcl.and_(iMax[0] < Qopt.shape[0], jMin[0] < Qopt.shape[1], kMin[0] < Qopt.shape[2])): - with hcl.if_(hcl.and_(iMax[0] >= 0, jMin[0] >= 0, kMin[0] >= 0)): - with hcl.for_(0, actions.shape[0], name="a_") as a_: - with hcl.if_(c100[0] < Qopt[iMax[0], jMin[0], kMin[0], a_]): - c100[0] = Qopt[iMax[0], jMin[0], kMin[0], a_] - # Qopt[iMax, jMin, kMax] - with hcl.if_(hcl.and_(iMax[0] < Qopt.shape[0], jMin[0] < Qopt.shape[1], kMax[0] < Qopt.shape[2])): - with hcl.if_(hcl.and_(iMax[0] >= 0, jMin[0] >= 0, kMax[0] >= 0)): - with hcl.for_(0, actions.shape[0], name="a_") as a_: - with hcl.if_(c101[0] < Qopt[iMax[0], jMin[0], kMax[0], a_]): - c101[0] = Qopt[iMax[0], jMin[0], kMax[0], a_] - # Qopt[iMax, jMax, kMin] - with hcl.if_(hcl.and_(iMax[0] < Qopt.shape[0], jMax[0] < Qopt.shape[1], kMin[0] < Qopt.shape[2])): - with hcl.if_(hcl.and_(iMax[0] >= 0, jMax[0] >= 0, kMin[0] >= 0)): - with hcl.for_(0, actions.shape[0], name="a_") as a_: - with hcl.if_(c110[0] < Qopt[iMax[0], jMax[0], kMin[0], a_]): - c110[0] = Qopt[iMax[0], jMax[0], kMin[0], a_] - # Qopt[iMax, jMax, kMax] - with hcl.if_(hcl.and_(iMax[0] < Qopt.shape[0], jMax[0] < Qopt.shape[1], kMax[0] < Qopt.shape[2])): - with hcl.if_(hcl.and_(iMax[0] >= 0, jMax[0] >= 0, kMax[0] >= 0)): - with hcl.for_(0, actions.shape[0], name="a_") as a_: - with hcl.if_(c111[0] < Qopt[iMax[0], jMax[0], kMax[0], a_]): - c111[0] = Qopt[iMax[0], jMax[0], kMax[0], a_] - - # perform linear interpolation - c00[0] = (c000[0] * (1-di[0])) + (c100[0] * di[0]) - c01[0] = (c001[0] * (1-di[0])) + (c101[0] * di[0]) - c10[0] = (c010[0] * (1-di[0])) + (c110[0] * di[0]) - c11[0] = (c011[0] * (1-di[0])) + (c111[0] * di[0]) - c0[0] = (c00[0] * (1-dj[0])) + (c10[0] * dj[0]) - c1[0] = (c01[0] * (1-dj[0])) + (c11[0] * dj[0]) - interpV[0] = (c0[0] * (1-dk[0])) + (c1[0] * dk[0]) - - - -######################################### VALUE ITERATION ########################################## - - -def value_iteration_3D(): - def solve_Qopt(Qopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN, fillVal): - reSweep = hcl.scalar(1, "reSweep") - oldQ = hcl.scalar(0, "oldV") - newQ = hcl.scalar(0, "newV") - with hcl.while_(hcl.and_(reSweep[0] == 1, count[0] < maxIters[0])): - reSweep[0] = 0 - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(0, Qopt.shape[0], name="i") as i: - with hcl.for_(0, Qopt.shape[1], name="j") as j: - with hcl.for_(0, Qopt.shape[2], name="k") as k: - with hcl.for_(0, Qopt.shape[3], name="a") as a: - oldQ[0] = Qopt[i,j,k,a] - updateQopt(i, j, k, a, iVals, sVals, Qopt, actions, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newQ[0] = Qopt[i,j,k,a] - evaluateConvergence(newQ, oldQ, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - # For all states - with hcl.for_(1, Qopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Qopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Qopt.shape[2] + 1, name="k") as k: - i2 = Qopt.shape[0] - i - j2 = Qopt.shape[1] - j - k2 = Qopt.shape[2] - k - # For all actions - with hcl.for_(0, Qopt.shape[3], name="a") as a: - oldQ[0] = Qopt[i2,j2,k2,a] - updateQopt(i2, j2, k2, a, iVals, sVals, Qopt, actions, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newQ[0] = Qopt[i2,j2,k2,a] - evaluateConvergence(newQ, oldQ, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - # For all states - with hcl.for_(1, Qopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Qopt.shape[1], name="j") as j: - with hcl.for_(0, Qopt.shape[2], name="k") as k: - i2 = Qopt.shape[0] - i - # For all actions - with hcl.for_(0, Qopt.shape[3], name="a") as a: - oldQ[0] = Qopt[i2,j,k,a] - updateQopt(i2, j, k, a, iVals, sVals, Qopt, actions, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newQ[0] = Qopt[i2,j,k,a] - evaluateConvergence(newQ, oldQ, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - # For all states - with hcl.for_(0, Qopt.shape[0], name="i") as i: - with hcl.for_(1, Qopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Qopt.shape[2], name="k") as k: - j2 = Qopt.shape[1] - j - # For all actions - with hcl.for_(0, Qopt.shape[3], name="a") as a: - oldQ[0] = Qopt[i,j2,k,a] - updateQopt(i, j2, k, a, iVals, sVals, Qopt, actions, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newQ[0] = Qopt[i,j2,k,a] - evaluateConvergence(newQ, oldQ, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - # For all states - with hcl.for_(0, Qopt.shape[0], name="i") as i: - with hcl.for_(0, Qopt.shape[1], name="j") as j: - with hcl.for_(1, Qopt.shape[2] + 1, name="k") as k: - k2 = Qopt.shape[2] - k - # For all actions - with hcl.for_(0, Qopt.shape[3], name="a") as a: - oldQ[0] = Qopt[i,j,k2,a] - updateQopt(i, j, k2, a, iVals, sVals, Qopt, actions, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newQ[0] = Qopt[i,j,k2,a] - evaluateConvergence(newQ, oldQ, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - # For all states - with hcl.for_(1, Qopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Qopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Qopt.shape[2], name="k") as k: - i2 = Qopt.shape[0] - i - j2 = Qopt.shape[1] - j - # For all actions - with hcl.for_(0, Qopt.shape[3], name="a") as a: - oldQ[0] = Qopt[i2,j2,k,a] - updateQopt(i2, j2, k, a, iVals, sVals, Qopt, actions, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newQ[0] = Qopt[i2,j2,k,a] - evaluateConvergence(newQ, oldQ, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - # For all states - with hcl.for_(1, Qopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Qopt.shape[1], name="j") as j: - with hcl.for_(1, Qopt.shape[2] + 1, name="k") as k: - i2 = Qopt.shape[0] - i - k2 = Qopt.shape[2] - k - # For all actions - with hcl.for_(0, Qopt.shape[3], name="a") as a: - oldQ[0] = Qopt[i2,j,k2,a] - updateQopt(i2, j, k2, a, iVals, sVals, Qopt, actions, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newQ[0] = Qopt[i2,j,k2,a] - evaluateConvergence(newQ, oldQ, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - # For all states - with hcl.for_(0, Qopt.shape[0], name="i") as i: - with hcl.for_(1, Qopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Qopt.shape[2] + 1, name="k") as k: - j2 = Qopt.shape[1] - j - k2 = Qopt.shape[2] - k - # For all actions - with hcl.for_(0, Qopt.shape[3], name="a") as a: - oldQ[0] = Qopt[i,j2,k2,a] - updateQopt(i, j2, k2, a, iVals, sVals, Qopt, actions, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newQ[0] = Qopt[i,j2,k2,a] - evaluateConvergence(newQ, oldQ, epsilon, reSweep) - count[0] += 1 - - - ###################################### SETUP PLACEHOLDERS ###################################### - - hcl.init() - hcl.config.init_dtype = hcl.Float() - - # NOTE: trans is a tensor with size = maximum number of transitions - # NOTE: intermeds must have size [# possible actions] - # NOTE: transition must have size [# possible outcomes, #state dimensions + 1] - Qopt = hcl.placeholder(tuple(UD._ptsEachDim), name="Qopt", dtype=hcl.Float()) - gamma = hcl.placeholder((0,), "gamma") - count = hcl.placeholder((0,), "count") - epsilon = hcl.placeholder((0,), "epsilon") - actions = hcl.placeholder(tuple(UD._actions.shape), name="actions", dtype=hcl.Float()) - intermeds = hcl.placeholder(tuple([UD._actions.shape[0]]), name="intermeds", dtype=hcl.Float()) - trans = hcl.placeholder(tuple(UD._trans.shape), name="successors", dtype=hcl.Float()) - bounds = hcl.placeholder(tuple(UD._bounds.shape), name="bounds", dtype=hcl.Float()) - goal = hcl.placeholder(tuple(UD._goal.shape), name="goal", dtype=hcl.Float()) - ptsEachDim = hcl.placeholder(tuple([3]), name="ptsEachDim", dtype=hcl.Float()) - sVals = hcl.placeholder(tuple([3]), name="sVals", dtype=hcl.Float()) - iVals = hcl.placeholder(tuple([3]), name="iVals", dtype=hcl.Float()) - interpV = hcl.placeholder((0,), "interpV") - maxIters = hcl.placeholder((0,), "maxIters") - useNN = hcl.placeholder((0,), "useNN") - fillVal = hcl.placeholder((0,), "fillVal") - - # Create a static schedule -- graph - s = hcl.create_schedule([Qopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN, fillVal], solve_Qopt) - - - ########################################## INITIALIZE ########################################## - - # Convert the python array to hcl type array - Q_opt = hcl.asarray(np.zeros(UD._ptsEachDim)) - intermeds = hcl.asarray(np.ones(UD._actions.shape[0])) - trans = hcl.asarray(UD._trans) - gamma = hcl.asarray(UD._gamma) - epsilon = hcl.asarray(UD._epsilon) - count = hcl.asarray(np.zeros(1)) - actions = hcl.asarray(UD._actions) - bounds = hcl.asarray(UD._bounds) - goal = hcl.asarray(UD._goal) - ptsEachDim = hcl.asarray(UD._ptsEachDim) - sVals = hcl.asarray(np.zeros([3])) - iVals = hcl.asarray(np.zeros([3])) - interpV = hcl.asarray(np.zeros([1])) - maxIters = hcl.asarray(UD._maxIters) - useNN = hcl.asarray(UD._useNN) - fillVal = hcl.asarray(UD._fillVal) - - - ########################################### EXECUTE ############################################ - - # Use this graph and build an executable - f = hcl.build(s, target="llvm") - - t_s = time.time() - f(Q_opt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN, fillVal) - t_e = time.time() - - Q = Q_opt.asnumpy() - c = count.asnumpy() - - print() - print("Finished in ", int(c[0]), " iterations") - print("Took ", t_e-t_s, " seconds") - - dir_path = "./hcl_value_matrix_test/" - file_name = "hcl_value_iteration_Qvalue_" + str(int(c[0])) + "_iterations_by" + ("_Interpolation" if UD._useNN[0] == 0 else "_NN") - UD.writeResults(Q, dir_path, file_name, just_values=True) - - -# Test function -value_iteration_3D() diff --git a/odp/valueIteration/3D_value_iteration_test.py b/odp/valueIteration/3D_value_iteration_test.py deleted file mode 100644 index 11db6ebe..00000000 --- a/odp/valueIteration/3D_value_iteration_test.py +++ /dev/null @@ -1,71 +0,0 @@ -import numpy as np -import time - - -###################################### USER-DEFINED FUNCTIONS ###################################### - - -# return the successor states and their probabilities -def transition(state, action): - return( - ( (0.1, state), - (0.9, (state[0] + action[0], state[1] + action[1], state[2] + action[2])) - ) - ) - -# return the reward for taking action from state -def reward(state, action): - if state == (8,8,8): return 100 - else: return 1 - - - -######################################### VALUE ITERATION ########################################## - - -# Solve for Vopt -def solve_Vopt(Vopt, actions, gamma, epsilon, count): - reSweep = True - while (reSweep == True and count < 500): - reSweep = False - for i in range(0, Vopt.shape[0]): - for j in range(0, Vopt.shape[1]): - for k in range(0, Vopt.shape[2]): - oldV = Vopt[(i,j,k)] - newV = update_Vopt( (i,j,k), actions, Vopt, gamma ) - if (abs(newV-oldV) > epsilon): reSweep = True - count += 1 - return Vopt, count - -# Update Vopt[(state)] -def update_Vopt(state, actions, Vopt, gamma): - for action in actions: - updatedV = reward(state, action) - for probability, successor in transition(state, action): - if (successor[0] < Vopt.shape[0]) and (successor[1] < Vopt.shape[1]) and (successor[2] < Vopt.shape[2]): - updatedV += gamma * probability * Vopt[(successor)] - if (Vopt[(state)] < updatedV): - Vopt[(state)] = updatedV - return Vopt[(state)] - - - -############################################ INITIALIZE ############################################ - -Vopt = np.zeros([30, 30, 30]) -actions = ( (1,0,0), (0,1,0), (0,0,1) ) -gamma = 0.9 -epsilon = 0.0000005 -count = 0 - - -############################################# EXECUTE ############################################## - -t_s = time.time() -Vopt, count = solve_Vopt(Vopt, actions, gamma, epsilon, count) -t_e = time.time() - -print(Vopt) -print() -print("Finished in ", count, " iterations, ") -print("Took ", t_e-t_s, " seconds") diff --git a/odp/valueIteration/7D_value_iteration.py b/odp/valueIteration/7D_value_iteration.py deleted file mode 100644 index b1460d73..00000000 --- a/odp/valueIteration/7D_value_iteration.py +++ /dev/null @@ -1,329 +0,0 @@ -import heterocl as hcl -import numpy as np -import time -import odp.valueIteration.user_definer_7D as UD - - - -######################################### HELPER FUNCTIONS ######################################### - - -# Update the value function at position (i,j,k,l,m,n,o) -# iVals: holds index values (i,j,k,l,m,n,o) that correspond to state values (si,sj,sk,sl,sm,sn,so) -# intermeds: holds the estimated value associated with taking each action -# interpV: holds the estimated value of a successor state (linear interpolation only) -# gamma: discount factor -# ptsEachDim: the number of grid points in each dimension of the state space -# useNN: a mode flag (0: use linear interpolation, 1: use nearest neighbour) -def updateVopt(i, j, k, l, m, n, o, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN): - p = hcl.scalar(0, "p") - - with hcl.for_(0, actions.shape[0], name="a") as a: - # set iVals equal to (i,j,k,l,m,n,o) and sVals equal to the corresponding state values (si,sj,sk,sl,sm,sn,so) - updateStateVals(i, j, k, l, m, n, o, iVals, sVals, bounds, ptsEachDim) - # call the transition function to obtain the outcome(s) of action a from state (si,sj,sk,sl,sm,sn,so) - UD.transition(sVals, actions[a], bounds, trans, goal) - # initialize the value of the action Q value with the immediate reward of taking that action - intermeds[a] = UD.reward(sVals, actions[a], bounds, goal, trans) - # add the value of each possible successor state to the Q value - with hcl.for_(0, trans.shape[0], name="si") as si: - p[0] = trans[si,0] - sVals[0] = trans[si,1] - sVals[1] = trans[si,2] - sVals[2] = trans[si,3] - sVals[3] = trans[si,4] - sVals[4] = trans[si,5] - sVals[5] = trans[si,6] - sVals[6] = trans[si,7] - - # Nearest neighbour - with hcl.if_(useNN[0] == 1): - # convert the state values of the successor state (si,sj,sk,sl,sm,sn,so) into indeces (ia,ja,ka,la,ma,na,oa) - stateToIndex(sVals, iVals, bounds, ptsEachDim) - # if (ia,ja,ka,la,ma,na,oa) is within the state space, add its discounted value to the Q value - with hcl.if_(hcl.and_(iVals[0] < Vopt.shape[0], iVals[1] < Vopt.shape[1], iVals[2] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iVals[3] < Vopt.shape[3], iVals[4] < Vopt.shape[4], iVals[5] < Vopt.shape[5], iVals[6] < Vopt.shape[6])): - with hcl.if_(hcl.and_(iVals[0] >= 0, iVals[1] >= 0, iVals[2] >= 0, iVals[3] >= 0, iVals[4] >= 0, iVals[5] >= 0, iVals[6] >= 0)): - intermeds[a] += (gamma[0] * (p[0] * Vopt[iVals[0], iVals[1], iVals[2], iVals[3], iVals[4], iVals[5], iVals[6]])) - - # maximize over each Q value to obtain the optimal value - Vopt[i,j,k,l,m,n,o] = -1000000 - with hcl.for_(0, intermeds.shape[0], name="r") as r: - with hcl.if_(Vopt[i,j,k,l,m,n,o] < intermeds[r]): - Vopt[i,j,k,l,m,n,o] = intermeds[r] - - -# Returns 0 if convergence has been reached -def evaluateConvergence(newV, oldV, epsilon, reSweep): - delta = hcl.scalar(0, "delta") - # Calculate the difference, if it's negative, make it positive - delta[0] = newV[0] - oldV[0] - with hcl.if_(delta[0] < 0): - delta[0] = delta[0] * -1 - with hcl.if_(delta[0] > epsilon[0]): - reSweep[0] = 1 - - -# Converts state values into indeces using nearest neighbour rounding -def stateToIndex(sVals, iVals, bounds, ptsEachDim): - iVals[0] = ((sVals[0] - bounds[0,0]) / (bounds[0,1] - bounds[0,0])) * (ptsEachDim[0] - 1) - iVals[1] = ((sVals[1] - bounds[1,0]) / (bounds[1,1] - bounds[1,0])) * (ptsEachDim[1] - 1) - iVals[2] = ((sVals[2] - bounds[2,0]) / (bounds[2,1] - bounds[2,0])) * (ptsEachDim[2] - 1) - iVals[3] = ((sVals[3] - bounds[3,0]) / (bounds[3,1] - bounds[3,0])) * (ptsEachDim[3] - 1) - iVals[4] = ((sVals[4] - bounds[4,0]) / (bounds[4,1] - bounds[4,0])) * (ptsEachDim[4] - 1) - iVals[5] = ((sVals[5] - bounds[5,0]) / (bounds[5,1] - bounds[5,0])) * (ptsEachDim[5] - 1) - iVals[6] = ((sVals[6] - bounds[6,0]) / (bounds[6,1] - bounds[6,0])) * (ptsEachDim[6] - 1) - # NOTE: add 0.5 to simulate rounding - iVals[0] = hcl.cast(hcl.Int(), iVals[0] + 0.5) - iVals[1] = hcl.cast(hcl.Int(), iVals[1] + 0.5) - iVals[2] = hcl.cast(hcl.Int(), iVals[2] + 0.5) - iVals[3] = hcl.cast(hcl.Int(), iVals[3] + 0.5) - iVals[4] = hcl.cast(hcl.Int(), iVals[4] + 0.5) - iVals[5] = hcl.cast(hcl.Int(), iVals[5] + 0.5) - iVals[6] = hcl.cast(hcl.Int(), iVals[6] + 0.5) - - -# Convert indices into state values -def indexToState(iVals, sVals, bounds, ptsEachDim): - sVals[0] = bounds[0,0] + ( (bounds[0,1] - bounds[0,0]) * (iVals[0] / (ptsEachDim[0]-1)) ) - sVals[1] = bounds[1,0] + ( (bounds[1,1] - bounds[1,0]) * (iVals[1] / (ptsEachDim[1]-1)) ) - sVals[2] = bounds[2,0] + ( (bounds[2,1] - bounds[2,0]) * (iVals[2] / (ptsEachDim[2]-1)) ) - sVals[3] = bounds[3,0] + ( (bounds[3,1] - bounds[3,0]) * (iVals[3] / (ptsEachDim[3]-1)) ) - sVals[4] = bounds[4,0] + ( (bounds[4,1] - bounds[4,0]) * (iVals[4] / (ptsEachDim[4]-1)) ) - sVals[5] = bounds[5,0] + ( (bounds[5,1] - bounds[5,0]) * (iVals[5] / (ptsEachDim[5]-1)) ) - sVals[6] = bounds[6,0] + ( (bounds[6,1] - bounds[6,0]) * (iVals[6] / (ptsEachDim[6]-1)) ) - - -# Sets iVals equal to (i,j,k,l,m,n,o) and sVals equal to the corresponding state values -def updateStateVals(i, j, k, l, m, n, o, iVals, sVals, bounds, ptsEachDim): - iVals[0] = i - iVals[1] = j - iVals[2] = k - iVals[3] = l - iVals[4] = m - iVals[5] = n - iVals[6] = o - indexToState(iVals, sVals, bounds, ptsEachDim) - - - -######################################### VALUE ITERATION ########################################## - - -# Main value iteration algorithm -# reSweep: a convergence flag (1: continue iterating, 0: convergence reached) -# epsilon: convergence criteria -# maxIters: maximum number of iterations that can occur without convergence being reached -# count: the number of iterations that have been performed -def value_iteration_7D(): - def solve_Vopt(Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN): - reSweep = hcl.scalar(1, "reSweep") - oldV = hcl.scalar(0, "oldV") - newV = hcl.scalar(0, "newV") - with hcl.while_(hcl.and_(reSweep[0] == 1, count[0] < maxIters[0])): - reSweep[0] = 0 - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - with hcl.for_(0, Vopt.shape[6], name="o") as o: - oldV[0] = Vopt[i,j,k,l,m,n,o] - updateVopt(i, j, k, l, m, n, o, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k,l,m,n,o] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - with hcl.for_(0, Vopt.shape[6], name="o") as o: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j2,k2,l,m,n,o] - updateVopt(i2, j2, k2, l, m, n, o, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k2,l,m,n,o] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - with hcl.for_(0, Vopt.shape[6], name="o") as o: - i2 = Vopt.shape[0] - i - oldV[0] = Vopt[i2,j,k,l,m,n,o] - updateVopt(i2, j, k, l, m, n, o, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k,l,m,n,o] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - with hcl.for_(0, Vopt.shape[6], name="o") as o: - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i,j2,k,l,m,n,o] - updateVopt(i, j2, k, l, m, n, o, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k,l,m,n,o] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - with hcl.for_(0, Vopt.shape[6], name="o") as o: - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j,k2,l,m,n,o] - updateVopt(i, j, k2, l, m, n, o, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k2,l,m,n,o] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - with hcl.for_(0, Vopt.shape[6], name="o") as o: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i2,j2,k,l,m,n,o] - updateVopt(i2, j2, k, l, m, n, o, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k,l,m,n,o] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - with hcl.for_(0, Vopt.shape[6], name="o") as o: - i2 = Vopt.shape[0] - i - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j,k2,l,m,n,o] - updateVopt(i2, j, k2, l, m, n, o, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k2,l,m,n,o] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - with hcl.for_(0, Vopt.shape[6], name="o") as o: - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j2,k2,l,m,n,o] - updateVopt(i, j2, k2, l, m, n, o, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k2,l,m,n,o] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - - - ###################################### SETUP PLACEHOLDERS ###################################### - - # Initialize the HCL environment - hcl.init() - hcl.config.init_dtype = hcl.Float() - - # NOTE: trans is a tensor with size = maximum number of transitions - # NOTE: intermeds must have size [# possible actions] - # NOTE: transition must have size [# possible outcomes, #state dimensions + 1] - Vopt = hcl.placeholder(tuple(UD._ptsEachDim), name="Vopt", dtype=hcl.Float()) - gamma = hcl.placeholder((0,), "gamma") - count = hcl.placeholder((0,), "count") - maxIters = hcl.placeholder((0,), "maxIters") - epsilon = hcl.placeholder((0,), "epsilon") - actions = hcl.placeholder(tuple(UD._actions.shape), name="actions", dtype=hcl.Float()) - intermeds = hcl.placeholder(tuple([UD._actions.shape[0]]), name="intermeds", dtype=hcl.Float()) - trans = hcl.placeholder(tuple(UD._trans.shape), name="successors", dtype=hcl.Float()) - bounds = hcl.placeholder(tuple(UD._bounds.shape), name="bounds", dtype=hcl.Float()) - goal = hcl.placeholder(tuple(UD._goal.shape), name="goal", dtype=hcl.Float()) - ptsEachDim = hcl.placeholder(tuple([7]), name="ptsEachDim", dtype=hcl.Float()) - sVals = hcl.placeholder(tuple([7]), name="sVals", dtype=hcl.Float()) - iVals = hcl.placeholder(tuple([7]), name="iVals", dtype=hcl.Float()) - interpV = hcl.placeholder((0,), "interpols") - useNN = hcl.placeholder((0,), "useNN") - - # Create a static schedule -- graph - s = hcl.create_schedule([Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN], solve_Vopt) - - - ########################################## INITIALIZE ########################################## - - # Convert the python array to hcl type array - V_opt = hcl.asarray(np.zeros(UD._ptsEachDim)) - intermeds = hcl.asarray(np.ones(UD._actions.shape[0])) - trans = hcl.asarray(UD._trans) - gamma = hcl.asarray(UD._gamma) - epsilon = hcl.asarray(UD._epsilon) - count = hcl.asarray(np.zeros(1)) - maxIters = hcl.asarray(UD._maxIters) - actions = hcl.asarray(UD._actions) - bounds = hcl.asarray(UD._bounds) - goal = hcl.asarray(UD._goal) - ptsEachDim = hcl.asarray(UD._ptsEachDim) - sVals = hcl.asarray(np.zeros([7])) - iVals = hcl.asarray(np.zeros([7])) - interpV = hcl.asarray(np.zeros([1])) - useNN = hcl.asarray(UD._useNN) - - # Use this graph and build an executable - f = hcl.build(s, target="llvm") - - - ########################################### EXECUTE ############################################ - - # Now use the executable - t_s = time.time() - f(V_opt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN) - t_e = time.time() - - V = V_opt.asnumpy() - c = count.asnumpy() - print("Finished in ", int(c[0]), " iterations") - print("Took ", t_e-t_s, " seconds") - - # Write results to file - dir_path = "./hcl_value_matrix_test/" - file_name = "hcl_value_iteration_7D_" + str(int(c[0])) + "_iterations_by" + ("_Interpolation" if UD._useNN[0] == 0 else "_NN") - UD.writeResults(V, dir_path, file_name, just_values=False) - - -# Call the function -value_iteration_7D() diff --git a/odp/valueIteration/__init__.py b/odp/valueIteration/__init__.py deleted file mode 100644 index a6a89bc3..00000000 --- a/odp/valueIteration/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from odp.valueIteration.value_iteration_3D import value_iteration_3D -from odp.valueIteration.value_iteration_4D import value_iteration_4D -from odp.valueIteration.value_iteration_5D import value_iteration_5D -from odp.valueIteration.value_iteration_6D import value_iteration_6D \ No newline at end of file diff --git a/odp/valueIteration/user_definer_3D_Q.py b/odp/valueIteration/user_definer_3D_Q.py deleted file mode 100644 index c2478b8f..00000000 --- a/odp/valueIteration/user_definer_3D_Q.py +++ /dev/null @@ -1,49 +0,0 @@ -import numpy as np -import os - -_bounds = np.array([[-5.0, 5.0],[-5.0, 5.0],[-3.1415, 3.1415]]) -_ptsEachDim = np.array([25, 25, 9, 81]) -_goal = np.array([[3.5, 3.5], [1.5707, 2.3562]]) - -# set _actions based on ranges and number of steps -# format: range(lower bound, upper bound, number of steps) -vValues = np.linspace(-2, 2, 9) -wValues = np.linspace(-1, 1, 9) -_actions = [] -for i in vValues: - for j in wValues: - _actions.append((i,j)) -_actions = np.array(_actions) - -_gamma = np.array([0.93]) -_epsilon = np.array([.3]) -_maxIters = np.array([500]) -_trans = np.zeros([1, 4]) # size: [maximum number of transition states available x 4] -_useNN = np.array([0]) -_fillVal = np.array([-400]) # Fill Value for linear interpolation - -# Write results to file -def writeResults(V, dir_path, file_name, just_values=False): - # Create directory for results if one does not exist - print("\nRecording results") - try: - os.mkdir(dir_path) - print("Created directory: ", dir_path) - except: - print("Writing to: '", dir_path, "'") - # Open file and write results - f = open(dir_path + file_name, "w") - for k in range(V.shape[2]): - for i in range(V.shape[0]): - for j in range(V.shape[1]): - s = "" - if not just_values: - si = (( i / (_ptsEachDim[0] - 1) ) * (_bounds[0,1] - _bounds[0,0])) + _bounds[0,0] - sj = (( j / (_ptsEachDim[1] - 1) ) * (_bounds[1,1] - _bounds[1,0])) + _bounds[1,0] - sk = (( k / (_ptsEachDim[2] - 1) ) * (_bounds[2,1] - _bounds[2,0])) + _bounds[2,0] - state = ("{:.4f}".format(si), "{:.4f}".format(sj), "{:.4f}".format(sk)) - s = str(state) + " " + str(max(V[(i,j,k)])) + '\n' - else: - s = str("{:.4f}".format(max(V[(i,j,k)]))) + ',\n' - f.write(s) - print("Finished recording results") diff --git a/odp/valueIteration/user_definer_7D.py b/odp/valueIteration/user_definer_7D.py deleted file mode 100644 index c56606b8..00000000 --- a/odp/valueIteration/user_definer_7D.py +++ /dev/null @@ -1,57 +0,0 @@ -import numpy as np -import os -import MDP.Example_7D as MDP -import valueIteration as VI - - -myProblem = MDP.MDP_7D_example() - -_bounds = myProblem._bounds -_ptsEachDim = myProblem._ptsEachDim -_goal = myProblem._goal -_actions = myProblem._actions -_gamma = myProblem._gamma -_epsilon = myProblem._epsilon -_maxIters = myProblem._maxIters -_trans = myProblem._trans -_useNN = myProblem._useNN - -transition = myProblem.transition -reward = myProblem.reward - - -def writeResults(V, dir_path, file_name, just_values=False): - # Create directory for results if one does not exist - print("\nRecording results") - try: - os.mkdir(dir_path) - print("Created directory: ", dir_path) - except: - print("Writing to: '", dir_path, "'") - # Open file and write results - f = open(dir_path + file_name, "w") - for i in range(V.shape[0]): - for j in range(V.shape[1]): - for k in range(V.shape[2]): - for l in range(V.shape[3]): - for m in range(V.shape[4]): - for n in range(V.shape[5]): - for o in range(V.shape[6]): - s = "" - if not just_values: - si = (( i / (_ptsEachDim[0] - 1) ) * (_bounds[0,1] - _bounds[0,0])) + _bounds[0,0] - sj = (( j / (_ptsEachDim[1] - 1) ) * (_bounds[1,1] - _bounds[1,0])) + _bounds[1,0] - sk = (( k / (_ptsEachDim[2] - 1) ) * (_bounds[2,1] - _bounds[2,0])) + _bounds[2,0] - sl = (( l / (_ptsEachDim[3] - 1) ) * (_bounds[3,1] - _bounds[3,0])) + _bounds[3,0] - sm = (( m / (_ptsEachDim[4] - 1) ) * (_bounds[4,1] - _bounds[4,0])) + _bounds[4,0] - sn = (( n / (_ptsEachDim[5] - 1) ) * (_bounds[5,1] - _bounds[5,0])) + _bounds[5,0] - so = (( o / (_ptsEachDim[6] - 1) ) * (_bounds[6,1] - _bounds[6,0])) + _bounds[6,0] - - state = ("{:.4f}".format(si), "{:.4f}".format(sj), "{:.4f}".format(sk), - "{:.4f}".format(sl), "{:.4f}".format(sm), "{:.4f}".format(sn), "{:.4f}".format(so)) - s = str(state) + " " + str("{:.4f}".format(V[(i,j,k,l,m,n,o)])) + '\n' - else: - s = str("{:.4f}".format(V[(i,j,k,l,m,n,o)])) + ',\n' - f.write(s) - print("Finished recording results") - \ No newline at end of file diff --git a/odp/valueIteration/value_iteration_3D.py b/odp/valueIteration/value_iteration_3D.py deleted file mode 100644 index d3320b63..00000000 --- a/odp/valueIteration/value_iteration_3D.py +++ /dev/null @@ -1,337 +0,0 @@ -import heterocl as hcl -import numpy as np - -######################################### HELPER FUNCTIONS ######################################### - - -# Update the value function at position (i,j,k) -# iVals: holds index values (i,j,k) that correspond to state values (si,sj,sk) -# intermeds: holds the estimated value associated with taking each action -# interpV: holds the estimated value of a successor state (linear interpolation only) -# gamma: discount factor -# ptsEachDim: the number of grid points in each dimension of the state space -# useNN: a mode flag (0: use linear interpolation, 1: use nearest neighbour) -def updateVopt(obj, i, j, k, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal): - p = hcl.scalar(0, "p") - - with hcl.for_(0, actions.shape[0], name="a") as a: - # set iVals equal to (i,j,k) and sVals equal to the corresponding state values (si,sj,sk) - updateStateVals(i, j, k, iVals, sVals, bounds, ptsEachDim) - # call the transition function to obtain the outcome(s) of action a from state (si,sj,sk) - obj.transition(sVals, actions[a], bounds, trans, goal) - # initialize the value of the action using the immediate reward of taking that action - intermeds[a] = obj.reward(sVals, actions[a], bounds, goal, trans) - Vopt[i,j,k] = intermeds[a] - # add the value of each possible successor state to the estimated value of taking action a - with hcl.for_(0, trans.shape[0], name="si") as si: - p[0] = trans[si,0] - sVals[0] = trans[si,1] - sVals[1] = trans[si,2] - sVals[2] = trans[si,3] - # Nearest neighbour - with hcl.if_(useNN[0] == 1): - # convert the state values of the successor state (si,sj,sk) into indeces (ia,ij,ik) - stateToIndex(sVals, iVals, bounds, ptsEachDim) - # if (ia, ij, ik) is within the state space, add its discounted value to action a - with hcl.if_(hcl.and_(iVals[0] < Vopt.shape[0], iVals[1] < Vopt.shape[1], iVals[2] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iVals[0] >= 0, iVals[1] >= 0, iVals[2] >= 0)): - intermeds[a] += (gamma[0] * (p[0] * Vopt[iVals[0], iVals[1], iVals[2]])) - # Linear interpolation - with hcl.if_(useNN[0] == 0): - # if (sia, sja, ska) is within the state space, add its discounted value to action a - with hcl.if_(hcl.and_(sVals[0] <= bounds[0,1], sVals[1] <= bounds[1,1], sVals[2] <= bounds[2,1])): - with hcl.if_(hcl.and_(sVals[0] >= bounds[0,0], sVals[1] >= bounds[1,0], sVals[2] >= bounds[2,0])): - stateToIndexInterpolants(Vopt, sVals, bounds, ptsEachDim, interpV, fillVal) - intermeds[a] += (gamma[0] * (p[0] * interpV[0])) - # maximize over each possible action in intermeds to obtain the optimal value - with hcl.for_(0, intermeds.shape[0], name="r") as r: - with hcl.if_(Vopt[i,j,k] < intermeds[r]): - Vopt[i,j,k] = intermeds[r] - - -# Returns 0 if convergence has been reached -def evaluateConvergence(newV, oldV, epsilon, reSweep): - delta = hcl.scalar(0, "delta") - # Calculate the difference, if it's negative, make it positive - delta[0] = newV[0] - oldV[0] - with hcl.if_(delta[0] < 0): - delta[0] = delta[0] * -1 - with hcl.if_(delta[0] > epsilon[0]): - reSweep[0] = 1 - - -# _bounds = np.array([[-5.0, 5.0],[-5.0, 5.0],[-3.1415, 3.1415]]) -# convert state values into indeces using nearest neighbour -def stateToIndex(sVals, iVals, bounds, ptsEachDim): - iVals[0] = ((sVals[0] - bounds[0,0]) / (bounds[0,1] - bounds[0,0])) * (ptsEachDim[0] - 1) - iVals[1] = ((sVals[1] - bounds[1,0]) / (bounds[1,1] - bounds[1,0])) * (ptsEachDim[1] - 1) - iVals[2] = ((sVals[2] - bounds[2,0]) / (bounds[2,1] - bounds[2,0])) * (ptsEachDim[2] - 1) - # NOTE: add 0.5 to simulate rounding - iVals[0] = hcl.cast(hcl.Int(), iVals[0] + 0.5) - iVals[1] = hcl.cast(hcl.Int(), iVals[1] + 0.5) - iVals[2] = hcl.cast(hcl.Int(), iVals[2] + 0.5) - - -# given state values sVals, obtain the 8 possible successor states and their corresponding weight -def stateToIndexInterpolants(Vopt, sVals, bounds, ptsEachDim, interpV, fillVal): - iMin = hcl.scalar(0, "iMin") - jMin = hcl.scalar(0, "jMin") - kMin = hcl.scalar(0, "kMin") - iMax = hcl.scalar(0, "iMax") - jMax = hcl.scalar(0, "jMax") - kMax = hcl.scalar(0, "kMax") - c000 = hcl.scalar(fillVal[0], "c000") - c001 = hcl.scalar(fillVal[0], "c001") - c010 = hcl.scalar(fillVal[0], "c010") - c011 = hcl.scalar(fillVal[0], "c011") - c100 = hcl.scalar(fillVal[0], "c100") - c101 = hcl.scalar(fillVal[0], "c101") - c110 = hcl.scalar(fillVal[0], "c110") - c111 = hcl.scalar(fillVal[0], "c111") - c00 = hcl.scalar(0, "c00") - c01 = hcl.scalar(0, "c01") - c10 = hcl.scalar(0, "c10") - c11 = hcl.scalar(0, "c11") - c0 = hcl.scalar(0, "c0") - c1 = hcl.scalar(0, "c1") - ia = hcl.scalar(0, "ia") - ja = hcl.scalar(0, "ja") - ka = hcl.scalar(0, "ka") - di = hcl.scalar(0, "di") - dj = hcl.scalar(0, "dj") - dk = hcl.scalar(0, "dk") - - # obtain unrounded index values - ia[0] = ((sVals[0] - bounds[0,0]) / (bounds[0,1] - bounds[0,0])) * (ptsEachDim[0] - 1) - ja[0] = ((sVals[1] - bounds[1,0]) / (bounds[1,1] - bounds[1,0])) * (ptsEachDim[1] - 1) - ka[0] = ((sVals[2] - bounds[2,0]) / (bounds[2,1] - bounds[2,0])) * (ptsEachDim[2] - 1) - - # obtain neighbouring state indeces in each direction - with hcl.if_(ia[0] < 0): - iMin[0] = hcl.cast(hcl.Int(), ia[0] - 1.0) - iMax[0] = hcl.cast(hcl.Int(), ia[0]) - with hcl.else_(): - iMin[0] = hcl.cast(hcl.Int(), ia[0]) - iMax[0] = hcl.cast(hcl.Int(), ia[0] + 1.0) - with hcl.if_(ja[0] < 0): - jMin[0] = hcl.cast(hcl.Int(), ja[0] - 1.0) - jMax[0] = hcl.cast(hcl.Int(), ja[0]) - with hcl.else_(): - jMin[0] = hcl.cast(hcl.Int(), ja[0]) - jMax[0] = hcl.cast(hcl.Int(), ja[0] + 1.0) - with hcl.if_(ka[0] < 0): - kMin[0] = hcl.cast(hcl.Int(), ka[0] - 1.0) - kMax[0] = hcl.cast(hcl.Int(), ka[0]) - with hcl.else_(): - kMin[0] = hcl.cast(hcl.Int(), ka[0]) - kMax[0] = hcl.cast(hcl.Int(), ka[0] + 1.0) - - # obtain weights in each direction - di[0] = ia[0] - iMin[0] - dj[0] = ja[0] - jMin[0] - dk[0] = ka[0] - kMin[0] - - # Obtain value of each neighbour state - # Vopt[iMin, jMin, kMin] - with hcl.if_(hcl.and_(iMin[0] < Vopt.shape[0], jMin[0] < Vopt.shape[1], kMin[0] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iMin[0] >= 0, jMin[0] >= 0, kMin[0] >= 0)): - c000[0] = Vopt[iMin[0], jMin[0], kMin[0]] - # Vopt[iMin, jMin, kMax] - with hcl.if_(hcl.and_(iMin[0] < Vopt.shape[0], jMin[0] < Vopt.shape[1], kMax[0] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iMin[0] >= 0, jMin[0] >= 0, kMax[0] >= 0)): - c001[0] = Vopt[iMin[0], jMin[0], kMax[0]] - # Vopt[iMin, jMax, kMin] - with hcl.if_(hcl.and_(iMin[0] < Vopt.shape[0], jMax[0] < Vopt.shape[1], kMin[0] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iMin[0] >= 0, jMax[0] >= 0, kMin[0] >= 0)): - c010[0] = Vopt[iMin[0], jMax[0], kMin[0]] - # Vopt[iMin, jMax, kMax] - with hcl.if_(hcl.and_(iMin[0] < Vopt.shape[0], jMax[0] < Vopt.shape[1], kMax[0] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iMin[0] >= 0, jMax[0] >= 0, kMax[0] >= 0)): - c011[0] = Vopt[iMin[0], jMax[0], kMax[0]] - # Vopt[iMax, jMin, kMin] - with hcl.if_(hcl.and_(iMax[0] < Vopt.shape[0], jMin[0] < Vopt.shape[1], kMin[0] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iMax[0] >= 0, jMin[0] >= 0, kMin[0] >= 0)): - c100[0] = Vopt[iMax[0], jMin[0], kMin[0]] - # Vopt[iMax, jMin, kMax] - with hcl.if_(hcl.and_(iMax[0] < Vopt.shape[0], jMin[0] < Vopt.shape[1], kMax[0] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iMax[0] >= 0, jMin[0] >= 0, kMax[0] >= 0)): - c101[0] = Vopt[iMax[0], jMin[0], kMax[0]] - # Vopt[iMax, jMax, kMin] - with hcl.if_(hcl.and_(iMax[0] < Vopt.shape[0], jMax[0] < Vopt.shape[1], kMin[0] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iMax[0] >= 0, jMax[0] >= 0, kMin[0] >= 0)): - c110[0] = Vopt[iMax[0], jMax[0], kMin[0]] - # Vopt[iMax, jMax, kMax] - with hcl.if_(hcl.and_(iMax[0] < Vopt.shape[0], jMax[0] < Vopt.shape[1], kMax[0] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iMax[0] >= 0, jMax[0] >= 0, kMax[0] >= 0)): - c111[0] = Vopt[iMax[0], jMax[0], kMax[0]] - - # perform linear interpolation - c00[0] = (c000[0] * (1-di[0])) + (c100[0] * di[0]) - c01[0] = (c001[0] * (1-di[0])) + (c101[0] * di[0]) - c10[0] = (c010[0] * (1-di[0])) + (c110[0] * di[0]) - c11[0] = (c011[0] * (1-di[0])) + (c111[0] * di[0]) - c0[0] = (c00[0] * (1-dj[0])) + (c10[0] * dj[0]) - c1[0] = (c01[0] * (1-dj[0])) + (c11[0] * dj[0]) - interpV[0] = (c0[0] * (1-dk[0])) + (c1[0] * dk[0]) - - -# convert indices into state values -def indexToState(iVals, sVals, bounds, ptsEachDim): - sVals[0] = bounds[0,0] + ( (bounds[0,1] - bounds[0,0]) * (iVals[0] / (ptsEachDim[0]-1)) ) - sVals[1] = bounds[1,0] + ( (bounds[1,1] - bounds[1,0]) * (iVals[1] / (ptsEachDim[1]-1)) ) - sVals[2] = bounds[2,0] + ( (bounds[2,1] - bounds[2,0]) * (iVals[2] / (ptsEachDim[2]-1)) ) - - -# set iVals equal to (i,j,k) and sVals equal to the corresponding state values at (i,j,k) -def updateStateVals(i, j, k, iVals, sVals, bounds, ptsEachDim): - iVals[0] = i - iVals[1] = j - iVals[2] = k - indexToState(iVals, sVals, bounds, ptsEachDim) - - - -######################################### VALUE ITERATION ########################################## - - -# Main value iteration algorithm -# reSweep: a convergence flag (1: continue iterating, 0: convergence reached) -# epsilon: convergence criteria -# maxIters: maximum number of iterations that can occur without convergence being reached -# count: the number of iterations that have been performed -def value_iteration_3D(MDP_object): - def solve_Vopt(Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN, fillVal): - reSweep = hcl.scalar(1, "reSweep") - oldV = hcl.scalar(0, "oldV") - newV = hcl.scalar(0, "newV") - with hcl.while_(hcl.and_(reSweep[0] == 1, count[0] < maxIters[0])): - reSweep[0] = 0 - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - oldV[0] = Vopt[i,j,k] - updateVopt(MDP_object, i, j, k, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newV[0] = Vopt[i,j,k] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j2,k2] - updateVopt(MDP_object, i2, j2, k2, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newV[0] = Vopt[i2,j2,k2] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - i2 = Vopt.shape[0] - i - oldV[0] = Vopt[i2,j,k] - updateVopt(MDP_object, i2, j, k, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newV[0] = Vopt[i2,j,k] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i,j2,k] - updateVopt(MDP_object, i, j2, k, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newV[0] = Vopt[i,j2,k] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j,k2] - updateVopt(MDP_object, i, j, k2, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newV[0] = Vopt[i,j,k2] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i2,j2,k] - updateVopt(MDP_object, i2, j2, k, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newV[0] = Vopt[i2,j2,k] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - i2 = Vopt.shape[0] - i - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j,k2] - updateVopt(MDP_object, i2, j, k2, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newV[0] = Vopt[i2,j,k2] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j2,k2] - updateVopt(MDP_object, i, j2, k2, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN, fillVal) - newV[0] = Vopt[i,j2,k2] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - - - ###################################### SETUP PLACEHOLDERS ###################################### - - - # NOTE: trans is a tensor with size = maximum number of transitions - # NOTE: intermeds must have size [# possible actions] - # NOTE: transition must have size [# possible outcomes, #state dimensions + 1] - Vopt = hcl.placeholder(tuple(MDP_object._ptsEachDim), name="Vopt", dtype=hcl.Float()) - gamma = hcl.placeholder((0,), "gamma") - count = hcl.placeholder((0,), "count") - maxIters = hcl.placeholder((0,), "maxIters") - epsilon = hcl.placeholder((0,), "epsilon") - actions = hcl.placeholder(tuple(MDP_object._actions.shape), name="actions", dtype=hcl.Float()) - intermeds = hcl.placeholder(tuple([MDP_object._actions.shape[0]]), name="intermeds", dtype=hcl.Float()) - trans = hcl.placeholder(tuple(MDP_object._trans.shape), name="successors", dtype=hcl.Float()) - bounds = hcl.placeholder(tuple(MDP_object._bounds.shape), name="bounds", dtype=hcl.Float()) - goal = hcl.placeholder(tuple(MDP_object._goal.shape), name="goal", dtype=hcl.Float()) - ptsEachDim = hcl.placeholder(tuple([3]), name="ptsEachDim", dtype=hcl.Float()) - sVals = hcl.placeholder(tuple([3]), name="sVals", dtype=hcl.Float()) - iVals = hcl.placeholder(tuple([3]), name="iVals", dtype=hcl.Float()) - interpV = hcl.placeholder((0,), "interpV") - useNN = hcl.placeholder((0,), "useNN") - fillVal = hcl.placeholder((0,), "fillVal") - - # Create a static schedule -- graph - s = hcl.create_schedule([Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN, fillVal], solve_Vopt) - - # Use this graph and build an executable - return hcl.build(s) #target="llvm") \ No newline at end of file diff --git a/odp/valueIteration/value_iteration_4D.py b/odp/valueIteration/value_iteration_4D.py deleted file mode 100644 index 6fccb9a6..00000000 --- a/odp/valueIteration/value_iteration_4D.py +++ /dev/null @@ -1,245 +0,0 @@ -import heterocl as hcl -import numpy as np - -######################################### HELPER FUNCTIONS ######################################### - - -# Update the value function at position (i,j,k,l) -# iVals: holds index values (i,j,k,l) that correspond to state values (si,sj,sk,sl) -# intermeds: holds the estimated value associated with taking each action -# interpV: holds the estimated value of a successor state (linear interpolation only) -# gamma: discount factor -# ptsEachDim: the number of grid points in each dimension of the state space -# useNN: a mode flag (0: use linear interpolation, 1: use nearest neighbour) -def updateVopt(obj, i, j, k, l, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN): - p = hcl.scalar(0, "p") - - with hcl.for_(0, actions.shape[0], name="a") as a: - # set iVals equal to (i,j,k,l) and sVals equal to the corresponding state values (si,sj,sk,sl) - updateStateVals(i, j, k, l, iVals, sVals, bounds, ptsEachDim) - # call the transition function to obtain the outcome(s) of action a from state (si,sj,sk,sl) - obj.transition(sVals, actions[a], bounds, trans, goal) - # initialize the value of the action Q value with the immediate reward of taking that action - intermeds[a] = obj.reward(sVals, actions[a], bounds, goal, trans) - # add the value of each possible successor state to the Q value - with hcl.for_(0, trans.shape[0], name="si") as si: - p[0] = trans[si,0] - sVals[0] = trans[si,1] - sVals[1] = trans[si,2] - sVals[2] = trans[si,3] - sVals[3] = trans[si,4] - - # Nearest neighbour - with hcl.if_(useNN[0] == 1): - # convert the state values of the successor state (si,sj,sk,sl) into indeces (ia,ja,ka,la) - stateToIndex(sVals, iVals, bounds, ptsEachDim) - # if (ia,ja,ka,la) is within the state space, add its discounted value to the Q value - with hcl.if_(hcl.and_(iVals[0] < Vopt.shape[0], iVals[1] < Vopt.shape[1], iVals[2] < Vopt.shape[2], iVals[3] < Vopt.shape[3])): - with hcl.if_(hcl.and_(iVals[0] >= 0, iVals[1] >= 0, iVals[2] >= 0, iVals[3] >= 0)): - intermeds[a] += (gamma[0] * (p[0] * Vopt[iVals[0], iVals[1], iVals[2], iVals[3]])) - - # maximize over each Q value to obtain the optimal value - Vopt[i,j,k,l] = -1000000 - with hcl.for_(0, intermeds.shape[0], name="r") as r: - with hcl.if_(Vopt[i,j,k,l] < intermeds[r]): - Vopt[i,j,k,l] = intermeds[r] - - -# Returns 0 if convergence has been reached -def evaluateConvergence(newV, oldV, epsilon, reSweep): - delta = hcl.scalar(0, "delta") - # Calculate the difference, if it's negative, make it positive - delta[0] = newV[0] - oldV[0] - with hcl.if_(delta[0] < 0): - delta[0] = delta[0] * -1 - with hcl.if_(delta[0] > epsilon[0]): - reSweep[0] = 1 - - -# Converts state values into indeces using nearest neighbour rounding -def stateToIndex(sVals, iVals, bounds, ptsEachDim): - iVals[0] = ((sVals[0] - bounds[0,0]) / (bounds[0,1] - bounds[0,0])) * (ptsEachDim[0] - 1) - iVals[1] = ((sVals[1] - bounds[1,0]) / (bounds[1,1] - bounds[1,0])) * (ptsEachDim[1] - 1) - iVals[2] = ((sVals[2] - bounds[2,0]) / (bounds[2,1] - bounds[2,0])) * (ptsEachDim[2] - 1) - iVals[3] = ((sVals[3] - bounds[3,0]) / (bounds[3,1] - bounds[3,0])) * (ptsEachDim[3] - 1) - # NOTE: add 0.5 to simulate rounding - iVals[0] = hcl.cast(hcl.Int(), iVals[0] + 0.5) - iVals[1] = hcl.cast(hcl.Int(), iVals[1] + 0.5) - iVals[2] = hcl.cast(hcl.Int(), iVals[2] + 0.5) - iVals[3] = hcl.cast(hcl.Int(), iVals[3] + 0.5) - - -# Convert indices into state values -def indexToState(iVals, sVals, bounds, ptsEachDim): - sVals[0] = bounds[0,0] + ( (bounds[0,1] - bounds[0,0]) * (iVals[0] / (ptsEachDim[0]-1)) ) - sVals[1] = bounds[1,0] + ( (bounds[1,1] - bounds[1,0]) * (iVals[1] / (ptsEachDim[1]-1)) ) - sVals[2] = bounds[2,0] + ( (bounds[2,1] - bounds[2,0]) * (iVals[2] / (ptsEachDim[2]-1)) ) - sVals[3] = bounds[3,0] + ( (bounds[3,1] - bounds[3,0]) * (iVals[3] / (ptsEachDim[3]-1)) ) - - -# Sets iVals equal to (i,j,k,l) and sVals equal to the corresponding state values -def updateStateVals(i, j, k, l, iVals, sVals, bounds, ptsEachDim): - iVals[0] = i - iVals[1] = j - iVals[2] = k - iVals[3] = l - indexToState(iVals, sVals, bounds, ptsEachDim) - - - -######################################### VALUE ITERATION ########################################## - - -# Main value iteration algorithm -# reSweep: a convergence flag (1: continue iterating, 0: convergence reached) -# epsilon: convergence criteria -# maxIters: maximum number of iterations that can occur without convergence being reached -# count: the number of iterations that have been performed -def value_iteration_4D(MDP_object): - def solve_Vopt(Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN): - reSweep = hcl.scalar(1, "reSweep") - oldV = hcl.scalar(0, "oldV") - newV = hcl.scalar(0, "newV") - with hcl.while_(hcl.and_(reSweep[0] == 1, count[0] < maxIters[0])): - reSweep[0] = 0 - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - oldV[0] = Vopt[i,j,k,l] - updateVopt(MDP_object, i, j, k, l, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k,l] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j2,k2,l] - updateVopt(MDP_object, i2, j2, k2, l, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k2,l] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - i2 = Vopt.shape[0] - i - oldV[0] = Vopt[i2,j,k,l] - updateVopt(MDP_object, i2, j, k, l, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k,l] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i,j2,k,l] - updateVopt(MDP_object, i, j2, k, l, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k,l] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j,k2,l] - updateVopt(MDP_object, i, j, k2, l, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k2,l] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i2,j2,k,l] - updateVopt(MDP_object, i2, j2, k, l, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k,l] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - i2 = Vopt.shape[0] - i - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j,k2,l] - updateVopt(MDP_object, i2, j, k2, l, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k2,l] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j2,k2,l] - updateVopt(MDP_object, i, j2, k2, l, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k2,l] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - - - ###################################### SETUP PLACEHOLDERS ###################################### - - # Initialize the HCL environment - hcl.init() - hcl.config.init_dtype = hcl.Float() - - # NOTE: trans is a tensor with size = maximum number of transitions - # NOTE: intermeds must have size [# possible actions] - # NOTE: transition must have size [# possible outcomes, #state dimensions + 1] - Vopt = hcl.placeholder(tuple(MDP_object._ptsEachDim), name="Vopt", dtype=hcl.Float()) - gamma = hcl.placeholder((0,), "gamma") - count = hcl.placeholder((0,), "count") - maxIters = hcl.placeholder((0,), "maxIters") - epsilon = hcl.placeholder((0,), "epsilon") - actions = hcl.placeholder(tuple(MDP_object._actions.shape), name="actions", dtype=hcl.Float()) - intermeds = hcl.placeholder(tuple([MDP_object._actions.shape[0]]), name="intermeds", dtype=hcl.Float()) - trans = hcl.placeholder(tuple(MDP_object._trans.shape), name="successors", dtype=hcl.Float()) - bounds = hcl.placeholder(tuple(MDP_object._bounds.shape), name="bounds", dtype=hcl.Float()) - goal = hcl.placeholder(tuple(MDP_object._goal.shape), name="goal", dtype=hcl.Float()) - ptsEachDim = hcl.placeholder(tuple([4]), name="ptsEachDim", dtype=hcl.Float()) - sVals = hcl.placeholder(tuple([4]), name="sVals", dtype=hcl.Float()) - iVals = hcl.placeholder(tuple([4]), name="iVals", dtype=hcl.Float()) - interpV = hcl.placeholder((0,), "interpols") - useNN = hcl.placeholder((0,), "useNN") - - # Create a static schedule -- graph - s = hcl.create_schedule([Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN], solve_Vopt) - - # Use this graph and build an executable - return hcl.build(s, target="llvm") - - diff --git a/odp/valueIteration/value_iteration_5D.py b/odp/valueIteration/value_iteration_5D.py deleted file mode 100644 index e290e5ee..00000000 --- a/odp/valueIteration/value_iteration_5D.py +++ /dev/null @@ -1,259 +0,0 @@ -import heterocl as hcl -import numpy as np - -######################################### HELPER FUNCTIONS ######################################### - - -# Update the value function at position (i,j,k,l,m) -# iVals: holds index values (i,j,k,l,m) that correspond to state values (si,sj,sk,sl,sm) -# intermeds: holds the estimated value associated with taking each action -# interpV: holds the estimated value of a successor state (linear interpolation only) -# gamma: discount factor -# ptsEachDim: the number of grid points in each dimension of the state space -# useNN: a mode flag (0: use linear interpolation, 1: use nearest neighbour) -def updateVopt(obj, i, j, k, l, m, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN): - p = hcl.scalar(0, "p") - - with hcl.for_(0, actions.shape[0], name="a") as a: - # set iVals equal to (i,j,k,l,m) and sVals equal to the corresponding state values (si,sj,sk,sl,sm) - updateStateVals(i, j, k, l, m, iVals, sVals, bounds, ptsEachDim) - # call the transition function to obtain the outcome(s) of action a from state (si,sj,sk,sl,sm) - obj.transition(sVals, actions[a], bounds, trans, goal) - # initialize the value of the action Q value with the immediate reward of taking that action - intermeds[a] = obj.reward(sVals, actions[a], bounds, goal, trans) - # add the value of each possible successor state to the Q value - with hcl.for_(0, trans.shape[0], name="si") as si: - p[0] = trans[si,0] - sVals[0] = trans[si,1] - sVals[1] = trans[si,2] - sVals[2] = trans[si,3] - sVals[3] = trans[si,4] - sVals[4] = trans[si,5] - - # Nearest neighbour - with hcl.if_(useNN[0] == 1): - # convert the state values of the successor state (si,sj,sk,sl,sm) into indeces (ia,ja,ka,la,ma) - stateToIndex(sVals, iVals, bounds, ptsEachDim) - # if (ia,ja,ka,la,ma) is within the state space, add its discounted value to the Q value - with hcl.if_(hcl.and_(iVals[0] < Vopt.shape[0], iVals[1] < Vopt.shape[1], iVals[2] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iVals[3] < Vopt.shape[3], iVals[4] < Vopt.shape[4])): - with hcl.if_(hcl.and_(iVals[0] >= 0, iVals[1] >= 0, iVals[2] >= 0, iVals[3] >= 0, iVals[4] >= 0)): - intermeds[a] += (gamma[0] * (p[0] * Vopt[iVals[0], iVals[1], iVals[2], iVals[3], iVals[4]])) - - # maximize over each Q value to obtain the optimal value - Vopt[i,j,k,l,m] = -1000000 - with hcl.for_(0, intermeds.shape[0], name="r") as r: - with hcl.if_(Vopt[i,j,k,l,m] < intermeds[r]): - Vopt[i,j,k,l,m] = intermeds[r] - - -# Returns 0 if convergence has been reached -def evaluateConvergence(newV, oldV, epsilon, reSweep): - delta = hcl.scalar(0, "delta") - # Calculate the difference, if it's negative, make it positive - delta[0] = newV[0] - oldV[0] - with hcl.if_(delta[0] < 0): - delta[0] = delta[0] * -1 - with hcl.if_(delta[0] > epsilon[0]): - reSweep[0] = 1 - - -# Converts state values into indeces using nearest neighbour rounding -def stateToIndex(sVals, iVals, bounds, ptsEachDim): - iVals[0] = ((sVals[0] - bounds[0,0]) / (bounds[0,1] - bounds[0,0])) * (ptsEachDim[0] - 1) - iVals[1] = ((sVals[1] - bounds[1,0]) / (bounds[1,1] - bounds[1,0])) * (ptsEachDim[1] - 1) - iVals[2] = ((sVals[2] - bounds[2,0]) / (bounds[2,1] - bounds[2,0])) * (ptsEachDim[2] - 1) - iVals[3] = ((sVals[3] - bounds[3,0]) / (bounds[3,1] - bounds[3,0])) * (ptsEachDim[3] - 1) - iVals[4] = ((sVals[4] - bounds[4,0]) / (bounds[4,1] - bounds[4,0])) * (ptsEachDim[4] - 1) - # NOTE: add 0.5 to simulate rounding - iVals[0] = hcl.cast(hcl.Int(), iVals[0] + 0.5) - iVals[1] = hcl.cast(hcl.Int(), iVals[1] + 0.5) - iVals[2] = hcl.cast(hcl.Int(), iVals[2] + 0.5) - iVals[3] = hcl.cast(hcl.Int(), iVals[3] + 0.5) - iVals[4] = hcl.cast(hcl.Int(), iVals[4] + 0.5) - - -# Convert indices into state values -def indexToState(iVals, sVals, bounds, ptsEachDim): - sVals[0] = bounds[0,0] + ( (bounds[0,1] - bounds[0,0]) * (iVals[0] / (ptsEachDim[0]-1)) ) - sVals[1] = bounds[1,0] + ( (bounds[1,1] - bounds[1,0]) * (iVals[1] / (ptsEachDim[1]-1)) ) - sVals[2] = bounds[2,0] + ( (bounds[2,1] - bounds[2,0]) * (iVals[2] / (ptsEachDim[2]-1)) ) - sVals[3] = bounds[3,0] + ( (bounds[3,1] - bounds[3,0]) * (iVals[3] / (ptsEachDim[3]-1)) ) - sVals[4] = bounds[4,0] + ( (bounds[4,1] - bounds[4,0]) * (iVals[4] / (ptsEachDim[4]-1)) ) - - -# Sets iVals equal to (i,j,k,l,m) and sVals equal to the corresponding state values -def updateStateVals(i, j, k, l, m, iVals, sVals, bounds, ptsEachDim): - iVals[0] = i - iVals[1] = j - iVals[2] = k - iVals[3] = l - iVals[4] = m - indexToState(iVals, sVals, bounds, ptsEachDim) - - - -######################################### VALUE ITERATION ########################################## - - -# Main value iteration algorithm -# reSweep: a convergence flag (1: continue iterating, 0: convergence reached) -# epsilon: convergence criteria -# maxIters: maximum number of iterations that can occur without convergence being reached -# count: the number of iterations that have been performed -def value_iteration_5D(MDP_object): - def solve_Vopt(Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN): - reSweep = hcl.scalar(1, "reSweep") - oldV = hcl.scalar(0, "oldV") - newV = hcl.scalar(0, "newV") - with hcl.while_(hcl.and_(reSweep[0] == 1, count[0] < maxIters[0])): - reSweep[0] = 0 - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - oldV[0] = Vopt[i,j,k,l,m] - updateVopt(MDP_object, i, j, k, l, m, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k,l,m] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j2,k2,l,m] - updateVopt(MDP_object, i2, j2, k2, l, m, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k2,l,m] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - i2 = Vopt.shape[0] - i - oldV[0] = Vopt[i2,j,k,l,m] - updateVopt(MDP_object, i2, j, k, l, m, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k,l,m] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i,j2,k,l,m] - updateVopt(MDP_object, i, j2, k, l, m, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k,l,m] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j,k2,l,m] - updateVopt(MDP_object, i, j, k2, l, m, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k2,l,m] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i2,j2,k,l,m] - updateVopt(MDP_object, i2, j2, k, l, m, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k,l,m] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - i2 = Vopt.shape[0] - i - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j,k2,l,m] - updateVopt(MDP_object, i2, j, k2, l, m, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k2,l,m] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j2,k2,l,m] - updateVopt(MDP_object, i, j2, k2, l, m, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k2,l,m] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - - - ###################################### SETUP PLACEHOLDERS ###################################### - - # Initialize the HCL environment - hcl.init() - hcl.config.init_dtype = hcl.Float() - - # NOTE: trans is a tensor with size = maximum number of transitions - # NOTE: intermeds must have size [# possible actions] - # NOTE: transition must have size [# possible outcomes, #state dimensions + 1] - Vopt = hcl.placeholder(tuple(MDP_object._ptsEachDim), name="Vopt", dtype=hcl.Float()) - gamma = hcl.placeholder((0,), "gamma") - count = hcl.placeholder((0,), "count") - maxIters = hcl.placeholder((0,), "maxIters") - epsilon = hcl.placeholder((0,), "epsilon") - actions = hcl.placeholder(tuple(MDP_object._actions.shape), name="actions", dtype=hcl.Float()) - intermeds = hcl.placeholder(tuple([MDP_object._actions.shape[0]]), name="intermeds", dtype=hcl.Float()) - trans = hcl.placeholder(tuple(MDP_object._trans.shape), name="successors", dtype=hcl.Float()) - bounds = hcl.placeholder(tuple(MDP_object._bounds.shape), name="bounds", dtype=hcl.Float()) - goal = hcl.placeholder(tuple(MDP_object._goal.shape), name="goal", dtype=hcl.Float()) - ptsEachDim = hcl.placeholder(tuple([5]), name="ptsEachDim", dtype=hcl.Float()) - sVals = hcl.placeholder(tuple([5]), name="sVals", dtype=hcl.Float()) - iVals = hcl.placeholder(tuple([5]), name="iVals", dtype=hcl.Float()) - interpV = hcl.placeholder((0,), "interpols") - useNN = hcl.placeholder((0,), "useNN") - - # Create a static schedule -- graph - s = hcl.create_schedule([Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN], solve_Vopt) - - # Use this graph and build an executable - return hcl.build(s, target="llvm") - - diff --git a/odp/valueIteration/value_iteration_6D.py b/odp/valueIteration/value_iteration_6D.py deleted file mode 100644 index 955fd4c2..00000000 --- a/odp/valueIteration/value_iteration_6D.py +++ /dev/null @@ -1,270 +0,0 @@ -import heterocl as hcl -import numpy as np - -######################################### HELPER FUNCTIONS ######################################### - - -# Update the value function at position (i,j,k,l,m,n) -# iVals: holds index values (i,j,k,l,m,n) that correspond to state values (si,sj,sk,sl,sm,sn) -# intermeds: holds the estimated value associated with taking each action -# interpV: holds the estimated value of a successor state (linear interpolation only) -# gamma: discount factor -# ptsEachDim: the number of grid points in each dimension of the state space -# useNN: a mode flag (0: use linear interpolation, 1: use nearest neighbour) -def updateVopt(obj, i, j, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN): - p = hcl.scalar(0, "p") - - with hcl.for_(0, actions.shape[0], name="a") as a: - # set iVals equal to (i,j,k,l,m,n) and sVals equal to the corresponding state values (si,sj,sk,sl,sm,sn) - updateStateVals(i, j, k, l, m, n, iVals, sVals, bounds, ptsEachDim) - # call the transition function to obtain the outcome(s) of action a from state (si,sj,sk,sl,sm,sn) - obj.transition(sVals, actions[a], bounds, trans, goal) - # initialize the value of the action Q value with the immediate reward of taking that action - intermeds[a] = obj.reward(sVals, actions[a], bounds, goal, trans) - # add the value of each possible successor state to the Q value - with hcl.for_(0, trans.shape[0], name="si") as si: - p[0] = trans[si,0] - sVals[0] = trans[si,1] - sVals[1] = trans[si,2] - sVals[2] = trans[si,3] - sVals[3] = trans[si,4] - sVals[4] = trans[si,5] - sVals[5] = trans[si,6] - - # Nearest neighbour - with hcl.if_(useNN[0] == 1): - # convert the state values of the successor state (si,sj,sk,sl,sm,sn) into indeces (ia,ja,ka,la,ma,na) - stateToIndex(sVals, iVals, bounds, ptsEachDim) - # if (ia,ja,ka,la,ma,na) is within the state space, add its discounted value to the Q value - with hcl.if_(hcl.and_(iVals[0] < Vopt.shape[0], iVals[1] < Vopt.shape[1], iVals[2] < Vopt.shape[2])): - with hcl.if_(hcl.and_(iVals[3] < Vopt.shape[3], iVals[4] < Vopt.shape[4], iVals[5] < Vopt.shape[5])): - with hcl.if_(hcl.and_(iVals[0] >= 0, iVals[1] >= 0, iVals[2] >= 0, iVals[3] >= 0, iVals[4] >= 0, iVals[5] >= 0)): - intermeds[a] += (gamma[0] * (p[0] * Vopt[iVals[0], iVals[1], iVals[2], iVals[3], iVals[4], iVals[5]])) - - # maximize over each Q value to obtain the optimal value - Vopt[i,j,k,l,m,n] = -1000000 - with hcl.for_(0, intermeds.shape[0], name="r") as r: - with hcl.if_(Vopt[i,j,k,l,m,n] < intermeds[r]): - Vopt[i,j,k,l,m,n] = intermeds[r] - - -# Returns 0 if convergence has been reached -def evaluateConvergence(newV, oldV, epsilon, reSweep): - delta = hcl.scalar(0, "delta") - # Calculate the difference, if it's negative, make it positive - delta[0] = newV[0] - oldV[0] - with hcl.if_(delta[0] < 0): - delta[0] = delta[0] * -1 - with hcl.if_(delta[0] > epsilon[0]): - reSweep[0] = 1 - - -# Converts state values into indeces using nearest neighbour rounding -def stateToIndex(sVals, iVals, bounds, ptsEachDim): - iVals[0] = ((sVals[0] - bounds[0,0]) / (bounds[0,1] - bounds[0,0])) * (ptsEachDim[0] - 1) - iVals[1] = ((sVals[1] - bounds[1,0]) / (bounds[1,1] - bounds[1,0])) * (ptsEachDim[1] - 1) - iVals[2] = ((sVals[2] - bounds[2,0]) / (bounds[2,1] - bounds[2,0])) * (ptsEachDim[2] - 1) - iVals[3] = ((sVals[3] - bounds[3,0]) / (bounds[3,1] - bounds[3,0])) * (ptsEachDim[3] - 1) - iVals[4] = ((sVals[4] - bounds[4,0]) / (bounds[4,1] - bounds[4,0])) * (ptsEachDim[4] - 1) - iVals[5] = ((sVals[5] - bounds[5,0]) / (bounds[5,1] - bounds[5,0])) * (ptsEachDim[5] - 1) - # NOTE: add 0.5 to simulate rounding - iVals[0] = hcl.cast(hcl.Int(), iVals[0] + 0.5) - iVals[1] = hcl.cast(hcl.Int(), iVals[1] + 0.5) - iVals[2] = hcl.cast(hcl.Int(), iVals[2] + 0.5) - iVals[3] = hcl.cast(hcl.Int(), iVals[3] + 0.5) - iVals[4] = hcl.cast(hcl.Int(), iVals[4] + 0.5) - iVals[5] = hcl.cast(hcl.Int(), iVals[5] + 0.5) - - -# Convert indices into state values -def indexToState(iVals, sVals, bounds, ptsEachDim): - sVals[0] = bounds[0,0] + ( (bounds[0,1] - bounds[0,0]) * (iVals[0] / (ptsEachDim[0]-1)) ) - sVals[1] = bounds[1,0] + ( (bounds[1,1] - bounds[1,0]) * (iVals[1] / (ptsEachDim[1]-1)) ) - sVals[2] = bounds[2,0] + ( (bounds[2,1] - bounds[2,0]) * (iVals[2] / (ptsEachDim[2]-1)) ) - sVals[3] = bounds[3,0] + ( (bounds[3,1] - bounds[3,0]) * (iVals[3] / (ptsEachDim[3]-1)) ) - sVals[4] = bounds[4,0] + ( (bounds[4,1] - bounds[4,0]) * (iVals[4] / (ptsEachDim[4]-1)) ) - sVals[5] = bounds[5,0] + ( (bounds[5,1] - bounds[5,0]) * (iVals[5] / (ptsEachDim[5]-1)) ) - - -# Sets iVals equal to (i,j,k,l,m,n) and sVals equal to the corresponding state values -def updateStateVals(i, j, k, l, m, n, iVals, sVals, bounds, ptsEachDim): - iVals[0] = i - iVals[1] = j - iVals[2] = k - iVals[3] = l - iVals[4] = m - iVals[5] = n - indexToState(iVals, sVals, bounds, ptsEachDim) - - - -######################################### VALUE ITERATION ########################################## - - -# Main value iteration algorithm -# reSweep: a convergence flag (1: continue iterating, 0: convergence reached) -# epsilon: convergence criteria -# maxIters: maximum number of iterations that can occur without convergence being reached -# count: the number of iterations that have been performed -def value_iteration_6D(MDP_obj): - def solve_Vopt(Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN): - reSweep = hcl.scalar(1, "reSweep") - oldV = hcl.scalar(0, "oldV") - newV = hcl.scalar(0, "newV") - with hcl.while_(hcl.and_(reSweep[0] == 1, count[0] < maxIters[0])): - reSweep[0] = 0 - # Perform value iteration by sweeping in direction 1 - with hcl.Stage("Sweep_1"): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - oldV[0] = Vopt[i,j,k,l,m,n] - updateVopt(MDP_obj, i, j, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 2 - with hcl.Stage("Sweep_2"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j2,k2,l,m,n] - updateVopt(MDP_obj, i2, j2, k2, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k2,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 3 - with hcl.Stage("Sweep_3"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - i2 = Vopt.shape[0] - i - oldV[0] = Vopt[i2,j,k,l,m,n] - updateVopt(MDP_obj, i2, j, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 4 - with hcl.Stage("Sweep_4"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i,j2,k,l,m,n] - updateVopt(MDP_obj, i, j2, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 5 - with hcl.Stage("Sweep_5"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j,k2,l,m,n] - updateVopt(MDP_obj, i, j, k2, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j,k2,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 6 - with hcl.Stage("Sweep_6"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(0, Vopt.shape[2], name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - i2 = Vopt.shape[0] - i - j2 = Vopt.shape[1] - j - oldV[0] = Vopt[i2,j2,k,l,m,n] - updateVopt(MDP_obj, i2, j2, k, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j2,k,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 7 - with hcl.Stage("Sweep_7"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(1, Vopt.shape[0] + 1, name="i") as i: - with hcl.for_(0, Vopt.shape[1], name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - i2 = Vopt.shape[0] - i - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i2,j,k2,l,m,n] - updateVopt(MDP_obj, i2, j, k2, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i2,j,k2,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - # Perform value iteration by sweeping in direction 8 - with hcl.Stage("Sweep_8"): - with hcl.if_(useNN[0] == 1): - with hcl.for_(0, Vopt.shape[0], name="i") as i: - with hcl.for_(1, Vopt.shape[1] + 1, name="j") as j: - with hcl.for_(1, Vopt.shape[2] + 1, name="k") as k: - with hcl.for_(0, Vopt.shape[3], name="l") as l: - with hcl.for_(0, Vopt.shape[4], name="m") as m: - with hcl.for_(0, Vopt.shape[5], name="n") as n: - j2 = Vopt.shape[1] - j - k2 = Vopt.shape[2] - k - oldV[0] = Vopt[i,j2,k2,l,m,n] - updateVopt(MDP_obj, i, j2, k2, l, m, n, iVals, sVals, actions, Vopt, intermeds, trans, interpV, gamma, bounds, goal, ptsEachDim, useNN) - newV[0] = Vopt[i,j2,k2,l,m,n] - evaluateConvergence(newV, oldV, epsilon, reSweep) - count[0] += 1 - - - ###################################### SETUP PLACEHOLDERS ###################################### - - # Initialize the HCL environment - hcl.init() - hcl.config.init_dtype = hcl.Float() - - # NOTE: trans is a tensor with size = maximum number of transitions - # NOTE: intermeds must have size [# possible actions] - # NOTE: transition must have size [# possible outcomes, #state dimensions + 1] - Vopt = hcl.placeholder(tuple(MDP_obj._ptsEachDim), name="Vopt", dtype=hcl.Float()) - gamma = hcl.placeholder((0,), "gamma") - count = hcl.placeholder((0,), "count") - maxIters = hcl.placeholder((0,), "maxIters") - epsilon = hcl.placeholder((0,), "epsilon") - actions = hcl.placeholder(tuple(MDP_obj._actions.shape), name="actions", dtype=hcl.Float()) - intermeds = hcl.placeholder(tuple([MDP_obj._actions.shape[0]]), name="intermeds", dtype=hcl.Float()) - trans = hcl.placeholder(tuple(MDP_obj._trans.shape), name="successors", dtype=hcl.Float()) - bounds = hcl.placeholder(tuple(MDP_obj._bounds.shape), name="bounds", dtype=hcl.Float()) - goal = hcl.placeholder(tuple(MDP_obj._goal.shape), name="goal", dtype=hcl.Float()) - ptsEachDim = hcl.placeholder(tuple([6]), name="ptsEachDim", dtype=hcl.Float()) - sVals = hcl.placeholder(tuple([6]), name="sVals", dtype=hcl.Float()) - iVals = hcl.placeholder(tuple([6]), name="iVals", dtype=hcl.Float()) - interpV = hcl.placeholder((0,), "interpols") - useNN = hcl.placeholder((0,), "useNN") - - # Create a static schedule -- graph - s = hcl.create_schedule([Vopt, actions, intermeds, trans, interpV, gamma, epsilon, iVals, sVals, bounds, goal, ptsEachDim, count, maxIters, useNN], solve_Vopt) - - # Use this graph and build an executable - return hcl.build(s, target="llvm") diff --git a/odp/visualize-graph.ipynb b/odp/visualize-graph.ipynb deleted file mode 100644 index c10c9202..00000000 --- a/odp/visualize-graph.ipynb +++ /dev/null @@ -1,94 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Requires ipywidgets \n", - "#\n", - "# Installation:\n", - "# pip install ipywidgets\n", - "# jupyter nbextension enable --py widgetsnbextension\n", - "#\n", - "# https://ipywidgets.readthedocs.io/en/latest/user_install.html" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import plotly.graph_objects as go\n", - "from ipywidgets import interactive, fixed\n", - "from Plots.plotting_utilities import plot_isosurface\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from user_definer import g" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# load saved V table from solver.py\n", - "V = np.load(\"example.npy\")\n", - "grid_speed_points = g.pts_each_dim[2] - 1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "interactive_plot = interactive(plot_isosurface,\n", - " grid = fixed(g),\n", - " V = fixed(V),\n", - " dims_plot = fixed([0, 1, 3]),\n", - " s = (0, grid_speed_points))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "interactive_plot" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.6.9 64-bit", - "language": "python", - "name": "python36964bitea0d3236082c4a12acd3db83c6ffb55e" - }, - "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.9" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -}