├── Cylinder-Wake ├── NS_PINNS.py ├── cylinder_wake.mat └── model.pt ├── ODE_Neural_Networks.ipynb └── README.md /Cylinder-Wake/NS_PINNS.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: Computational Domain 3 | """ 4 | 5 | import torch 6 | import torch.nn as nn 7 | import numpy as np 8 | import scipy.io 9 | from matplotlib import pyplot as plt 10 | import matplotlib.animation as animation 11 | 12 | nu = 0.01 13 | 14 | class NavierStokes(): 15 | def __init__(self, X, Y, T, u, v): 16 | 17 | self.x = torch.tensor(X, dtype=torch.float32, requires_grad=True) 18 | self.y = torch.tensor(Y, dtype=torch.float32, requires_grad=True) 19 | self.t = torch.tensor(T, dtype=torch.float32, requires_grad=True) 20 | 21 | self.u = torch.tensor(u, dtype=torch.float32) 22 | self.v = torch.tensor(v, dtype=torch.float32) 23 | 24 | #null vector to test against f and g: 25 | self.null = torch.zeros((self.x.shape[0], 1)) 26 | 27 | # initialize network: 28 | self.network() 29 | 30 | self.optimizer = torch.optim.LBFGS(self.net.parameters(), lr=1, max_iter=200000, max_eval=50000, 31 | history_size=50, tolerance_grad=1e-05, tolerance_change=0.5 * np.finfo(float).eps, 32 | line_search_fn="strong_wolfe") 33 | 34 | self.mse = nn.MSELoss() 35 | 36 | #loss 37 | self.ls = 0 38 | 39 | #iteration number 40 | self.iter = 0 41 | 42 | def network(self): 43 | 44 | self.net = nn.Sequential( 45 | nn.Linear(3, 20), nn.Tanh(), 46 | nn.Linear(20, 20), nn.Tanh(), 47 | nn.Linear(20, 20), nn.Tanh(), 48 | nn.Linear(20, 20), nn.Tanh(), 49 | nn.Linear(20, 20), nn.Tanh(), 50 | nn.Linear(20, 20), nn.Tanh(), 51 | nn.Linear(20, 20), nn.Tanh(), 52 | nn.Linear(20, 20), nn.Tanh(), 53 | nn.Linear(20, 20), nn.Tanh(), 54 | nn.Linear(20, 2)) 55 | 56 | def function(self, x, y, t): 57 | 58 | res = self.net(torch.hstack((x, y, t))) 59 | psi, p = res[:, 0:1], res[:, 1:2] 60 | 61 | u = torch.autograd.grad(psi, y, grad_outputs=torch.ones_like(psi), create_graph=True)[0] #retain_graph=True, 62 | v = -1.*torch.autograd.grad(psi, x, grad_outputs=torch.ones_like(psi), create_graph=True)[0] 63 | 64 | u_x = torch.autograd.grad(u, x, grad_outputs=torch.ones_like(u), create_graph=True)[0] 65 | u_xx = torch.autograd.grad(u_x, x, grad_outputs=torch.ones_like(u_x), create_graph=True)[0] 66 | u_y = torch.autograd.grad(u, y, grad_outputs=torch.ones_like(u), create_graph=True)[0] 67 | u_yy = torch.autograd.grad(u_y, y, grad_outputs=torch.ones_like(u_y), create_graph=True)[0] 68 | u_t = torch.autograd.grad(u, t, grad_outputs=torch.ones_like(u), create_graph=True)[0] 69 | 70 | v_x = torch.autograd.grad(v, x, grad_outputs=torch.ones_like(v), create_graph=True)[0] 71 | v_xx = torch.autograd.grad(v_x, x, grad_outputs=torch.ones_like(v_x), create_graph=True)[0] 72 | v_y = torch.autograd.grad(v, y, grad_outputs=torch.ones_like(v), create_graph=True)[0] 73 | v_yy = torch.autograd.grad(v_y, y, grad_outputs=torch.ones_like(v_y), create_graph=True)[0] 74 | v_t = torch.autograd.grad(v, t, grad_outputs=torch.ones_like(v), create_graph=True)[0] 75 | 76 | p_x = torch.autograd.grad(p, x, grad_outputs=torch.ones_like(p), create_graph=True)[0] 77 | p_y = torch.autograd.grad(p, y, grad_outputs=torch.ones_like(p), create_graph=True)[0] 78 | 79 | f = u_t + u * u_x + v * u_y + p_x - nu * (u_xx + u_yy) 80 | g = v_t + u * v_x + v * v_y + p_y - nu * (v_xx + v_yy) 81 | 82 | return u, v, p, f, g 83 | 84 | def closure(self): 85 | # reset gradients to zero: 86 | self.optimizer.zero_grad() 87 | 88 | # u, v, p, g and f predictions: 89 | u_prediction, v_prediction, p_prediction, f_prediction, g_prediction = self.function(self.x, self.y, self.t) 90 | 91 | # calculate losses 92 | u_loss = self.mse(u_prediction, self.u) 93 | v_loss = self.mse(v_prediction, self.v) 94 | f_loss = self.mse(f_prediction, self.null) 95 | g_loss = self.mse(g_prediction, self.null) 96 | self.ls = u_loss + v_loss + f_loss +g_loss 97 | 98 | # derivative with respect to net's weights: 99 | self.ls.backward() 100 | 101 | self.iter += 1 102 | if not self.iter % 1: 103 | print('Iteration: {:}, Loss: {:0.6f}'.format(self.iter, self.ls)) 104 | 105 | return self.ls 106 | 107 | def train(self): 108 | 109 | # training loop 110 | self.net.train() 111 | self.optimizer.step(self.closure) 112 | 113 | N_train = 5000 114 | 115 | data = scipy.io.loadmat('cylinder_wake.mat') 116 | 117 | U_star = data['U_star'] # N x 2 x T 118 | P_star = data['p_star'] # N x T 119 | t_star = data['t'] # T x 1 120 | X_star = data['X_star'] # N x 2 121 | 122 | N = X_star.shape[0] 123 | T = t_star.shape[0] 124 | 125 | x_test = X_star[:, 0:1] 126 | y_test = X_star[:, 1:2] 127 | p_test = P_star[:, 0:1] 128 | u_test = U_star[:, 0:1, 0] 129 | t_test = np.ones((x_test.shape[0], x_test.shape[1])) 130 | 131 | # Rearrange Data 132 | XX = np.tile(X_star[:, 0:1], (1, T)) # N x T 133 | YY = np.tile(X_star[:, 1:2], (1, T)) # N x T 134 | TT = np.tile(t_star, (1, N)).T # N x T 135 | 136 | UU = U_star[:, 0, :] # N x T 137 | VV = U_star[:, 1, :] # N x T 138 | PP = P_star # N x T 139 | 140 | x = XX.flatten()[:, None] # NT x 1 141 | y = YY.flatten()[:, None] # NT x 1 142 | t = TT.flatten()[:, None] # NT x 1 143 | 144 | u = UU.flatten()[:, None] # NT x 1 145 | v = VV.flatten()[:, None] # NT x 1 146 | p = PP.flatten()[:, None] # NT x 1 147 | 148 | # Training Data 149 | idx = np.random.choice(N * T, N_train, replace=False) 150 | x_train = x[idx, :] 151 | y_train = y[idx, :] 152 | t_train = t[idx, :] 153 | u_train = u[idx, :] 154 | v_train = v[idx, :] 155 | 156 | ''' 157 | pinn = NavierStokes(x_train, y_train, t_train, u_train, v_train) 158 | 159 | pinn.train() 160 | 161 | torch.save(pinn.net.state_dict(), 'model.pt') 162 | ''' 163 | 164 | pinn = NavierStokes(x_train, y_train, t_train, u_train, v_train) 165 | pinn.net.load_state_dict(torch.load('model.pt')) 166 | pinn.net.eval() 167 | 168 | x_test = torch.tensor(x_test, dtype=torch.float32, requires_grad=True) 169 | y_test = torch.tensor(y_test, dtype=torch.float32, requires_grad=True) 170 | t_test = torch.tensor(t_test, dtype=torch.float32, requires_grad=True) 171 | 172 | u_out, v_out, p_out, f_out, g_out = pinn.function(x_test, y_test, t_test) 173 | 174 | u_plot = p_out.data.cpu().numpy() 175 | u_plot = np.reshape(u_plot, (50, 100)) 176 | 177 | fig, ax = plt.subplots() 178 | 179 | plt.contourf(u_plot, levels=30, cmap='jet') 180 | plt.colorbar() 181 | #plt.show() 182 | 183 | def animate(i): 184 | ax.clear() 185 | u_out, v_out, p_out, f_out, g_out = pinn.function(x_test, y_test, i*t_test) 186 | u_plot = p_out.data.cpu().numpy() 187 | u_plot = np.reshape(u_plot, (50, 100)) 188 | cax = ax.contourf(u_plot, levels=20, cmap='jet') 189 | plt.xlabel(r'$x$') 190 | plt.xlabel(r'$y$') 191 | plt.title(r'$p(x,\; y, \; t)$') 192 | 193 | # Call animate method 194 | ani = animation.FuncAnimation(fig, animate, 20, interval=1, blit=False) 195 | #ani.save('p_field_lbfgs.gif') 196 | #plt.close() 197 | # Display the plot 198 | plt.show() 199 | -------------------------------------------------------------------------------- /Cylinder-Wake/cylinder_wake.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComputationalDomain/PINNs/09eceeca807f1d69a95a42b310d583263b762085/Cylinder-Wake/cylinder_wake.mat -------------------------------------------------------------------------------- /Cylinder-Wake/model.pt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComputationalDomain/PINNs/09eceeca807f1d69a95a42b310d583263b762085/Cylinder-Wake/model.pt -------------------------------------------------------------------------------- /ODE_Neural_Networks.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# First order ODE:" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "\\begin{equation}\n", 15 | " \\frac{dy}{dx} + p(x)\\cdot y = f(x)\n", 16 | "\\end{equation}\n", 17 | "\n", 18 | "\\begin{equation}\n", 19 | " x \\; \\in \\; [0, 1]\n", 20 | "\\end{equation}\n", 21 | "\n", 22 | "\\begin{equation}\n", 23 | " y(0) = A\n", 24 | "\\end{equation}" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "# Solving ODE:" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "Finding the solution for the differential equation is the same as minimizing loss function ($min\\{\\mathcal{L} \\}$), where the loss function is defined as:\n", 39 | "\n", 40 | "\\begin{equation}\n", 41 | " \\mathcal{L} = \\int_0^1 \\left(\\frac{d y}{dx} - f(x)\\right)^2 dx\n", 42 | "\\end{equation}" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "# Neural Networks" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "\\begin{equation}\n", 57 | " y \\approx \\mathcal{N}(x)\n", 58 | "\\end{equation}\n", 59 | "\n", 60 | "Loss function:\n", 61 | "\n", 62 | "\\begin{equation} \n", 63 | " MSE = MSE_f + MSE_u\n", 64 | "\\end{equation}\n", 65 | "\n", 66 | "where\n", 67 | "\n", 68 | "\\begin{equation}\n", 69 | " MSE_f = \\frac{1}{N_f} \\sum_{i=1}^{N_f} (\\frac{d \\mathcal{N}(x)}{dx}|_{x = x_i} - f(x_i))^2\n", 70 | "\\end{equation}\n", 71 | "\n", 72 | "and\n", 73 | "\n", 74 | "\\begin{equation}\n", 75 | " MSE_u = \\frac{1}{N_u} \\sum_{i=1}^{N_u} (\\mathcal{N}(x_i) - y(x_i))^2\n", 76 | "\\end{equation}\n" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "## Building Neural Network " 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 1, 89 | "metadata": {}, 90 | "outputs": [], 91 | "source": [ 92 | "import torch\n", 93 | "import torch.nn as nn\n", 94 | "\n", 95 | "# check if GPU is available and use it; otherwise use CPU\n", 96 | "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 2, 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [ 105 | "class Network(nn.Module):\n", 106 | " def __init__(self):\n", 107 | " super().__init__()\n", 108 | " self.hidden_layer = nn.Linear(1, 10)\n", 109 | " self.output_layer = nn.Linear(10, 1)\n", 110 | "\n", 111 | " def forward(self, x):\n", 112 | " layer_out = torch.sigmoid(self.hidden_layer(x))\n", 113 | " output = self.output_layer(layer_out)\n", 114 | " return output\n", 115 | "\n", 116 | "#N = nn.Sequential(nn.Linear(1, 10), nn.Sigmoid(), nn.Linear(10, 1))" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 3, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "N = Network()\n", 126 | "N = N.to(device)" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "## Example Function and BC" 134 | ] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": {}, 139 | "source": [ 140 | "\\begin{equation}\n", 141 | " \\begin{cases}\n", 142 | " f(x) = e^x\\\\\n", 143 | " p(x) = 0\n", 144 | " \\end{cases}\\,.\n", 145 | "\\end{equation}\n", 146 | "\n", 147 | "\\begin{equation}\n", 148 | " y(0) = 1\n", 149 | "\\end{equation}\n" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "### Exact Solution" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "\\begin{equation}\n", 164 | " y = e^x\n", 165 | "\\end{equation}" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 4, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "def f(x):\n", 175 | " return torch.exp(x)\n", 176 | "\n", 177 | "def loss(x):\n", 178 | " x.requires_grad = True\n", 179 | " y = N(x)\n", 180 | " dy_dx = torch.autograd.grad(y.sum(), x, create_graph=True)[0]\n", 181 | " \n", 182 | " return torch.mean( (dy_dx - f(x))**2 ) + (y[0, 0] - 1.)**2" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": 5, 188 | "metadata": {}, 189 | "outputs": [], 190 | "source": [ 191 | "optimizer = torch.optim.LBFGS(N.parameters())\n", 192 | "\n", 193 | "x = torch.linspace(0, 1, 100)[:, None]\n", 194 | "\n", 195 | "def closure():\n", 196 | " optimizer.zero_grad()\n", 197 | " l = loss(x)\n", 198 | " l.backward()\n", 199 | "\n", 200 | " return l\n", 201 | "\n", 202 | "epochs = 10\n", 203 | "for i in range(epochs):\n", 204 | " optimizer.step(closure)\n" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": 6, 210 | "metadata": {}, 211 | "outputs": [ 212 | { 213 | "data": { 214 | "image/png": "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67r8Ofh40cPQzvOZOettHFgwYX8+/5xe/nuMpBGqKeippkfjvympCZJuAh4C1tj+raFsXTZdXeYAy4CPJX0HrARGc1PAQJV+fr1n+w/b3wLfUDVrMTglddkM7ACw/QUwm+oZjzEcReedQUhz1tteYLGkRZLOorowc3TSmFHg9nr7NmC386VxgzRtTerls5epGrNcQ9OMKeti+5jtubYX2l5IdS3gGtv7hhO3E0o+v94FbgCQNJdqmfNQoym7p6Quh4FVAJIupWrOfmo0ZUw0Cmys79pcCRyz/WMTb5xlzR5sn5S0BdgFzAJes31A0mPAPtujwKtUU85jVDNm64aXeOYrrMkzwLnAO/W9GYdtrxla6A4orEs0qLAmu4CbJR0ETgEP2P55eKlnvsK63A+8Iuk+quWzTfmnf3AkvU21tD+3vs7vEeBMANsvUV33dyswBhwH7mgspNaQhAAAARFJREFUW+oeERER0R5Z1oyIiIhokTRnERERES2S5iwiIiKiRdKcRURERLRImrOIiIiIFklzFhEREdEiac4iIiIiWiTNWURED5KulLRf0mxJ50g6IGnZsHNFxMyXL6GNiOhD0hNUj9A5Gxi3/eSQI0VEB6Q5i4joo34G4l7gBHCN7VNDjhQRHZBlzYiI/i6kel7rHKoZtIiIgcvMWUREH5JGge3AImCe7S1DjhQRHTAy7AAREW0kaSNw0vZbkmYBn0u60fbuYWeLiJktM2cRERERLZJrziIiIiJaJM1ZRERERIukOYuIiIhokTRnERERES2S5iwiIiKiRdKcRURERLRImrOIiIiIFklzFhEREdEifwF+jv2fLK7qAwAAAABJRU5ErkJggg==\n", 215 | "text/plain": [ 216 | "
" 217 | ] 218 | }, 219 | "metadata": { 220 | "needs_background": "light" 221 | }, 222 | "output_type": "display_data" 223 | } 224 | ], 225 | "source": [ 226 | "import matplotlib.pyplot as plt\n", 227 | "\n", 228 | "xx = torch.linspace(0, 1, 100)[:, None]\n", 229 | "with torch.no_grad():\n", 230 | " yy = N(xx)\n", 231 | "\n", 232 | "plt.figure(figsize=(10, 6))\n", 233 | "plt.plot(xx, yy, label=\"Predicted\")\n", 234 | "plt.plot(xx, torch.exp(xx), '--', label=\"Exact\")\n", 235 | "plt.xlabel('x')\n", 236 | "plt.ylabel('y')\n", 237 | "plt.legend()\n", 238 | "plt.grid()" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": {}, 244 | "source": [ 245 | "# Second order ODE:" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": {}, 251 | "source": [ 252 | "\\begin{equation}\n", 253 | " \\frac{d^2 y}{dx^2} + p(x) \\frac{dy}{dx} + q(x) y = f(x)\n", 254 | "\\end{equation}\n", 255 | "\n", 256 | "\\begin{equation}\n", 257 | " x \\; \\in \\; [0, 1]\n", 258 | "\\end{equation}\n", 259 | "\n", 260 | "\\begin{equation}\n", 261 | " y(0) = A\n", 262 | "\\end{equation}\n", 263 | "\n", 264 | "\\begin{equation}\n", 265 | " y(1) = B\n", 266 | "\\end{equation}" 267 | ] 268 | }, 269 | { 270 | "cell_type": "markdown", 271 | "metadata": {}, 272 | "source": [ 273 | "## Example Function and BC" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "\\begin{equation}\n", 281 | " \\begin{cases}\n", 282 | " p(x) = 0\\\\\n", 283 | " q(x) = 0\\\\\n", 284 | " f(x) = -1\n", 285 | " \\end{cases}\\,.\n", 286 | "\\end{equation}\n", 287 | "\n", 288 | "\\begin{equation}\n", 289 | " \\begin{cases}\n", 290 | " y(0) = 0\\\\\n", 291 | " y(1) = 0\n", 292 | " \\end{cases}\\,.\n", 293 | "\\end{equation}" 294 | ] 295 | }, 296 | { 297 | "cell_type": "markdown", 298 | "metadata": {}, 299 | "source": [ 300 | "### Exact Solution" 301 | ] 302 | }, 303 | { 304 | "cell_type": "markdown", 305 | "metadata": {}, 306 | "source": [ 307 | "\\begin{equation}\n", 308 | " y(x) = - \\frac{1}{2}x^2 + \\frac{1}{2}x\n", 309 | "\\end{equation}" 310 | ] 311 | }, 312 | { 313 | "cell_type": "code", 314 | "execution_count": 7, 315 | "metadata": {}, 316 | "outputs": [], 317 | "source": [ 318 | "class Network2(nn.Module):\n", 319 | " def __init__(self):\n", 320 | " super().__init__()\n", 321 | " self.hidden_layer = nn.Linear(1, 10)\n", 322 | " self.output_layer = nn.Linear(10, 1)\n", 323 | "\n", 324 | " def forward(self, x):\n", 325 | " layer_out = torch.sigmoid(self.hidden_layer(x))\n", 326 | " output = self.output_layer(layer_out)\n", 327 | " return output\n", 328 | " \n", 329 | "N2 = Network2()\n", 330 | "N2 = N2.to(device)" 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": 8, 336 | "metadata": {}, 337 | "outputs": [], 338 | "source": [ 339 | "def f(x):\n", 340 | " return -torch.ones(x.shape[0], x.shape[1])\n", 341 | "\n", 342 | "def loss(x):\n", 343 | " x.requires_grad = True\n", 344 | " y = N2(x)\n", 345 | " dy_dx = torch.autograd.grad(y.sum(), x, create_graph=True)[0]\n", 346 | " y_double_prime = torch.autograd.grad(dy_dx.sum(), x, create_graph=True)[0]\n", 347 | " \n", 348 | " return torch.mean( (y_double_prime - f(x))**2 ) + 0.5*(y[0, 0] - 0.)**2 + 0.5*(y[-1, 0] - 0.)**2" 349 | ] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "execution_count": 9, 354 | "metadata": {}, 355 | "outputs": [], 356 | "source": [ 357 | "optimizer = torch.optim.LBFGS(N2.parameters())\n", 358 | "\n", 359 | "x = torch.linspace(0, 1, 100)[:, None]\n", 360 | "\n", 361 | "def closure():\n", 362 | " optimizer.zero_grad()\n", 363 | " l = loss(x)\n", 364 | " l.backward()\n", 365 | "\n", 366 | " return l\n", 367 | "\n", 368 | "epochs = 10\n", 369 | "for i in range(epochs):\n", 370 | " optimizer.step(closure)" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": 10, 376 | "metadata": {}, 377 | "outputs": [ 378 | { 379 | "data": { 380 | "image/png": "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\n", 381 | "text/plain": [ 382 | "
" 383 | ] 384 | }, 385 | "metadata": { 386 | "needs_background": "light" 387 | }, 388 | "output_type": "display_data" 389 | } 390 | ], 391 | "source": [ 392 | "import matplotlib.pyplot as plt\n", 393 | "\n", 394 | "xx = torch.linspace(0, 1, 100)[:, None]\n", 395 | "with torch.no_grad():\n", 396 | " yy = N2(xx)\n", 397 | "\n", 398 | "plt.figure(figsize=(10, 6))\n", 399 | "plt.plot(xx, yy, label=\"Predicted\")\n", 400 | "plt.plot(xx, -0.5*torch.pow(xx, 2) + 0.5*xx, '--', label=\"Exact\")\n", 401 | "plt.xlabel('x')\n", 402 | "plt.ylabel('y')\n", 403 | "plt.legend()\n", 404 | "plt.grid()" 405 | ] 406 | }, 407 | { 408 | "cell_type": "markdown", 409 | "metadata": {}, 410 | "source": [ 411 | "Sources: https://www.sciencedirect.com/science/article/pii/S0021999118307125" 412 | ] 413 | }, 414 | { 415 | "cell_type": "code", 416 | "execution_count": null, 417 | "metadata": {}, 418 | "outputs": [], 419 | "source": [] 420 | } 421 | ], 422 | "metadata": { 423 | "kernelspec": { 424 | "display_name": "Python 3", 425 | "language": "python", 426 | "name": "python3" 427 | }, 428 | "language_info": { 429 | "codemirror_mode": { 430 | "name": "ipython", 431 | "version": 3 432 | }, 433 | "file_extension": ".py", 434 | "mimetype": "text/x-python", 435 | "name": "python", 436 | "nbconvert_exporter": "python", 437 | "pygments_lexer": "ipython3", 438 | "version": "3.7.6" 439 | } 440 | }, 441 | "nbformat": 4, 442 | "nbformat_minor": 4 443 | } 444 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PINNs --------------------------------------------------------------------------------