{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PINN Solution of the Nonlinear Shroedinger PDE\n",
    "\n",
    "This PyTorch code demonstrates the application of physically-informed neural networks (PINN) in the solution of a well-known Nonlinear Shroedinger PDE with periodic boundary condition\n",
    "\\begin{aligned}\n",
    "  &\\mathbf{u}_t = i * \\mathbf{u}_{xx} + i * |\\mathbf{u}|^2 * \\mathbf{u} \\in [0, T]\\times[-L, L]\\\\\n",
    "  &\\mathbf{u}(0, x) = \\mathbf{u}_0(x), \\quad \\forall x \\in [-L, L] \\\\\n",
    "  &\\mathbf{u}(t, -L) = \\mathbf{u}(t, L), \\quad \\forall t \\in [0, T]\n",
    "\\end{aligned}\n",
    "where $i^2 = -1$, and $[-L, L]$ covers one full period, i.e. $T = 2L$.  If we let $\\mathbf{u} = u + i * v$, then we obtain two PDEs\n",
    "\\begin{aligned}\n",
    "u_t &= -v_{xx} - (u^2 + v^2) * v \\\\\n",
    "v_t &= u_{xx} + (u^2 + v^2) * u\n",
    "\\end{aligned}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Libraries and Dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.optim\n",
    "import torch.optim.lr_scheduler as lr_scheduler\n",
    "from itertools import chain\n",
    "from collections import OrderedDict\n",
    "from pyDOE import lhs\n",
    "import numpy as np\n",
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "import scipy.io\n",
    "from scipy.interpolate import griddata\n",
    "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
    "import matplotlib.gridspec as gridspec\n",
    "import time\n",
    "# set the random seed\n",
    "np.random.seed(1234)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Working on mps\n"
     ]
    }
   ],
   "source": [
    "if torch.backends.mps.is_available():\n",
    "    device = torch.device('mps')\n",
    "elif torch.cuda.is_available():\n",
    "    device = torch.device('cuda')\n",
    "else:\n",
    "    device = torch.device('cpu')\n",
    "#\n",
    "print(f\"Working on {device}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "L = np.pi\n",
    "xlo = -L\n",
    "xhi = L\n",
    "period = xhi - xlo\n",
    "tlo = 0.0\n",
    "thi = 2.0\n",
    "sqrt2 = torch.tensor(np.sqrt(2)).float().to(device)\n",
    "# taking A = 1 and B = 1\n",
    "u0 = lambda x: 2.0/(2.0 - np.sqrt(2) * np.cos(x)) - 1.0\n",
    "v0 = lambda x: np.zeros_like(x)\n",
    "u0_ten = lambda x: 2.0/(2.0 - sqrt2 * torch.cos(x)) - 1.0\n",
    "v0_ten = lambda x: torch.zeros_like(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Physics-informed Neural Networks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# the deep neural network\n",
    "class DNN(torch.nn.Module):\n",
    "    def __init__(self, layers):\n",
    "        super(DNN, self).__init__()\n",
    "        # parameters\n",
    "        self.depth = len(layers) - 1\n",
    "        # set up layer order dict\n",
    "        self.activation = torch.nn.Tanh\n",
    "        layer_list = list()\n",
    "        for i in range(self.depth - 1): \n",
    "            layer_list.append(\n",
    "                ('layer_%d' % i, torch.nn.Linear(layers[i], layers[i+1]))\n",
    "            )\n",
    "            layer_list.append(('activation_%d' % i, self.activation()))\n",
    "            \n",
    "        layer_list.append(\n",
    "            ('layer_%d' % (self.depth - 1), torch.nn.Linear(layers[-2], layers[-1]))\n",
    "        )\n",
    "        layerDict = OrderedDict(layer_list)\n",
    "        # deploy layers\n",
    "        self.layers = torch.nn.Sequential(layerDict)\n",
    "        self.layers[0].weight = torch.load('initial_weight.pt')\n",
    "    def forward(self, x):\n",
    "        out = self.layers(x)\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class PhysicsInformedNN():\n",
    "    def __init__(self, period, X_IC, u_IC, v_IC, X_BC, u_BC, v_BC, X_PDE, layers):\n",
    "        # IC data point\n",
    "        self.t_IC = torch.tensor(X_IC[:, 0:1]).float().to(device)\n",
    "        self.x_IC = torch.tensor(X_IC[:, 1:2]).float().to(device)\n",
    "        self.u_IC = torch.tensor(u_IC).float().to(device)\n",
    "        self.v_IC = torch.tensor(v_IC).float().to(device) \n",
    "        N_IC = X_IC.shape[0]\n",
    "        self.LW_uIC = torch.nn.ParameterList([torch.nn.Parameter(torch.ones(N_IC, 1).float(), requires_grad=True).to(device)])\n",
    "        self.LW_vIC = torch.nn.ParameterList([torch.nn.Parameter(torch.ones(N_IC, 1).float(), requires_grad=True).to(device)])\n",
    "        # BC data point\n",
    "        self.t_BC = torch.tensor(X_BC[:, 0:1]).float().to(device)\n",
    "        self.x_BC = torch.tensor(X_BC[:, 1:2]).float().to(device)\n",
    "        self.u_BC = torch.tensor(u_BC).float().to(device)\n",
    "        self.v_BC = torch.tensor(v_BC).float().to(device) \n",
    "        self.period = torch.tensor(period).float().to(device)\n",
    "        N_BC = X_BC.shape[0]\n",
    "        self.LW_uBC = torch.nn.ParameterList([torch.nn.Parameter(torch.ones(N_BC, 1).float(), requires_grad=True).to(device)])        \n",
    "        self.LW_vBC = torch.nn.ParameterList([torch.nn.Parameter(torch.ones(N_BC, 1).float(), requires_grad=True).to(device)])        \n",
    "        # PDE data, gradients will be computed on these points so requires_grad = True\n",
    "        self.t_PDE = torch.tensor(X_PDE[:, 0:1], requires_grad=True).float().to(device)\n",
    "        self.x_PDE = torch.tensor(X_PDE[:, 1:2], requires_grad=True).float().to(device)\n",
    "       \n",
    "        N_PDE = X_PDE.shape[0]\n",
    "        self.LW_uPDE = torch.nn.ParameterList([torch.nn.Parameter(torch.ones(N_PDE, 1).float(), requires_grad=True).to(device)])\n",
    "        self.LW_vPDE = torch.nn.ParameterList([torch.nn.Parameter(torch.ones(N_PDE, 1).float(), requires_grad=True).to(device)])\n",
    "\n",
    "        \n",
    "        # layers to build Neural Net\n",
    "        self.layers = layers\n",
    "        # deep neural networks\n",
    "        self.dnn = DNN(layers).to(device)    \n",
    "        # prepare the optimizer\n",
    "        self.optimizer_Adam = torch.optim.Adam(self.dnn.parameters(), lr = 1e-3)\n",
    "        self.optimizer_LW_uIC = torch.optim.Adam(self.LW_uIC.parameters(), lr = 5e-3)\n",
    "        self.optimizer_LW_uBC = torch.optim.Adam(self.LW_uBC.parameters(), lr = 5e-3)\n",
    "        self.optimizer_LW_uPDE = torch.optim.Adam(self.LW_uPDE.parameters(), lr = 5e-3)\n",
    "        self.optimizer_LW_vIC = torch.optim.Adam(self.LW_vIC.parameters(), lr = 5e-3)\n",
    "        self.optimizer_LW_vBC = torch.optim.Adam(self.LW_vBC.parameters(), lr = 5e-3)\n",
    "        self.optimizer_LW_vPDE = torch.optim.Adam(self.LW_vPDE.parameters(), lr = 5e-3)\n",
    "        # add a learning rate scheduler\n",
    "        \n",
    "        self.optimizer_LBFGS = torch.optim.LBFGS(\n",
    "            self.dnn.parameters(), \n",
    "            lr=1.0, \n",
    "            max_iter=50000, \n",
    "            max_eval=50000, \n",
    "            history_size=50,\n",
    "            tolerance_grad=1e-8, \n",
    "            tolerance_change=1.0 * np.finfo(float).eps,\n",
    "            line_search_fn=\"strong_wolfe\"       # can be \"strong_wolfe\"\n",
    "        )        \n",
    "        self.scheduler = lr_scheduler.ExponentialLR(self.optimizer_Adam, gamma=0.999)\n",
    "        self.iter = 0\n",
    "    # evaluater neural network, no transformation\n",
    "    def NN_eval(self, t, x):  \n",
    "        NN = self.dnn(torch.cat([t, x], dim = 1)) \n",
    "        u = NN[:, 0][:, None]\n",
    "        v = NN[:, 1][:, None]\n",
    "        return u,v\n",
    "    # compute the PDE\n",
    "    def pde_eval(self, t, x):\n",
    "        \"\"\" The pytorch autograd version of calculating residual \"\"\"\n",
    "        u, v = self.NN_eval(t, x)\n",
    "        # compute the derivatives for u\n",
    "        u_t    = torch.autograd.grad(u,     t, grad_outputs = torch.ones_like(u), retain_graph = True, create_graph=True)[0]\n",
    "        u_x    = torch.autograd.grad(u,     x, grad_outputs = torch.ones_like(u), retain_graph = True, create_graph=True)[0]\n",
    "        u_xx   = torch.autograd.grad(u_x,   x, grad_outputs = torch.ones_like(u), retain_graph = True, create_graph=True)[0]\n",
    "        v_t    = torch.autograd.grad(v,     t, grad_outputs = torch.ones_like(u), retain_graph = True, create_graph=True)[0]\n",
    "        v_x    = torch.autograd.grad(v,     x, grad_outputs = torch.ones_like(u), retain_graph = True, create_graph=True)[0]\n",
    "        v_xx   = torch.autograd.grad(v_x,   x, grad_outputs = torch.ones_like(u), retain_graph = True, create_graph=True)[0]   \n",
    "        # pre-compute the norm of \\mathbf{u}, so that it can be re-used\n",
    "        U_norm = torch.pow(u, 2.0) + torch.pow(v, 2.0)\n",
    "        Eq1    = u_t + v_xx + U_norm * v\n",
    "        Eq2    = v_t - u_xx - U_norm * u\n",
    "        return Eq1, Eq2\n",
    "    # compute the total loss for the second-order optimizer\n",
    "    def loss_func(self):\n",
    "        # reset the gradient\n",
    "        self.optimizer_LBFGS.zero_grad()\n",
    "        # compute IC loss\n",
    "        uIC_pred, vIC_pred = self.NN_eval(self.t_IC, self.x_IC)\n",
    "    \n",
    "        loss_IC = torch.mean((self.LW_uIC[0] *(self.u_IC - uIC_pred))**2.0) + torch.mean((self.LW_vIC[0] *(self.v_IC - vIC_pred))**2.0)\n",
    "        # compute PBC loss\n",
    "        uBC_pred_left, vBC_pred_left = self.NN_eval(self.t_BC, self.x_BC)\n",
    "        uBC_pred_right, vBC_pred_right = self.NN_eval(self.t_BC, self.x_BC+self.period)\n",
    "        loss_BC = torch.mean((self.LW_uBC[0]*(uBC_pred_left - uBC_pred_right))**2.0) + torch.mean((self.LW_vBC[0]*(vBC_pred_left - vBC_pred_right))**2.0)\n",
    "        \n",
    "        \n",
    "        pde1_pred, pde2_pred = self.pde_eval(self.t_PDE, self.x_PDE)\n",
    "        loss_PDE = torch.mean((self.LW_uPDE[0]*pde1_pred )** 2) + torch.mean((self.LW_vPDE[0]*pde2_pred )** 2)   \n",
    "        \n",
    "       \n",
    "        # compute the total loss, it can be weighted\n",
    "        loss = loss_IC + loss_BC + loss_PDE\n",
    "        # backward propagation\n",
    "        loss.backward()\n",
    "        # increase the iteration counter\n",
    "        self.iter += 1\n",
    "        # output\n",
    "        # output the progress\n",
    "        if self.iter % 1000 == 0:\n",
    "            end_time = time.time()\n",
    "            print('Iter %5d, Total: %10.4e, Time: %.2f secs' % (self.iter, loss.item(), end_time - self.start_time))\n",
    "            print('IC: %10.4e, PBC: %10.4e, PDE: %10.4e' % (loss_IC.item(), loss_BC.item(), loss_PDE.item()))\n",
    "            self.start_time = end_time\n",
    "        return loss\n",
    "    #\n",
    "    def train(self, nIter):\n",
    "        # start the timer\n",
    "        start_time = time.time()        \n",
    "        # start the training with Adam first\n",
    "        self.dnn.train()\n",
    "        print('Starting with Adam')\n",
    "        for epoch in range(nIter):\n",
    "            # compute IC loss\n",
    "            uIC_pred, vIC_pred = self.NN_eval(self.t_IC, self.x_IC)\n",
    "    \n",
    "            loss_IC = torch.mean((self.LW_uIC[0] *(self.u_IC - uIC_pred))**2.0) + torch.mean((self.LW_vIC[0] *(self.v_IC - vIC_pred))**2.0)\n",
    "        # compute PBC loss\n",
    "            uBC_pred_left, vBC_pred_left = self.NN_eval(self.t_BC, self.x_BC)\n",
    "            uBC_pred_right, vBC_pred_right = self.NN_eval(self.t_BC, self.x_BC+self.period)\n",
    "            loss_BC = torch.mean((self.LW_uBC[0]*(uBC_pred_left - uBC_pred_right))**2.0) + torch.mean((self.LW_vBC[0]*(vBC_pred_left - vBC_pred_right))**2.0)\n",
    "        \n",
    "        \n",
    "            pde1_pred, pde2_pred = self.pde_eval(self.t_PDE, self.x_PDE)\n",
    "            loss_PDE = torch.mean((self.LW_uPDE[0]*pde1_pred )** 2) + torch.mean((self.LW_vPDE[0]*pde2_pred )** 2)   \n",
    "        \n",
    "       \n",
    "        # compute the total loss, it can be weighted\n",
    "            loss = loss_IC + loss_BC + loss_PDE\n",
    "            # Backward and optimize\n",
    "            self.optimizer_Adam.zero_grad()\n",
    "            self.optimizer_LW_uIC.zero_grad()\n",
    "            self.optimizer_LW_uBC.zero_grad()\n",
    "            self.optimizer_LW_uPDE.zero_grad()\n",
    "            self.optimizer_LW_vIC.zero_grad()\n",
    "            self.optimizer_LW_vBC.zero_grad()\n",
    "            self.optimizer_LW_vPDE.zero_grad()\n",
    "            loss.backward()\n",
    "            self.optimizer_Adam.step() \n",
    "            self.LW_uIC[0].grad.data = -self.LW_uIC[0].grad.data\n",
    "            self.LW_uBC[0].grad.data = -self.LW_uBC[0].grad.data\n",
    "            self.LW_uPDE[0].grad.data = -self.LW_uPDE[0].grad.data\n",
    "            self.LW_vIC[0].grad.data = -self.LW_vIC[0].grad.data\n",
    "            self.LW_vBC[0].grad.data = -self.LW_vBC[0].grad.data\n",
    "            self.LW_vPDE[0].grad.data = -self.LW_vPDE[0].grad.data\n",
    "            self.optimizer_LW_uIC.step()\n",
    "            self.optimizer_LW_uBC.step()\n",
    "            self.optimizer_LW_uPDE.step()\n",
    "            self.optimizer_LW_vIC.step()\n",
    "            self.optimizer_LW_vBC.step()\n",
    "            self.optimizer_LW_vPDE.step()\n",
    "            # output the progress\n",
    "            if (epoch + 1) % 1000 == 0:\n",
    "                end_time = time.time()\n",
    "                print('Iter %5d, Total: %10.4e, Time: %.2f secs' % (epoch + 1, loss.item(), end_time - start_time))\n",
    "                print('IC: %10.4e, PBC: %10.4e, PDE: %10.4e' % (loss_IC.item(), loss_BC.item(), loss_PDE.item()))\n",
    "                print('For uIC,  min uLW: %10.4e, max uLW: %10.4e' %(torch.min(self.LW_uIC[0]).item(), torch.max(self.LW_uIC[0]).item()))\n",
    "                print('For uBC,  min uLW: %10.4e, max uLW: %10.4e' %(torch.min(self.LW_uBC[0]).item(), torch.max(self.LW_uBC[0]).item()))\n",
    "                print('For uPDE, min uLW: %10.4e, max uLW: %10.4e' %(torch.min(self.LW_uPDE[0]).item(), torch.max(self.LW_uPDE[0]).item()))\n",
    "                print('For vIC,  min vLW: %10.4e, max vLW: %10.4e' %(torch.min(self.LW_vIC[0]).item(), torch.max(self.LW_vIC[0]).item()))\n",
    "                print('For vBC,  min vLW: %10.4e, max vLW: %10.4e' %(torch.min(self.LW_vBC[0]).item(), torch.max(self.LW_vBC[0]).item()))\n",
    "                print('For vPDE, min vLW: %10.4e, max vLW: %10.4e' %(torch.min(self.LW_vPDE[0]).item(), torch.max(self.LW_vPDE[0]).item()))\n",
    "                \n",
    "                start_time = end_time\n",
    "                # change the learning rate\n",
    "                self.scheduler.step()\n",
    "        # Using the second-order L-BFGS optimizer\n",
    "        print('Starting with L-BFGS')\n",
    "        self.start_time = time.time()\n",
    "        self.optimizer_LBFGS.step(self.loss_func)                \n",
    "    #        \n",
    "    def predict(self, X):\n",
    "        t = torch.tensor(X[:, 0:1], requires_grad=True).float().to(device)\n",
    "        x = torch.tensor(X[:, 1:2], requires_grad=True).float().to(device)\n",
    "        self.dnn.eval()\n",
    "        u, v = self.NN_eval(t, x)\n",
    "        u = u.detach().cpu().numpy()\n",
    "        v = v.detach().cpu().numpy()\n",
    "        return u,v\n",
    "\n",
    "\n",
    "## Configurations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting with Adam\n",
      "Iter  1000, Total: 1.6031e-01, Time: 126.52 secs\n",
      "IC: 9.0673e-02, PBC: 3.9267e-04, PDE: 6.9248e-02\n",
      "For uIC,  min uLW: 1.1490e+00, max uLW: 2.0657e+00\n",
      "For uBC,  min uLW: 1.5546e+00, max uLW: 1.6734e+00\n",
      "For uPDE, min uLW: 1.3104e+00, max uLW: 6.3274e+00\n",
      "For vIC,  min vLW: 1.3485e+00, max vLW: 2.5063e+00\n",
      "For vBC,  min vLW: 1.6893e+00, max vLW: 2.1980e+00\n",
      "For vPDE, min vLW: 1.4301e+00, max vLW: 6.2425e+00\n",
      "Iter  2000, Total: 4.0954e-02, Time: 119.54 secs\n",
      "IC: 2.2843e-02, PBC: 2.6050e-04, PDE: 1.7851e-02\n",
      "For uIC,  min uLW: 1.1501e+00, max uLW: 2.2769e+00\n",
      "For uBC,  min uLW: 1.5551e+00, max uLW: 1.6784e+00\n",
      "For uPDE, min uLW: 1.3313e+00, max uLW: 9.3907e+00\n",
      "For vIC,  min vLW: 1.4611e+00, max vLW: 5.2376e+00\n",
      "For vBC,  min vLW: 1.7723e+00, max vLW: 2.6643e+00\n",
      "For vPDE, min vLW: 1.4410e+00, max vLW: 7.7466e+00\n",
      "Iter  3000, Total: 2.5098e-02, Time: 119.60 secs\n",
      "IC: 1.2682e-02, PBC: 3.3647e-04, PDE: 1.2080e-02\n",
      "For uIC,  min uLW: 1.1534e+00, max uLW: 2.2774e+00\n",
      "For uBC,  min uLW: 1.5551e+00, max uLW: 1.6788e+00\n",
      "For uPDE, min uLW: 1.3368e+00, max uLW: 1.1091e+01\n",
      "For vIC,  min vLW: 1.5708e+00, max vLW: 6.3490e+00\n",
      "For vBC,  min vLW: 1.8243e+00, max vLW: 2.8465e+00\n",
      "For vPDE, min vLW: 1.4543e+00, max vLW: 8.3030e+00\n",
      "Iter  4000, Total: 1.9037e+00, Time: 119.10 secs\n",
      "IC: 1.1049e+00, PBC: 3.2973e-02, PDE: 7.6588e-01\n",
      "For uIC,  min uLW: 2.7783e+00, max uLW: 6.4017e+00\n",
      "For uBC,  min uLW: 1.9322e+00, max uLW: 2.2848e+00\n",
      "For uPDE, min uLW: 1.6500e+00, max uLW: 1.2251e+01\n",
      "For vIC,  min vLW: 2.0285e+00, max vLW: 7.2057e+00\n",
      "For vBC,  min vLW: 2.2584e+00, max vLW: 3.5019e+00\n",
      "For vPDE, min vLW: 1.9922e+00, max vLW: 1.2242e+01\n",
      "Iter  5000, Total: 9.3577e-01, Time: 119.59 secs\n",
      "IC: 4.4885e-01, PBC: 6.7129e-03, PDE: 4.8020e-01\n",
      "For uIC,  min uLW: 3.0832e+00, max uLW: 8.7145e+00\n",
      "For uBC,  min uLW: 1.9339e+00, max uLW: 2.6056e+00\n",
      "For uPDE, min uLW: 1.6566e+00, max uLW: 1.5165e+01\n",
      "For vIC,  min vLW: 2.0517e+00, max vLW: 7.2882e+00\n",
      "For vBC,  min vLW: 2.2680e+00, max vLW: 3.5056e+00\n",
      "For vPDE, min vLW: 2.0602e+00, max vLW: 1.2259e+01\n",
      "Iter  6000, Total: 6.7831e-01, Time: 119.48 secs\n",
      "IC: 2.7867e-01, PBC: 6.8332e-03, PDE: 3.9281e-01\n",
      "For uIC,  min uLW: 3.1484e+00, max uLW: 9.3358e+00\n",
      "For uBC,  min uLW: 1.9497e+00, max uLW: 2.6240e+00\n",
      "For uPDE, min uLW: 1.6614e+00, max uLW: 1.7720e+01\n",
      "For vIC,  min vLW: 2.0551e+00, max vLW: 7.2935e+00\n",
      "For vBC,  min vLW: 2.2774e+00, max vLW: 3.5065e+00\n",
      "For vPDE, min vLW: 2.0993e+00, max vLW: 1.2333e+01\n",
      "Iter  7000, Total: 4.7065e-01, Time: 119.03 secs\n",
      "IC: 1.7485e-01, PBC: 5.7156e-03, PDE: 2.9009e-01\n",
      "For uIC,  min uLW: 3.1693e+00, max uLW: 9.5495e+00\n",
      "For uBC,  min uLW: 1.9863e+00, max uLW: 2.6802e+00\n",
      "For uPDE, min uLW: 1.6718e+00, max uLW: 1.9428e+01\n",
      "For vIC,  min vLW: 2.0589e+00, max vLW: 7.2943e+00\n",
      "For vBC,  min vLW: 2.2808e+00, max vLW: 3.5153e+00\n",
      "For vPDE, min vLW: 2.1118e+00, max vLW: 1.4292e+01\n",
      "Iter  8000, Total: 3.0114e-01, Time: 119.53 secs\n",
      "IC: 1.0598e-01, PBC: 2.5760e-03, PDE: 1.9258e-01\n",
      "For uIC,  min uLW: 3.1719e+00, max uLW: 9.6083e+00\n",
      "For uBC,  min uLW: 2.0083e+00, max uLW: 2.7226e+00\n",
      "For uPDE, min uLW: 1.6815e+00, max uLW: 2.0216e+01\n",
      "For vIC,  min vLW: 2.0619e+00, max vLW: 7.2975e+00\n",
      "For vBC,  min vLW: 2.2813e+00, max vLW: 3.5306e+00\n",
      "For vPDE, min vLW: 2.1205e+00, max vLW: 1.6500e+01\n",
      "Iter  9000, Total: 1.9340e-01, Time: 120.31 secs\n",
      "IC: 6.3840e-02, PBC: 9.4228e-04, PDE: 1.2861e-01\n",
      "For uIC,  min uLW: 3.1736e+00, max uLW: 9.6147e+00\n",
      "For uBC,  min uLW: 2.0126e+00, max uLW: 2.7380e+00\n",
      "For uPDE, min uLW: 1.6827e+00, max uLW: 2.0450e+01\n",
      "For vIC,  min vLW: 2.0623e+00, max vLW: 7.3053e+00\n",
      "For vBC,  min vLW: 2.2813e+00, max vLW: 3.5395e+00\n",
      "For vPDE, min vLW: 2.1506e+00, max vLW: 1.7590e+01\n",
      "Iter 10000, Total: 1.3925e-01, Time: 120.24 secs\n",
      "IC: 4.2406e-02, PBC: 4.6903e-04, PDE: 9.6373e-02\n",
      "For uIC,  min uLW: 3.1813e+00, max uLW: 9.6208e+00\n",
      "For uBC,  min uLW: 2.0128e+00, max uLW: 2.7460e+00\n",
      "For uPDE, min uLW: 1.6840e+00, max uLW: 2.0507e+01\n",
      "For vIC,  min vLW: 2.0636e+00, max vLW: 7.3185e+00\n",
      "For vBC,  min vLW: 2.2813e+00, max vLW: 3.5414e+00\n",
      "For vPDE, min vLW: 2.1817e+00, max vLW: 1.8149e+01\n",
      "Iter 11000, Total: 1.1142e-01, Time: 119.70 secs\n",
      "IC: 3.1922e-02, PBC: 3.0331e-04, PDE: 7.9197e-02\n",
      "For uIC,  min uLW: 3.1998e+00, max uLW: 9.6528e+00\n",
      "For uBC,  min uLW: 2.0128e+00, max uLW: 2.7531e+00\n",
      "For uPDE, min uLW: 1.6865e+00, max uLW: 2.0520e+01\n",
      "For vIC,  min vLW: 2.0677e+00, max vLW: 7.3354e+00\n",
      "For vBC,  min vLW: 2.2814e+00, max vLW: 3.5415e+00\n",
      "For vPDE, min vLW: 2.1822e+00, max vLW: 1.8586e+01\n",
      "Iter 12000, Total: 9.0804e-02, Time: 119.72 secs\n",
      "IC: 2.5833e-02, PBC: 2.1201e-04, PDE: 6.4759e-02\n",
      "For uIC,  min uLW: 3.2375e+00, max uLW: 9.7258e+00\n",
      "For uBC,  min uLW: 2.0128e+00, max uLW: 2.7612e+00\n",
      "For uPDE, min uLW: 1.6878e+00, max uLW: 2.0521e+01\n",
      "For vIC,  min vLW: 2.0740e+00, max vLW: 7.3533e+00\n",
      "For vBC,  min vLW: 2.2818e+00, max vLW: 3.5415e+00\n",
      "For vPDE, min vLW: 2.1825e+00, max vLW: 1.9092e+01\n",
      "Iter 13000, Total: 7.3196e-02, Time: 120.45 secs\n",
      "IC: 2.1447e-02, PBC: 1.8490e-04, PDE: 5.1565e-02\n",
      "For uIC,  min uLW: 3.3007e+00, max uLW: 9.8421e+00\n",
      "For uBC,  min uLW: 2.0128e+00, max uLW: 2.7713e+00\n",
      "For uPDE, min uLW: 1.6880e+00, max uLW: 2.0523e+01\n",
      "For vIC,  min vLW: 2.0813e+00, max vLW: 7.3684e+00\n",
      "For vBC,  min vLW: 2.2825e+00, max vLW: 3.5415e+00\n",
      "For vPDE, min vLW: 2.1828e+00, max vLW: 1.9757e+01\n",
      "Iter 14000, Total: 5.7916e-02, Time: 119.80 secs\n",
      "IC: 1.7494e-02, PBC: 2.0184e-04, PDE: 4.0220e-02\n",
      "For uIC,  min uLW: 3.3954e+00, max uLW: 1.0000e+01\n",
      "For uBC,  min uLW: 2.0132e+00, max uLW: 2.7842e+00\n",
      "For uPDE, min uLW: 1.6901e+00, max uLW: 2.0534e+01\n",
      "For vIC,  min vLW: 2.0823e+00, max vLW: 7.3797e+00\n",
      "For vBC,  min vLW: 2.2833e+00, max vLW: 3.5415e+00\n",
      "For vPDE, min vLW: 2.1829e+00, max vLW: 2.0677e+01\n",
      "Iter 15000, Total: 4.4984e-02, Time: 119.45 secs\n",
      "IC: 1.3748e-02, PBC: 2.0815e-04, PDE: 3.1028e-02\n",
      "For uIC,  min uLW: 3.5162e+00, max uLW: 1.0182e+01\n",
      "For uBC,  min uLW: 2.0147e+00, max uLW: 2.7967e+00\n",
      "For uPDE, min uLW: 1.6965e+00, max uLW: 2.0568e+01\n",
      "For vIC,  min vLW: 2.0832e+00, max vLW: 7.3863e+00\n",
      "For vBC,  min vLW: 2.2833e+00, max vLW: 3.5415e+00\n",
      "For vPDE, min vLW: 2.1829e+00, max vLW: 2.1844e+01\n",
      "Iter 16000, Total: 3.4059e-02, Time: 120.23 secs\n",
      "IC: 1.0306e-02, PBC: 1.8661e-04, PDE: 2.3567e-02\n",
      "For uIC,  min uLW: 3.6414e+00, max uLW: 1.0363e+01\n",
      "For uBC,  min uLW: 2.0168e+00, max uLW: 2.8038e+00\n",
      "For uPDE, min uLW: 1.7041e+00, max uLW: 2.0633e+01\n",
      "For vIC,  min vLW: 2.0838e+00, max vLW: 7.3889e+00\n",
      "For vBC,  min vLW: 2.2833e+00, max vLW: 3.5415e+00\n",
      "For vPDE, min vLW: 2.1830e+00, max vLW: 2.3146e+01\n",
      "Iter 17000, Total: 2.5307e-02, Time: 119.49 secs\n",
      "IC: 7.4359e-03, PBC: 1.5340e-04, PDE: 1.7718e-02\n",
      "For uIC,  min uLW: 3.7577e+00, max uLW: 1.0559e+01\n",
      "For uBC,  min uLW: 2.0185e+00, max uLW: 2.8060e+00\n",
      "For uPDE, min uLW: 1.7127e+00, max uLW: 2.0715e+01\n",
      "For vIC,  min vLW: 2.0841e+00, max vLW: 7.3894e+00\n",
      "For vBC,  min vLW: 2.2833e+00, max vLW: 3.5417e+00\n",
      "For vPDE, min vLW: 2.1838e+00, max vLW: 2.4404e+01\n",
      "Iter 18000, Total: 6.6087e+00, Time: 119.85 secs\n",
      "IC: 3.4518e+00, PBC: 7.3778e-03, PDE: 3.1495e+00\n",
      "For uIC,  min uLW: 4.2582e+00, max uLW: 1.1340e+01\n",
      "For uBC,  min uLW: 2.4037e+00, max uLW: 3.2501e+00\n",
      "For uPDE, min uLW: 2.4953e+00, max uLW: 2.1603e+01\n",
      "For vIC,  min vLW: 2.7247e+00, max vLW: 8.0360e+00\n",
      "For vBC,  min vLW: 2.8962e+00, max vLW: 4.1331e+00\n",
      "For vPDE, min vLW: 2.6317e+00, max vLW: 2.6608e+01\n",
      "Iter 19000, Total: 9.0345e-01, Time: 119.67 secs\n",
      "IC: 3.8003e-01, PBC: 2.2784e-03, PDE: 5.2114e-01\n",
      "For uIC,  min uLW: 4.4568e+00, max uLW: 1.1813e+01\n",
      "For uBC,  min uLW: 2.4136e+00, max uLW: 3.3733e+00\n",
      "For uPDE, min uLW: 2.5739e+00, max uLW: 2.3420e+01\n",
      "For vIC,  min vLW: 2.7731e+00, max vLW: 8.3270e+00\n",
      "For vBC,  min vLW: 2.9481e+00, max vLW: 4.2155e+00\n",
      "For vPDE, min vLW: 2.6908e+00, max vLW: 2.7431e+01\n",
      "Iter 20000, Total: 4.7247e-01, Time: 118.54 secs\n",
      "IC: 1.6323e-01, PBC: 2.2827e-03, PDE: 3.0696e-01\n",
      "For uIC,  min uLW: 4.4586e+00, max uLW: 1.1824e+01\n",
      "For uBC,  min uLW: 2.4138e+00, max uLW: 3.3739e+00\n",
      "For uPDE, min uLW: 2.5860e+00, max uLW: 2.4091e+01\n",
      "For vIC,  min vLW: 2.7772e+00, max vLW: 8.3305e+00\n",
      "For vBC,  min vLW: 2.9517e+00, max vLW: 4.2293e+00\n",
      "For vPDE, min vLW: 2.6937e+00, max vLW: 2.7714e+01\n",
      "Iter 21000, Total: 3.0857e-01, Time: 119.81 secs\n",
      "IC: 9.2096e-02, PBC: 2.2461e-03, PDE: 2.1422e-01\n",
      "For uIC,  min uLW: 4.4620e+00, max uLW: 1.1825e+01\n",
      "For uBC,  min uLW: 2.4142e+00, max uLW: 3.3761e+00\n",
      "For uPDE, min uLW: 2.5869e+00, max uLW: 2.4425e+01\n",
      "For vIC,  min vLW: 2.7780e+00, max vLW: 8.3339e+00\n",
      "For vBC,  min vLW: 2.9552e+00, max vLW: 4.2596e+00\n",
      "For vPDE, min vLW: 2.6937e+00, max vLW: 2.7961e+01\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iter 22000, Total: 2.1349e-01, Time: 119.99 secs\n",
      "IC: 5.9556e-02, PBC: 1.7438e-03, PDE: 1.5219e-01\n",
      "For uIC,  min uLW: 4.4673e+00, max uLW: 1.1826e+01\n",
      "For uBC,  min uLW: 2.4147e+00, max uLW: 3.3787e+00\n",
      "For uPDE, min uLW: 2.5932e+00, max uLW: 2.4603e+01\n",
      "For vIC,  min vLW: 2.7781e+00, max vLW: 8.3341e+00\n",
      "For vBC,  min vLW: 2.9626e+00, max vLW: 4.2899e+00\n",
      "For vPDE, min vLW: 2.6937e+00, max vLW: 2.8141e+01\n",
      "Iter 23000, Total: 1.5257e-01, Time: 117.65 secs\n",
      "IC: 4.2148e-02, PBC: 1.2303e-03, PDE: 1.0919e-01\n",
      "For uIC,  min uLW: 4.4759e+00, max uLW: 1.1829e+01\n",
      "For uBC,  min uLW: 2.4151e+00, max uLW: 3.3809e+00\n",
      "For uPDE, min uLW: 2.6059e+00, max uLW: 2.4696e+01\n",
      "For vIC,  min vLW: 2.7784e+00, max vLW: 8.3353e+00\n",
      "For vBC,  min vLW: 2.9711e+00, max vLW: 4.3176e+00\n",
      "For vPDE, min vLW: 2.6937e+00, max vLW: 2.8269e+01\n",
      "Iter 24000, Total: 1.1514e-01, Time: 116.54 secs\n",
      "IC: 3.1881e-02, PBC: 8.4529e-04, PDE: 8.2417e-02\n",
      "For uIC,  min uLW: 4.4892e+00, max uLW: 1.1836e+01\n",
      "For uBC,  min uLW: 2.4152e+00, max uLW: 3.3828e+00\n",
      "For uPDE, min uLW: 2.6227e+00, max uLW: 2.4742e+01\n",
      "For vIC,  min vLW: 2.7793e+00, max vLW: 8.3410e+00\n",
      "For vBC,  min vLW: 2.9766e+00, max vLW: 4.3439e+00\n",
      "For vPDE, min vLW: 2.6937e+00, max vLW: 2.8360e+01\n",
      "Iter 25000, Total: 9.2290e-02, Time: 116.58 secs\n",
      "IC: 2.5334e-02, PBC: 6.1251e-04, PDE: 6.6344e-02\n",
      "For uIC,  min uLW: 4.5086e+00, max uLW: 1.1844e+01\n",
      "For uBC,  min uLW: 2.4152e+00, max uLW: 3.3845e+00\n",
      "For uPDE, min uLW: 2.6413e+00, max uLW: 2.4763e+01\n",
      "For vIC,  min vLW: 2.7807e+00, max vLW: 8.3529e+00\n",
      "For vBC,  min vLW: 2.9771e+00, max vLW: 4.3702e+00\n",
      "For vPDE, min vLW: 2.6937e+00, max vLW: 2.8430e+01\n",
      "Iter 26000, Total: 7.6518e-02, Time: 116.52 secs\n",
      "IC: 2.0745e-02, PBC: 4.8905e-04, PDE: 5.5284e-02\n",
      "For uIC,  min uLW: 4.5357e+00, max uLW: 1.1856e+01\n",
      "For uBC,  min uLW: 2.4153e+00, max uLW: 3.3864e+00\n",
      "For uPDE, min uLW: 2.6569e+00, max uLW: 2.4775e+01\n",
      "For vIC,  min vLW: 2.7823e+00, max vLW: 8.3680e+00\n",
      "For vBC,  min vLW: 2.9771e+00, max vLW: 4.3976e+00\n",
      "For vPDE, min vLW: 2.6937e+00, max vLW: 2.8495e+01\n",
      "Iter 27000, Total: 6.3931e-02, Time: 116.10 secs\n",
      "IC: 1.7056e-02, PBC: 4.0811e-04, PDE: 4.6467e-02\n",
      "For uIC,  min uLW: 4.5722e+00, max uLW: 1.1869e+01\n",
      "For uBC,  min uLW: 2.4156e+00, max uLW: 3.3889e+00\n",
      "For uPDE, min uLW: 2.6682e+00, max uLW: 2.4785e+01\n",
      "For vIC,  min vLW: 2.7842e+00, max vLW: 8.3811e+00\n",
      "For vBC,  min vLW: 2.9773e+00, max vLW: 4.4267e+00\n",
      "For vPDE, min vLW: 2.6938e+00, max vLW: 2.8574e+01\n",
      "Iter 28000, Total: 5.3301e-02, Time: 118.46 secs\n",
      "IC: 1.3807e-02, PBC: 3.2583e-04, PDE: 3.9168e-02\n",
      "For uIC,  min uLW: 4.6183e+00, max uLW: 1.1885e+01\n",
      "For uBC,  min uLW: 2.4162e+00, max uLW: 3.3917e+00\n",
      "For uPDE, min uLW: 2.6778e+00, max uLW: 2.4794e+01\n",
      "For vIC,  min vLW: 2.7859e+00, max vLW: 8.3878e+00\n",
      "For vBC,  min vLW: 2.9778e+00, max vLW: 4.4561e+00\n",
      "For vPDE, min vLW: 2.6940e+00, max vLW: 2.8685e+01\n",
      "Iter 29000, Total: 4.4180e-02, Time: 119.61 secs\n",
      "IC: 1.0980e-02, PBC: 2.3602e-04, PDE: 3.2964e-02\n",
      "For uIC,  min uLW: 4.6726e+00, max uLW: 1.1902e+01\n",
      "For uBC,  min uLW: 2.4169e+00, max uLW: 3.3944e+00\n",
      "For uPDE, min uLW: 2.6884e+00, max uLW: 2.4804e+01\n",
      "For vIC,  min vLW: 2.7874e+00, max vLW: 8.3890e+00\n",
      "For vBC,  min vLW: 2.9784e+00, max vLW: 4.4823e+00\n",
      "For vPDE, min vLW: 2.6943e+00, max vLW: 2.8841e+01\n",
      "Iter 30000, Total: 3.6280e-02, Time: 119.64 secs\n",
      "IC: 8.6301e-03, PBC: 1.5767e-04, PDE: 2.7492e-02\n",
      "For uIC,  min uLW: 4.7331e+00, max uLW: 1.1919e+01\n",
      "For uBC,  min uLW: 2.4176e+00, max uLW: 3.3964e+00\n",
      "For uPDE, min uLW: 2.6982e+00, max uLW: 2.4810e+01\n",
      "For vIC,  min vLW: 2.7887e+00, max vLW: 8.3896e+00\n",
      "For vBC,  min vLW: 2.9787e+00, max vLW: 4.5013e+00\n",
      "For vPDE, min vLW: 2.6950e+00, max vLW: 2.9046e+01\n",
      "Iter 31000, Total: 2.9410e-02, Time: 121.32 secs\n",
      "IC: 6.7171e-03, PBC: 1.0277e-04, PDE: 2.2590e-02\n",
      "For uIC,  min uLW: 4.7972e+00, max uLW: 1.1936e+01\n",
      "For uBC,  min uLW: 2.4181e+00, max uLW: 3.3978e+00\n",
      "For uPDE, min uLW: 2.7081e+00, max uLW: 2.4814e+01\n",
      "For vIC,  min vLW: 2.7899e+00, max vLW: 8.3945e+00\n",
      "For vBC,  min vLW: 2.9788e+00, max vLW: 4.5121e+00\n",
      "For vPDE, min vLW: 2.6961e+00, max vLW: 2.9290e+01\n",
      "Iter 32000, Total: 2.3481e-02, Time: 118.83 secs\n",
      "IC: 5.1652e-03, PBC: 6.8049e-05, PDE: 1.8248e-02\n",
      "For uIC,  min uLW: 4.8619e+00, max uLW: 1.1953e+01\n",
      "For uBC,  min uLW: 2.4183e+00, max uLW: 3.3989e+00\n",
      "For uPDE, min uLW: 2.7174e+00, max uLW: 2.4816e+01\n",
      "For vIC,  min vLW: 2.7909e+00, max vLW: 8.4068e+00\n",
      "For vBC,  min vLW: 2.9788e+00, max vLW: 4.5164e+00\n",
      "For vPDE, min vLW: 2.6983e+00, max vLW: 2.9553e+01\n",
      "Iter 33000, Total: 1.8503e-02, Time: 119.90 secs\n",
      "IC: 3.9289e-03, PBC: 4.6250e-05, PDE: 1.4527e-02\n",
      "For uIC,  min uLW: 4.9245e+00, max uLW: 1.1970e+01\n",
      "For uBC,  min uLW: 2.4183e+00, max uLW: 3.3998e+00\n",
      "For uPDE, min uLW: 2.7261e+00, max uLW: 2.4819e+01\n",
      "For vIC,  min vLW: 2.7918e+00, max vLW: 8.4275e+00\n",
      "For vBC,  min vLW: 2.9790e+00, max vLW: 4.5172e+00\n",
      "For vPDE, min vLW: 2.7002e+00, max vLW: 2.9805e+01\n",
      "Iter 34000, Total: 1.4494e-02, Time: 119.36 secs\n",
      "IC: 2.9800e-03, PBC: 3.2220e-05, PDE: 1.1482e-02\n",
      "For uIC,  min uLW: 4.9835e+00, max uLW: 1.1985e+01\n",
      "For uBC,  min uLW: 2.4183e+00, max uLW: 3.4006e+00\n",
      "For uPDE, min uLW: 2.7352e+00, max uLW: 2.4824e+01\n",
      "For vIC,  min vLW: 2.7928e+00, max vLW: 8.4557e+00\n",
      "For vBC,  min vLW: 2.9795e+00, max vLW: 4.5173e+00\n",
      "For vPDE, min vLW: 2.7045e+00, max vLW: 3.0021e+01\n",
      "Iter 35000, Total: 2.2327e+00, Time: 119.30 secs\n",
      "IC: 8.1607e-01, PBC: 8.8748e-03, PDE: 1.4078e+00\n",
      "For uIC,  min uLW: 5.6608e+00, max uLW: 1.3545e+01\n",
      "For uBC,  min uLW: 3.3057e+00, max uLW: 5.0048e+00\n",
      "For uPDE, min uLW: 3.0395e+00, max uLW: 2.6812e+01\n",
      "For vIC,  min vLW: 3.4598e+00, max vLW: 9.2341e+00\n",
      "For vBC,  min vLW: 3.5972e+00, max vLW: 5.0218e+00\n",
      "For vPDE, min vLW: 3.1229e+00, max vLW: 3.1244e+01\n",
      "Iter 36000, Total: 1.3911e+00, Time: 120.17 secs\n",
      "IC: 4.4989e-01, PBC: 1.2098e-02, PDE: 9.2912e-01\n",
      "For uIC,  min uLW: 5.6618e+00, max uLW: 1.3623e+01\n",
      "For uBC,  min uLW: 3.3297e+00, max uLW: 5.0833e+00\n",
      "For uPDE, min uLW: 3.0555e+00, max uLW: 2.8518e+01\n",
      "For vIC,  min vLW: 3.4679e+00, max vLW: 9.2412e+00\n",
      "For vBC,  min vLW: 3.6538e+00, max vLW: 5.1145e+00\n",
      "For vPDE, min vLW: 3.1559e+00, max vLW: 3.1794e+01\n",
      "Iter 37000, Total: 7.9861e-01, Time: 120.52 secs\n",
      "IC: 2.2168e-01, PBC: 9.4492e-03, PDE: 5.6748e-01\n",
      "For uIC,  min uLW: 5.6658e+00, max uLW: 1.3647e+01\n",
      "For uBC,  min uLW: 3.3479e+00, max uLW: 5.1536e+00\n",
      "For uPDE, min uLW: 3.0803e+00, max uLW: 2.9382e+01\n",
      "For vIC,  min vLW: 3.4758e+00, max vLW: 9.2474e+00\n",
      "For vBC,  min vLW: 3.6582e+00, max vLW: 5.3917e+00\n",
      "For vPDE, min vLW: 3.1731e+00, max vLW: 3.2277e+01\n",
      "Iter 38000, Total: 4.6986e-01, Time: 118.78 secs\n",
      "IC: 1.1835e-01, PBC: 5.4385e-03, PDE: 3.4607e-01\n",
      "For uIC,  min uLW: 5.6730e+00, max uLW: 1.3649e+01\n",
      "For uBC,  min uLW: 3.3699e+00, max uLW: 5.2116e+00\n",
      "For uPDE, min uLW: 3.1019e+00, max uLW: 2.9717e+01\n",
      "For vIC,  min vLW: 3.4778e+00, max vLW: 9.2485e+00\n",
      "For vBC,  min vLW: 3.6583e+00, max vLW: 5.6001e+00\n",
      "For vPDE, min vLW: 3.1770e+00, max vLW: 3.2493e+01\n",
      "Iter 39000, Total: 3.0194e-01, Time: 120.31 secs\n",
      "IC: 7.6683e-02, PBC: 2.9210e-03, PDE: 2.2233e-01\n",
      "For uIC,  min uLW: 5.6841e+00, max uLW: 1.3652e+01\n",
      "For uBC,  min uLW: 3.3887e+00, max uLW: 5.2480e+00\n",
      "For uPDE, min uLW: 3.1170e+00, max uLW: 2.9871e+01\n",
      "For vIC,  min vLW: 3.4781e+00, max vLW: 9.2485e+00\n",
      "For vBC,  min vLW: 3.6585e+00, max vLW: 5.7354e+00\n",
      "For vPDE, min vLW: 3.1778e+00, max vLW: 3.2591e+01\n",
      "Iter 40000, Total: 2.1132e-01, Time: 118.84 secs\n",
      "IC: 5.7998e-02, PBC: 1.3196e-03, PDE: 1.5200e-01\n",
      "For uIC,  min uLW: 5.7003e+00, max uLW: 1.3664e+01\n",
      "For uBC,  min uLW: 3.3996e+00, max uLW: 5.2705e+00\n",
      "For uPDE, min uLW: 3.1271e+00, max uLW: 2.9957e+01\n",
      "For vIC,  min vLW: 3.4781e+00, max vLW: 9.2498e+00\n",
      "For vBC,  min vLW: 3.6589e+00, max vLW: 5.8202e+00\n",
      "For vPDE, min vLW: 3.1781e+00, max vLW: 3.2652e+01\n",
      "Iter 41000, Total: 1.5997e-01, Time: 120.47 secs\n",
      "IC: 4.7330e-02, PBC: 6.3736e-04, PDE: 1.1200e-01\n",
      "For uIC,  min uLW: 5.7226e+00, max uLW: 1.3687e+01\n",
      "For uBC,  min uLW: 3.4035e+00, max uLW: 5.2869e+00\n",
      "For uPDE, min uLW: 3.1336e+00, max uLW: 3.0009e+01\n",
      "For vIC,  min vLW: 3.4781e+00, max vLW: 9.2521e+00\n",
      "For vBC,  min vLW: 3.6597e+00, max vLW: 5.8685e+00\n",
      "For vPDE, min vLW: 3.1786e+00, max vLW: 3.2712e+01\n",
      "Iter 42000, Total: 1.2692e-01, Time: 121.91 secs\n",
      "IC: 3.8988e-02, PBC: 4.7705e-04, PDE: 8.7452e-02\n",
      "For uIC,  min uLW: 5.7510e+00, max uLW: 1.3719e+01\n",
      "For uBC,  min uLW: 3.4048e+00, max uLW: 5.3036e+00\n",
      "For uPDE, min uLW: 3.1369e+00, max uLW: 3.0044e+01\n",
      "For vIC,  min vLW: 3.4781e+00, max vLW: 9.2549e+00\n",
      "For vBC,  min vLW: 3.6607e+00, max vLW: 5.8970e+00\n",
      "For vPDE, min vLW: 3.1797e+00, max vLW: 3.2792e+01\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iter 43000, Total: 1.0160e-01, Time: 119.90 secs\n",
      "IC: 3.1370e-02, PBC: 4.2692e-04, PDE: 6.9804e-02\n",
      "For uIC,  min uLW: 5.7852e+00, max uLW: 1.3754e+01\n",
      "For uBC,  min uLW: 3.4061e+00, max uLW: 5.3247e+00\n",
      "For uPDE, min uLW: 3.1380e+00, max uLW: 3.0066e+01\n",
      "For vIC,  min vLW: 3.4781e+00, max vLW: 9.2571e+00\n",
      "For vBC,  min vLW: 3.6616e+00, max vLW: 5.9201e+00\n",
      "For vPDE, min vLW: 3.1808e+00, max vLW: 3.2907e+01\n",
      "Iter 44000, Total: 8.0722e-02, Time: 119.97 secs\n",
      "IC: 2.4433e-02, PBC: 3.4797e-04, PDE: 5.5941e-02\n",
      "For uIC,  min uLW: 5.8237e+00, max uLW: 1.3791e+01\n",
      "For uBC,  min uLW: 3.4074e+00, max uLW: 5.3489e+00\n",
      "For uPDE, min uLW: 3.1381e+00, max uLW: 3.0078e+01\n",
      "For vIC,  min vLW: 3.4781e+00, max vLW: 9.2585e+00\n",
      "For vBC,  min vLW: 3.6622e+00, max vLW: 5.9435e+00\n",
      "For vPDE, min vLW: 3.1815e+00, max vLW: 3.3065e+01\n",
      "Iter 45000, Total: 6.3762e-02, Time: 120.22 secs\n",
      "IC: 1.8525e-02, PBC: 2.4893e-04, PDE: 4.4987e-02\n",
      "For uIC,  min uLW: 5.8640e+00, max uLW: 1.3828e+01\n",
      "For uBC,  min uLW: 3.4088e+00, max uLW: 5.3709e+00\n",
      "For uPDE, min uLW: 3.1383e+00, max uLW: 3.0082e+01\n",
      "For vIC,  min vLW: 3.4781e+00, max vLW: 9.2590e+00\n",
      "For vBC,  min vLW: 3.6624e+00, max vLW: 5.9672e+00\n",
      "For vPDE, min vLW: 3.1815e+00, max vLW: 3.3260e+01\n",
      "Iter 46000, Total: 5.0427e-02, Time: 117.45 secs\n",
      "IC: 1.3877e-02, PBC: 1.6346e-04, PDE: 3.6386e-02\n",
      "For uIC,  min uLW: 5.9036e+00, max uLW: 1.3862e+01\n",
      "For uBC,  min uLW: 3.4100e+00, max uLW: 5.3878e+00\n",
      "For uPDE, min uLW: 3.1390e+00, max uLW: 3.0082e+01\n",
      "For vIC,  min vLW: 3.4781e+00, max vLW: 9.2590e+00\n",
      "For vBC,  min vLW: 3.6624e+00, max vLW: 5.9892e+00\n",
      "For vPDE, min vLW: 3.1816e+00, max vLW: 3.3483e+01\n",
      "Iter 47000, Total: 4.0036e-02, Time: 120.16 secs\n",
      "IC: 1.0389e-02, PBC: 1.0253e-04, PDE: 2.9544e-02\n",
      "For uIC,  min uLW: 5.9411e+00, max uLW: 1.3893e+01\n",
      "For uBC,  min uLW: 3.4110e+00, max uLW: 5.4002e+00\n",
      "For uPDE, min uLW: 3.1400e+00, max uLW: 3.0083e+01\n",
      "For vIC,  min vLW: 3.4782e+00, max vLW: 9.2592e+00\n",
      "For vBC,  min vLW: 3.6624e+00, max vLW: 6.0073e+00\n",
      "For vPDE, min vLW: 3.1818e+00, max vLW: 3.3725e+01\n",
      "Iter 48000, Total: 3.1849e-02, Time: 120.21 secs\n",
      "IC: 7.7932e-03, PBC: 6.2188e-05, PDE: 2.3994e-02\n",
      "For uIC,  min uLW: 5.9761e+00, max uLW: 1.3922e+01\n",
      "For uBC,  min uLW: 3.4122e+00, max uLW: 5.4098e+00\n",
      "For uPDE, min uLW: 3.1410e+00, max uLW: 3.0085e+01\n",
      "For vIC,  min vLW: 3.4784e+00, max vLW: 9.2604e+00\n",
      "For vBC,  min vLW: 3.6624e+00, max vLW: 6.0206e+00\n",
      "For vPDE, min vLW: 3.1819e+00, max vLW: 3.3973e+01\n",
      "Iter 49000, Total: 2.5368e-02, Time: 119.48 secs\n",
      "IC: 5.8477e-03, PBC: 3.7580e-05, PDE: 1.9483e-02\n",
      "For uIC,  min uLW: 6.0087e+00, max uLW: 1.3948e+01\n",
      "For uBC,  min uLW: 3.4143e+00, max uLW: 5.4176e+00\n",
      "For uPDE, min uLW: 3.1416e+00, max uLW: 3.0087e+01\n",
      "For vIC,  min vLW: 3.4787e+00, max vLW: 9.2628e+00\n",
      "For vBC,  min vLW: 3.6624e+00, max vLW: 6.0295e+00\n",
      "For vPDE, min vLW: 3.1820e+00, max vLW: 3.4217e+01\n",
      "Iter 50000, Total: 2.0306e-02, Time: 114.66 secs\n",
      "IC: 4.3948e-03, PBC: 2.4868e-05, PDE: 1.5887e-02\n",
      "For uIC,  min uLW: 6.0389e+00, max uLW: 1.3972e+01\n",
      "For uBC,  min uLW: 3.4181e+00, max uLW: 5.4240e+00\n",
      "For uPDE, min uLW: 3.1418e+00, max uLW: 3.0087e+01\n",
      "For vIC,  min vLW: 3.4794e+00, max vLW: 9.2664e+00\n",
      "For vBC,  min vLW: 3.6624e+00, max vLW: 6.0351e+00\n",
      "For vPDE, min vLW: 3.1829e+00, max vLW: 3.4447e+01\n",
      "Starting with L-BFGS\n"
     ]
    }
   ],
   "source": [
    "layers = [2, 32, 32, 32, 32, 32, 32, 32, 2]\n",
    "N_IC = 128\n",
    "ptsIC=np.load('ptsIC.npy')\n",
    "ptsBC=np.load('ptsBC.npy')\n",
    "ptsPDE=np.load('random_data.npy')\n",
    "uBC = np.load('uBC.npy')\n",
    "vBC = np.load('vBC.npy')\n",
    "x_IC = np.expand_dims(np.linspace(xlo, xhi, N_IC), axis = 1)\n",
    "uIC = u0(x_IC)\n",
    "vIC = v0(x_IC)\n",
    "model = PhysicsInformedNN(period, ptsIC, uIC, vIC, ptsBC, uBC, vBC, ptsPDE, layers)\n",
    "model.train(50000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "t = np.linspace(tlo, thi, 201)\n",
    "x = np.linspace(xlo, xhi, 501)\n",
    "T, X = np.meshgrid(t, x)\n",
    "pts_flat = np.hstack((T.flatten()[:, None], X.flatten()[:, None]))\n",
    "u_pred, v_pred = model.predict(pts_flat)           \n",
    "u_pred = griddata(pts_flat, u_pred.flatten(), (T, X), method='cubic')\n",
    "v_pred = griddata(pts_flat, v_pred.flatten(), (T, X), method='cubic')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualizations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = scipy.io.loadmat('Data/NLS.mat')\n",
    "t = data['t'].flatten()[:,None]\n",
    "x2 = data['x'].flatten()[:,None]\n",
    "u_sol = np.real(data['Exact']).T\n",
    "v_sol = np.imag(data['Exact']).T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 218472 characters]",
      "text/plain": [
       "<Figure size 1100x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(11, 5))\n",
    "ax = fig.add_subplot(1, 1, 1)\n",
    "#\n",
    "ax.plot(ptsPDE[:, 0], ptsPDE[:, 1], \n",
    "    'rd', label = 'PDE Data (%d points)' % (ptsPDE.shape[0]), \n",
    "    markersize = 4,  # marker size doubled\n",
    "    clip_on = False,\n",
    "    alpha=1.0\n",
    ")\n",
    "\n",
    "ax.plot(ptsIC[:, 0], ptsIC[:, 1], \n",
    "    'bd', label = 'IC Data (%d points)' % (ptsIC.shape[0]), \n",
    "    markersize = 4,  # marker size doubled\n",
    "    clip_on = False,\n",
    "    alpha=1.0\n",
    ")\n",
    "\n",
    "\n",
    "ax.plot(ptsBC[:, 0], ptsBC[:, 1], \n",
    "    'gd', label = 'BC Data (%d points)' % (ptsBC.shape[0]), \n",
    "    markersize = 4,  # marker size doubled\n",
    "    clip_on = False,\n",
    "    alpha=1.0\n",
    ")\n",
    "\n",
    "ax.set_xlabel('$t$', size=15)\n",
    "ax.set_ylabel('$x$', size=15)\n",
    "ax.legend(\n",
    "    loc='upper center', \n",
    "    bbox_to_anchor=(0.9, -0.05), \n",
    "    ncol=5, \n",
    "    frameon=False, \n",
    "    prop={'size': 15}\n",
    ")\n",
    "ax.legend()\n",
    "ax.set_title('Points', fontsize = 15) # font size doubled\n",
    "ax.tick_params(labelsize=12)\n",
    "#\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "l2: 0.05442057626694608\n",
      "l1: 0.04405289936639366\n",
      "linf: 0.05792182416967903\n"
     ]
    }
   ],
   "source": [
    "print(f'l2: {relative_error_l2(u_pred.T,u_sol)}')\n",
    "print(f'l1: {relative_error_l1(u_pred.T,u_sol)}')\n",
    "print(f'linf: {relative_error_linf(u_pred.T,u_sol)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "l2: 0.07263661451889662\n",
      "l1: 0.07055344321462\n",
      "linf: 0.0890658849382605\n"
     ]
    }
   ],
   "source": [
    "print(f'l2: {relative_error_l2(-v_pred.T,v_sol)}')\n",
    "print(f'l1: {relative_error_l1(-v_pred.T,v_sol)}')\n",
    "print(f'linf: {relative_error_linf(-v_pred.T,v_sol)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "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.12.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
