{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "*This notebook contains material from [cbe67701-uncertainty-quantification](https://ndcbe.github.io/cbe67701-uncertainty-quantification);\n", "content is available [on Github](https://github.com/ndcbe/cbe67701-uncertainty-quantification.git).*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [6.0 Adjoint-Based Local Sensitivity Analysis](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.00-Adjoint-Based-Local-Sensitivity-Analysis.html) | [Contents](toc.html) | [6.2 A Simple Example of Adjoint Sensitivity Analysis](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.02-Contributed-Example.html)
"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "5F6q8D_2xysC",
"nbpages": {
"level": 1,
"link": "[6.1 Nonlinear Diffusion-Reaction Equation](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1-Nonlinear-Diffusion-Reaction-Equation)",
"section": "6.1 Nonlinear Diffusion-Reaction Equation"
}
},
"source": [
"# 6.1 Nonlinear Diffusion-Reaction Equation\n",
"\n",
"Created by Shanghui Huang (shuang7@nd.edu)\n",
"\n",
"This example was adapted from:\n",
"\n",
"McClarren, Ryan G (2018). Uncertainty Quantification and Predictive Computational Science: A Foundation for Physical Scientists and Engineers, Chapter 6: Adjoints-Based Local Sensitivity Analysis, Springer, https://doi.org/10.1007/978-3-319-99525-0_6\n",
"\n",
"And special acknowledgement to *Han Gao* for a fruitful discussion"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "nVkXoGG5MVjd",
"nbpages": {
"level": 2,
"link": "[6.1.1 An Overview](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.1-An-Overview)",
"section": "6.1.1 An Overview"
}
},
"source": [
"## 6.1.1 An Overview\n",
"This chapter introduces an adjoint-based method to compute the local sensitivity of a QoI against a parameter. In this method, adjoints gives information of perturbed quantity with only one solve of the forward system and one solve of the adjoint equations.\n",
"\n",
"Take the steady ADR equation for example: \n",
"\\begin{equation}\n",
"v\\frac{\\partial u}{\\partial x} - \\omega \\frac{\\partial ^2 u}{\\partial x^2} + \\kappa u = q\n",
"\\end{equation}\n",
"the operator $L$ is defined as:\n",
"\\begin{equation}\n",
"L = v\\frac{\\partial}{\\partial x} - \\omega \\frac{\\partial ^2}{\\partial x^2} + \\kappa\n",
"\\end{equation}\n",
"Then the adjoints satisfies:\n",
"\\begin{equation}\n",
"(Lu,u^{\\ast})=(u,L^{\\ast}u^{\\ast})\n",
"\\end{equation}\n",
"and\n",
"\\begin{equation}\n",
"L^{\\ast}u^{\\ast} = w\n",
"\\end{equation}\n",
"After a series of mathematical derivations, we can calculate the local sensitivities:\n",
"\\begin{equation}\n",
"\\frac{\\partial Q}{\\partial \\theta} = (\\frac{\\partial q}{\\partial \\theta},u^{\\ast}) + (u,\\frac{\\partial w}{\\partial \\theta}) - (\\frac{\\partial L}{\\partial \\theta}u,u^{\\ast})\n",
"\\end{equation} "
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "r0IDoJRGXT_-",
"nbpages": {
"level": 2,
"link": "[6.1.2 Example of nonlinear diffusion-reaction equation](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.2-Example-of-nonlinear-diffusion-reaction-equation)",
"section": "6.1.2 Example of nonlinear diffusion-reaction equation"
}
},
"source": [
"## 6.1.2 Example of nonlinear diffusion-reaction equation"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "8Eyf7kcNbGU9",
"nbpages": {
"level": 2,
"link": "[6.1.2 Example of nonlinear diffusion-reaction equation](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.2-Example-of-nonlinear-diffusion-reaction-equation)",
"section": "6.1.2 Example of nonlinear diffusion-reaction equation"
}
},
"source": [
"Solving nonlinear diffusion-reaction equation:\n",
"\\begin{equation}\n",
"F(u,\\dot{u}) = \\rho\\dot{u}-\\omega\\frac{\\partial^2u^4}{\\partial x^2} + \\kappa u^4 - S\n",
"\\end{equation}\n",
"in which \n",
"\\begin{equation}\n",
"\\kappa (x) =\n",
"\\begin{cases}\n",
"\\kappa_h, & 1 \\le x \\lt 1.5 \\\\\n",
"\\kappa_l, & otherwise\n",
"\\end{cases}\n",
"\\end{equation}\n",
"\\begin{equation}\n",
"\\S(x) = \n",
"\\begin{cases}\n",
"q, & 0.5 \\le x \\le 1.5 \\\\\n",
"0, & otherwise\n",
"\\end{cases}\n",
"\\end{equation}\n",
"with nominal values \n",
"\\begin{equation}\n",
"\\rho = 1, \\omega = 0.1, \\kappa _l = 0.1 \\kappa _h =2, q = 1\n",
"\\end{equation}"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "OFnYIf6MX_bw",
"nbpages": {
"level": 2,
"link": "[6.1.3 Codes](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3-Codes)",
"section": "6.1.3 Codes"
}
},
"source": [
"## 6.1.3 Codes"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 228
},
"colab_type": "code",
"executionInfo": {
"elapsed": 5038,
"status": "ok",
"timestamp": 1593523486948,
"user": {
"displayName": "黄尚晖",
"photoUrl": "",
"userId": "16496223364462243774"
},
"user_tz": 240
},
"id": "L1kWRZFJ9M3n",
"nbpages": {
"level": 2,
"link": "[6.1.3 Codes](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3-Codes)",
"section": "6.1.3 Codes"
},
"outputId": "2e20d19a-a99a-40f3-85e2-b6e7069e5221"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting pyDOE\n",
" Downloading https://files.pythonhosted.org/packages/bc/ac/91fe4c039e2744466621343d3b8af4a485193ed0aab53af5b1db03be0989/pyDOE-0.3.8.zip\n",
"Requirement already satisfied, skipping upgrade: numpy in /usr/local/lib/python3.6/dist-packages (from pyDOE) (1.18.5)\n",
"Requirement already satisfied, skipping upgrade: scipy in /usr/local/lib/python3.6/dist-packages (from pyDOE) (1.4.1)\n",
"Building wheels for collected packages: pyDOE\n",
" Building wheel for pyDOE (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
" Created wheel for pyDOE: filename=pyDOE-0.3.8-cp36-none-any.whl size=18178 sha256=eae884fee2b8e02ed0591f4026fbd6d99f8c3937a2ef7b62e330bfd5bc6672e9\n",
" Stored in directory: /root/.cache/pip/wheels/7c/c8/58/a6493bd415e8ba5735082b5e0c096d7c1f2933077a8ce34544\n",
"Successfully built pyDOE\n",
"Installing collected packages: pyDOE\n",
"Successfully installed pyDOE-0.3.8\n"
]
}
],
"source": [
"!pip install --upgrade pyDOE\n",
"!pip install tabulate"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"colab": {},
"colab_type": "code",
"executionInfo": {
"elapsed": 498,
"status": "ok",
"timestamp": 1593523488826,
"user": {
"displayName": "黄尚晖",
"photoUrl": "",
"userId": "16496223364462243774"
},
"user_tz": 240
},
"id": "OKtmTiFh6I9k",
"nbpages": {
"level": 2,
"link": "[6.1.3 Codes](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3-Codes)",
"section": "6.1.3 Codes"
}
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import scipy.sparse as sparse\n",
"import scipy.sparse.linalg as linalg\n",
"import scipy.integrate as integrate\n",
"from scipy.stats import gamma\n",
"import math\n",
"from scipy.stats.distributions import norm\n",
"from scipy import stats\n",
"from pyDOE import *\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"colab": {},
"colab_type": "code",
"executionInfo": {
"elapsed": 342,
"status": "ok",
"timestamp": 1593523492495,
"user": {
"displayName": "黄尚晖",
"photoUrl": "",
"userId": "16496223364462243774"
},
"user_tz": 240
},
"id": "6H4HdAhJ6I9p",
"nbpages": {
"level": 2,
"link": "[6.1.3 Codes](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3-Codes)",
"section": "6.1.3 Codes"
}
},
"outputs": [],
"source": [
"def ADRSource(Lx, Nx, Source, omega, v, kappa):\n",
" #Solves the diffusion equation with Generalized Source\n",
" A = sparse.dia_matrix((Nx,Nx),dtype=\"complex\")\n",
" dx = Lx/Nx\n",
" i2dx2 = 1.0/(dx*dx)\n",
" #fill diagonal of A\n",
" A.setdiag(2*i2dx2*omega + np.sign(v)*v/dx)\n",
" #fill off diagonals of A\n",
" A.setdiag(-i2dx2*omega[1:Nx] + \n",
" 0.5*(1-np.sign(v[1:Nx]))*v[1:Nx]/dx,1)\n",
" A.setdiag(-i2dx2*omega[0:(Nx-1)] - \n",
" 0.5*(np.sign(v[0:(Nx-1)])+1)*v[0:(Nx-1)]/dx,-1)\n",
" #solve A x = Source\n",
" Solution = linalg.spsolve(A,Source)\n",
" Q = integrate.trapz(Solution*kappa,dx=dx)\n",
" return Solution, Q"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "h1lNWlMYZDQn",
"nbpages": {
"level": 3,
"link": "[6.1.3.1A function calculating solution $u$](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3.1A-function-calculating-solution-$u$)",
"section": "6.1.3.1A function calculating solution $u$"
}
},
"source": [
"### 6.1.3.1A function calculating solution $u$"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"colab": {},
"colab_type": "code",
"executionInfo": {
"elapsed": 528,
"status": "ok",
"timestamp": 1593523515395,
"user": {
"displayName": "黄尚晖",
"photoUrl": "",
"userId": "16496223364462243774"
},
"user_tz": 240
},
"id": "07NSOk9t6I9t",
"nbpages": {
"level": 3,
"link": "[6.1.3.1A function calculating solution $u$](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3.1A-function-calculating-solution-$u$)",
"section": "6.1.3.1A function calculating solution $u$"
}
},
"outputs": [],
"source": [
"def run_calc(Lx, Nx, rho, Source, omega, v, \n",
" kappa, dt, steps,\n",
" tmin,tmax,xmin,xmax, IC):\n",
" dx = Lx/Nx\n",
" assert IC.size==Nx\n",
" irho = 1/rho\n",
" dt2 = dt/2\n",
" idx2 = 1/dx**2\n",
" solution = np.zeros((Nx+2,steps+1))\n",
" solution[1:Nx+1,0] = 1.0*IC #copy IC\n",
" xs = np.linspace(-dx/2,Lx+dx/2,Nx+2)\n",
" Q = 0\n",
" for step in range(steps):\n",
" #predictor\n",
" pred = solution[:,step]*1.0\n",
" \n",
" pred[1:Nx+1] = (pred[1:Nx+1]-irho*kappa*dt2*pred[1:Nx+1]**4 +\n",
" irho*dt2*Source +\n",
" irho*dt2*omega*idx2*(pred[2:Nx+2]**4 - 2*pred[1:Nx+1]**4 + pred[0:Nx]**4))\n",
" \n",
" #corrector\n",
" solution[1:Nx+1,step+1] = (solution[1:Nx+1,step]-irho*kappa*dt*pred[1:Nx+1]**4 + \n",
" irho*dt*Source +\n",
" irho*dt*omega*idx2 * (pred[2:Nx+2]**4 - 2*pred[1:Nx+1]**4 + pred[0:Nx]**4))\n",
" if ((step+1)*dt >= tmin) and ((step+1)*dt <= tmax):\n",
" Q += np.sum(dt*solution[1:Nx+1,step][(xs[1:Nx+1]>=xmin)*(xs[1:Nx+1]<=xmax)]*\n",
" kappa[(xs[1:Nx+1]>=xmin)*(xs[1:Nx+1]<=xmax)]*dx)\n",
" return solution,Q,xs"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "mazDyC_6Yo14",
"nbpages": {
"level": 3,
"link": "[6.1.3.2 Setting up the nonlinear diffusion-reaction equation](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3.2-Setting-up-the-nonlinear-diffusion-reaction-equation)",
"section": "6.1.3.2 Setting up the nonlinear diffusion-reaction equation"
}
},
"source": [
"### 6.1.3.2 Setting up the nonlinear diffusion-reaction equation"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"colab": {},
"colab_type": "code",
"executionInfo": {
"elapsed": 3314,
"status": "ok",
"timestamp": 1593523526457,
"user": {
"displayName": "黄尚晖",
"photoUrl": "",
"userId": "16496223364462243774"
},
"user_tz": 240
},
"id": "kfi1jUS36I9y",
"nbpages": {
"level": 3,
"link": "[6.1.3.2 Setting up the nonlinear diffusion-reaction equation](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3.2-Setting-up-the-nonlinear-diffusion-reaction-equation)",
"section": "6.1.3.2 Setting up the nonlinear diffusion-reaction equation"
}
},
"outputs": [],
"source": [
"#set up simple advection problem\n",
"Lx = 2\n",
"Nx = 200\n",
"dx = Lx/Nx\n",
"dt = dx**2\n",
"#print('Timestep = ',dt)\n",
"tfinal = 2\n",
"numsteps = math.ceil(tfinal/dt)\n",
"xs = np.linspace(dx/2,Lx-dx/2,Nx)\n",
"Source_func = lambda x, q: (x>0.25*Lx)*(x<0.75*Lx)*q\n",
"kappa_func = lambda x, kappal, kappah: kappah + (kappal-kappah)*(x>0.5*Lx)*(x<0.75*Lx)\n",
"#print('Number of steps = ', numsteps)\n",
"IC = np.zeros(Nx)\n",
"IC[Nx//4:3*Nx//4] = 1*0\n",
"source = IC*0\n",
"source[Nx//4:3*Nx//4] = 10\n",
"\n",
"omega_nom = .1\n",
"v_nom = 0.0\n",
"kappal_nom = 0.1\n",
"kappal_var = 8.511570e-6\n",
"kappah_nom = 2\n",
"kappah_var = 0.002778142\n",
"q_nom = 1\n",
"q_var = 7.062353e-4\n",
"rho = 1.0\n",
"\n",
"sol,Q,xs2 = run_calc(Lx, Nx, rho, Source_func(xs,1), omega_nom, v_nom, \n",
" kappa_func(xs,kappal_nom, kappah_nom), dt, numsteps, 1.8,tfinal,1.5,1.9,IC)\n",
"#print(Q)\n",
"xs3 = xs2\n",
"#plt.plot(xs2,sol[:,numsteps])"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "I3y7UScJOOQV",
"nbpages": {
"level": 3,
"link": "[6.1.3.3 A function calculating adjoint solution $u^{\\ast}$](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3.3-A-function-calculating-adjoint-solution-$u^{\\ast}$)",
"section": "6.1.3.3 A function calculating adjoint solution $u^{\\ast}$"
}
},
"source": [
"### 6.1.3.3 A function calculating adjoint solution $u^{\\ast}$"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"colab": {},
"colab_type": "code",
"executionInfo": {
"elapsed": 317,
"status": "ok",
"timestamp": 1593523531990,
"user": {
"displayName": "黄尚晖",
"photoUrl": "",
"userId": "16496223364462243774"
},
"user_tz": 240
},
"id": "sF1qggY56I93",
"nbpages": {
"level": 3,
"link": "[6.1.3.3 A function calculating adjoint solution $u^{\\ast}$](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3.3-A-function-calculating-adjoint-solution-$u^{\\ast}$)",
"section": "6.1.3.3 A function calculating adjoint solution $u^{\\ast}$"
}
},
"outputs": [],
"source": [
"def run_adjoint_calc(Lx, Nx, rho, Source, omega, v, kappa, dt, steps,tmin,tmax,xmin,xmax, IC, forward):\n",
" dx = Lx/Nx\n",
" assert IC.size==Nx\n",
" dt2 = dt/2\n",
" irho = 1/rho\n",
" solution = np.zeros((Nx+2,steps+1))\n",
" solution[1:Nx+1,steps] = 1.0*IC #copy IC\n",
" xs = np.linspace(-dx/2,Lx+dx/2,Nx+2)\n",
" Q = 0\n",
" ks = kappa*(xs[1:Nx+1]>=xmin)*(xs[1:Nx+1]<=xmax)\n",
" for step in range(steps-1,-1,-1):\n",
" #predictor\n",
" pred = solution[:,step+1]*1.0\n",
" pred[1:Nx+1] = (pred[1:Nx+1]*(1- irho*4*kappa*dt2*forward[1:Nx+1,step]**3) + \n",
" irho*dt2*ks*((step+1)*dt >= tmin)*((step+1)*dt <= tmax) +\n",
" irho*4*dt2*omega/(dx**2)*forward[1:Nx+1,step]**3 * (pred[2:Nx+2]-2*pred[1:Nx+1] + pred[0:Nx])) \n",
" \n",
" \n",
" #corrector\n",
" solution[1:Nx+1,step] = (solution[1:Nx+1,step+1]-irho*4*kappa*dt*pred[1:Nx+1]*forward[1:Nx+1,step]**3 + \n",
" irho*dt*ks*((step+1)*dt >= tmin)*((step+1)*dt <= tmax)+\n",
" irho*4*dt*omega/(dx**2)*forward[1:Nx+1,step]**3 * (pred[2:Nx+2]-2*pred[1:Nx+1] + pred[0:Nx])) \n",
" return solution,xs"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"colab": {},
"colab_type": "code",
"executionInfo": {
"elapsed": 2359,
"status": "ok",
"timestamp": 1593523536988,
"user": {
"displayName": "黄尚晖",
"photoUrl": "",
"userId": "16496223364462243774"
},
"user_tz": 240
},
"id": "BD4mRrzr6I97",
"nbpages": {
"level": 3,
"link": "[6.1.3.3 A function calculating adjoint solution $u^{\\ast}$](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3.3-A-function-calculating-adjoint-solution-$u^{\\ast}$)",
"section": "6.1.3.3 A function calculating adjoint solution $u^{\\ast}$"
}
},
"outputs": [],
"source": [
"sol_adj,xs2 = run_adjoint_calc(Lx, Nx,rho, Source_func(xs,1), omega_nom, v_nom, \n",
" kappa_func(xs,kappal_nom, kappah_nom), dt, numsteps, 1.8,tfinal,1.5,1.9,IC*0, sol)\n",
"\n",
"output = np.vstack([xs2,sol[:,numsteps], sol_adj[:,round(1.8/dt)]]).transpose()\n",
"np.savetxt('nonlindr_foradj.csv', output, delimiter=',')"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "_pLnbneDZTUX",
"nbpages": {
"level": 3,
"link": "[6.1.3.4 Results of foward and adjoint solutions](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3.4-Results-of-foward-and-adjoint-solutions)",
"section": "6.1.3.4 Results of foward and adjoint solutions"
}
},
"source": [
"### 6.1.3.4 Results of foward and adjoint solutions"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 283
},
"colab_type": "code",
"executionInfo": {
"elapsed": 432,
"status": "ok",
"timestamp": 1593523575994,
"user": {
"displayName": "黄尚晖",
"photoUrl": "",
"userId": "16496223364462243774"
},
"user_tz": 240
},
"id": "vxYcVslCV0NR",
"nbpages": {
"level": 3,
"link": "[6.1.3.4 Results of foward and adjoint solutions](https://ndcbe.github.io/cbe67701-uncertainty-quantification/06.01-Contributed-Example.html#6.1.3.4-Results-of-foward-and-adjoint-solutions)",
"section": "6.1.3.4 Results of foward and adjoint solutions"
},
"outputId": "f0daaca1-a26d-4875-c8c4-a0f6c696370a"
},
"outputs": [
{
"data": {
"text/plain": [
"
"
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [
"mazDyC_6Yo14",
"I3y7UScJOOQV",
"_pLnbneDZTUX",
"igOTigTMeFBq"
],
"name": "Nonlinear ADR.ipynb",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 1
}