{ "cells": [ { "cell_type": "markdown", "id": "f389f465-1007-443d-873b-d27bfa74cbc7", "metadata": {}, "source": [ "# Basic model tutorial\n", "\n", "In this tutorial you will learn the basics of the model interface for a simple inline python model. The API for the model interface is provided here:\n", "\n", "https://pressio.github.io/rom-tools-and-workflows/romtools/workflows/models.html\n" ] }, { "cell_type": "code", "execution_count": 30, "id": "358fb709-9c81-45a3-a871-2549de121580", "metadata": {}, "outputs": [], "source": [ "#First, let's import the relavant modules:\n", "import romtools\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "from romtools.workflows import models" ] }, { "cell_type": "code", "execution_count": 37, "id": "b1ffa4be-246c-44a9-b486-f517b9f7acb9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0, 0.5, '$u$')" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "pda_path = os.environ[\"pda-src-dir\"]\n", "\n", "'''\n", "Here, we will interface around a very basic model for solving the 1D poisson equation.\n", "c u_x - nu * u_xx = 1\n", "'''\n", "# We will start with defining an advection diffusion problem. This class does NOT meet any interface related to romtools\n", "class advectionDiffusionProblem:\n", " def __init__(self , nx):\n", " nx_ = nx\n", " self.x_ = np.linspace(0,1,nx)\n", " dx = 1. / (nx - 1)\n", "\n", " ## Assemble diffusion operator and assign boundary conditions\n", " self.Ad_ = np.zeros((nx,nx))\n", " self.Ad_[0,0] = -2./dx**2\n", " self.Ad_[0,1] = 1./dx**2\n", " \n", " self.Ad_[-1,-1] = -2./dx**2\n", " self.Ad_[-1,-2] = 1./dx**2\n", " \n", " for i in range(1,nx_ -1):\n", " self.Ad_[i,i] = -2./dx**2\n", " self.Ad_[i,i-1] = 1./dx**2\n", " self.Ad_[i,i+1] = 1./dx**2\n", " \n", " self.Ac_ = np.zeros((nx,nx))\n", " self.Ac_[0,0] = 1./dx\n", " for i in range(1,nx_ -1 ):\n", " self.Ac_[i,i] = 1/dx\n", " self.Ac_[i,i-1] = -1./dx\n", " \n", " self.f_ = np.ones(nx)\n", "\n", " def assemble_system(self,c,nu):\n", " self.A_ = c*self.Ac_ - nu*self.Ad_\n", "\n", " def solve(self,c,nu):\n", " self.assemble_system(c,nu)\n", " solution = np.linalg.solve(self.A_,self.f_)\n", " return solution\n", "\n", "# As an example, we can insatiate this class and solve for a given parameter insance.\n", "adr_problem = advectionDiffusionProblem(nx=33)\n", "c,nu = 1.,1.e-2\n", "u = adr_problem.solve(c,nu)\n", "plt.plot(adr_problem.x_,u)\n", "plt.xlabel(r'$x$')\n", "plt.ylabel(r'$u$')\n" ] }, { "cell_type": "code", "execution_count": 35, "id": "217759fb-6ec9-4488-897b-e5b4db9f4b2c", "metadata": {}, "outputs": [], "source": [ "## Now, let's create a romtools wrapper around this that meets the API of the ModelClass\n", "class adrRomToolsModel:\n", " def __init__(self,problem: advectionDiffusionProblem):\n", " self.problem_ = advectionDiffusionProblem\n", "\n", " def populate_run_directory(self, run_directory: str, parameter_sample: dict):\n", " # In this example, we don't need any offline data to run our model, so this can be empty\n", " pass\n", " \n", " def run_model(self, run_directory: str, parameter_sample: dict):\n", " #parameter sample will come from a ParameterSpace object, and will be a dictionary of the form:\n", " #[{parameter_name},{value}]\n", " c = parameter_sample['c']\n", " nu = parameter_sample['nu']\n", " u = self.problem_.solve(c,nu)\n", " # return 0 for pass\n", " return 0\n", "\n", "\n", "adr_for_romtools = adrRomToolsModel(adr_problem)\n", "\n", "#That's it! This type of model can be used for running a sampling workflow. " ] }, { "cell_type": "code", "execution_count": null, "id": "b1115b8d-0859-4a6a-ae0f-8cf8c888650c", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.7" } }, "nbformat": 4, "nbformat_minor": 5 }