{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MemoryInfo(free=15420489728, total=16911433728)\n",
      "6523164.234790019\n",
      "29.250712871551514\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 18524 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 18080 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "26073076.433106028\n"
     ]
    }
   ],
   "source": [
    "from numba import cuda\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import time\n",
    "import math\n",
    "from numba.cuda.random import create_xoroshiro128p_states, xoroshiro128p_uniform_float32\n",
    "\n",
    "cuda.select_device(3)\n",
    "print(cuda.current_context().get_memory_info())\n",
    "\n",
    "@cuda.jit\n",
    "def warren1995_kernel(phi, c, D, temp, phi_out, c_out, rng_states, T):\n",
    "    \n",
    "    startx, starty = cuda.grid(2)    \n",
    "    stridex, stridey = cuda.gridsize(2) \n",
    "    thread_id = cuda.grid(1)\n",
    "    \n",
    "    T = T\n",
    "    T_mA = 1728.\n",
    "    T_mB = 1358.\n",
    "    L_A = 2350.\n",
    "    L_B = 1728.\n",
    "    s_A = 0.000037\n",
    "    s_B = 0.000029\n",
    "    D_L = 0.00001\n",
    "    D_S = 0.000000001\n",
    "    B_A = 0.33\n",
    "    B_B = 0.39\n",
    "    v_m = 7.42\n",
    "    R = 8.314\n",
    "    y_e = 0.04\n",
    "    a = 0.3\n",
    "    dx = 4.6e-06\n",
    "    d = dx/0.94\n",
    "    dt = dx*dx/(5.*D_L)\n",
    "    \n",
    "    M_A = T_mA*T_mA*B_A/(6.*math.sqrt(2.)*L_A*d)\n",
    "    M_B = T_mB*T_mB*B_B/(6.*math.sqrt(2.)*L_B*d)\n",
    "    W_A = 3.*s_A/(math.sqrt(2.)*T_mA*d)\n",
    "    W_B = 3.*s_B/(math.sqrt(2.)*T_mB*d)\n",
    "    e2 = 6.*math.sqrt(2.)*s_A*d/T_mA\n",
    "\n",
    "    # assuming x and y inputs are same length\n",
    "    for i in range(starty, phi.shape[0], stridey):\n",
    "        for j in range(startx, phi.shape[1], stridex):\n",
    "            g = (phi[i][j]**2)*(1-phi[i][j])**2\n",
    "            gprime = 4*phi[i][j]**3 - 6*phi[i][j]**2 + 2*phi[i][j]\n",
    "            H_A = W_A*gprime + 30.*g*L_A*(1./T-1./T_mA)\n",
    "            H_B = W_B*gprime + 30.*g*L_B*(1./T-1./T_mB)\n",
    "            \n",
    "            idx = 1./dx\n",
    "            \n",
    "            dphidx = 0.5*(phi[i][j+1]-phi[i][j-1])*idx\n",
    "            dphidy = 0.5*(phi[i+1][j]-phi[i-1][j])*idx\n",
    "            d2phidx2 = (phi[i][j+1]+phi[i][j-1]-2*phi[i][j])*idx*idx\n",
    "            d2phidy2 = (phi[i+1][j]+phi[i-1][j]-2*phi[i][j])*idx*idx\n",
    "            lphi = d2phidx2 + d2phidy2\n",
    "            d2phidxy = 0.25*(phi[i+1][j+1]-phi[i+1][j-1]-phi[i-1][j+1]+phi[i-1][j-1])*idx*idx\n",
    "            theta = math.atan2(dphidy, dphidx)\n",
    "            eta = 1+y_e*math.cos(4*theta)\n",
    "            etaprime = -4*y_e*math.sin(4*theta)\n",
    "            etadoubleprime = -16*(eta-1)\n",
    "            \n",
    "            M_phi = (1-c[i][j])*M_A + c[i][j]*M_B\n",
    "            \n",
    "            dphidt = e2*eta*eta*lphi - (1.-c[i][j])*H_A - c[i][j]*H_B \n",
    "            dphidt += e2*eta*etaprime*(math.sin(2.*theta)*(d2phidy2-d2phidx2) + 2.*math.cos(2.*theta)*d2phidxy)\n",
    "            dphidt -= 0.5*e2*(etaprime*etaprime + eta*etadoubleprime)*(2.*math.sin(2.*theta)*d2phidxy - lphi - math.cos(2.*theta)*(d2phidy2-d2phidx2))\n",
    "            random = xoroshiro128p_uniform_float32(rng_states, thread_id)\n",
    "            dphidt += a*16*g*((1-c[i][j])*H_A + c[i][j]*H_B)*(2.*random-1.)\n",
    "            dphidt *= M_phi\n",
    "            \n",
    "            #dcdt = D[i][j]*(c[i][j+1]+c[i][j-1]+c[i+1][j]+c[i-1][j]-4*c[i][j])\n",
    "            #dcdt += 0.25*(D[i][j+1]-D[i][j-1])*(c[i][j+1]-c[i][j-1])\n",
    "            #dcdt += 0.25*(D[i+1][j]-D[i-1][j])*(c[i+1][j]-c[i-1][j])\n",
    "            #dcdt *= (idx*idx)\n",
    "            #dcdt += temp[i][j]*lphi\n",
    "            #dcdt += 0.5*(temp[i][j+1]-temp[i][j-1])*dphidx*idx\n",
    "            #dcdt += 0.5*(temp[i+1][j]-temp[i-1][j])*dphidy*idx\n",
    "            \n",
    "            dcdt = 0.5*idx*idx*((D[i+1][j] + D[i][j])*(c[i+1][j] - c[i][j]) - (D[i][j] + D[i-1][j])*(c[i][j] - c[i-1][j]))\n",
    "            dcdt += 0.5*idx*idx*((D[i][j+1] + D[i][j])*(c[i][j+1] - c[i][j]) - (D[i][j] + D[i][j-1])*(c[i][j] - c[i][j-1]))\n",
    "            dcdt += 0.5*idx*idx*((temp[i+1][j] + temp[i][j])*(phi[i+1][j] - phi[i][j]) - (temp[i][j] + temp[i-1][j])*(phi[i][j] - phi[i-1][j]))\n",
    "            dcdt += 0.5*idx*idx*((temp[i][j+1] + temp[i][j])*(phi[i][j+1] - phi[i][j]) - (temp[i][j] + temp[i][j-1])*(phi[i][j] - phi[i][j-1]))\n",
    "            \n",
    "            phi_out[i][j] = phi[i][j] + dphidt*dt\n",
    "            c_out[i][j] = c[i][j] + dcdt*dt\n",
    "            \n",
    "@cuda.jit\n",
    "def warren1995_helper_kernel(phi, c, D, temp, T):\n",
    "    startx, starty = cuda.grid(2)     \n",
    "    stridex, stridey = cuda.gridsize(2) \n",
    "    \n",
    "    T = T\n",
    "    T_mA = 1728.\n",
    "    T_mB = 1358.\n",
    "    L_A = 2350.\n",
    "    L_B = 1728.\n",
    "    s_A = 0.000037\n",
    "    s_B = 0.000029\n",
    "    D_L = 0.00001\n",
    "    D_S = 0.000000001\n",
    "    v_m = 7.42\n",
    "    R = 8.314\n",
    "    dx = 4.6e-06\n",
    "    d = dx/0.25\n",
    "    \n",
    "    W_A = 3.*s_A/(math.sqrt(2.)*T_mA*d)\n",
    "    W_B = 3.*s_B/(math.sqrt(2.)*T_mB*d)\n",
    "    \n",
    "    for i in range(startx, phi.shape[0], stridex):\n",
    "        for j in range(starty, phi.shape[1], stridey):\n",
    "            g = (phi[i][j]**2)*(1.-phi[i][j])**2\n",
    "            gprime = 4.*phi[i][j]**3 - 6.*phi[i][j]**2 + 2.*phi[i][j]\n",
    "            p = (phi[i][j]**3)*(10.-15.*phi[i][j]+6.*phi[i][j]**2)\n",
    "            H_A = W_A*gprime + 30.*g*L_A*(1./T-1./T_mA)\n",
    "            H_B = W_B*gprime + 30.*g*L_B*(1./T-1./T_mB)\n",
    "            D[i][j] = D_S+p*(D_L-D_S)\n",
    "            temp[i][j] = D[i][j]*v_m*c[i][j]*(1-c[i][j])*(H_B-H_A)/R\n",
    "            \n",
    "@cuda.jit\n",
    "def warren1995_combined_kernel(phi_device, c_device, phi_out_device, c_out_device, rng_states, T, wall):\n",
    "    startx, starty = cuda.grid(2)    \n",
    "    stridex, stridey = cuda.gridsize(2) \n",
    "    thread_id = cuda.grid(1)\n",
    "    \n",
    "    T = T\n",
    "    T_mA = 1728.\n",
    "    T_mB = 1358.\n",
    "    L_A = 2350.\n",
    "    L_B = 1728.\n",
    "    s_A = 0.000037\n",
    "    s_B = 0.000029\n",
    "    D_L = 0.00001\n",
    "    D_S = 0.000000001\n",
    "    B_A = 0.33\n",
    "    B_B = 0.39\n",
    "    v_m = 7.42\n",
    "    R = 8.314\n",
    "    y_e = 0.04\n",
    "    a = 0.3\n",
    "    dx = 4.6e-06\n",
    "    d = dx/0.94\n",
    "    dt = dx*dx/(5.*D_L)\n",
    "    \n",
    "    #gr = cuda.cg.this_grid()\n",
    "    \n",
    "    M_A = T_mA*T_mA*B_A/(6.*math.sqrt(2.)*L_A*d)\n",
    "    M_B = T_mB*T_mB*B_B/(6.*math.sqrt(2.)*L_B*d)\n",
    "    W_A = 3.*s_A/(math.sqrt(2.)*T_mA*d)\n",
    "    W_B = 3.*s_B/(math.sqrt(2.)*T_mB*d)\n",
    "    e2 = 6.*math.sqrt(2.)*s_A*d/T_mA\n",
    "    \n",
    "    size = stridex*stridey\n",
    "\n",
    "    # assuming x and y inputs are same length\n",
    "    for k in range(1):\n",
    "        if k%2 == 0:\n",
    "            phi = phi_device\n",
    "            c = c_device\n",
    "            phi_out = phi_out_device\n",
    "            c_out = c_out_device\n",
    "        else:\n",
    "            phi = phi_out_device\n",
    "            c = c_out_device\n",
    "            phi_out = phi_device\n",
    "            c_out = c_device\n",
    "        for i in range(starty+1, phi.shape[0]-1, stridey):\n",
    "            for j in range(startx+1, phi.shape[1]-1, stridex):\n",
    "                g = (phi[i][j]**2)*(1-phi[i][j])**2\n",
    "                gprime = 4*phi[i][j]**3 - 6*phi[i][j]**2 + 2*phi[i][j]\n",
    "                H_A = W_A*gprime + 30.*g*L_A*(1./T-1./T_mA)\n",
    "                H_B = W_B*gprime + 30.*g*L_B*(1./T-1./T_mB)\n",
    "\n",
    "                idx = 1./dx\n",
    "\n",
    "                dphidx = 0.5*(phi[i][j+1]-phi[i][j-1])*idx\n",
    "                dphidy = 0.5*(phi[i+1][j]-phi[i-1][j])*idx\n",
    "                d2phidx2 = (phi[i][j+1]+phi[i][j-1]-2*phi[i][j])*idx*idx\n",
    "                d2phidy2 = (phi[i+1][j]+phi[i-1][j]-2*phi[i][j])*idx*idx\n",
    "                lphi = d2phidx2 + d2phidy2\n",
    "                d2phidxy = 0.25*(phi[i+1][j+1]-phi[i+1][j-1]-phi[i-1][j+1]+phi[i-1][j-1])*idx*idx\n",
    "                theta = math.atan2(dphidy, dphidx)\n",
    "                eta = 1+y_e*math.cos(4*theta)\n",
    "                etaprime = -4*y_e*math.sin(4*theta)\n",
    "                etadoubleprime = -16*(eta-1)\n",
    "\n",
    "                M_phi = (1-c[i][j])*M_A + c[i][j]*M_B\n",
    "\n",
    "                dphidt = e2*eta*eta*lphi - (1.-c[i][j])*H_A - c[i][j]*H_B \n",
    "                dphidt += e2*eta*etaprime*(math.sin(2.*theta)*(d2phidy2-d2phidx2) + 2.*math.cos(2.*theta)*d2phidxy)\n",
    "                dphidt -= 0.5*e2*(etaprime*etaprime + eta*etadoubleprime)*(2.*math.sin(2.*theta)*d2phidxy - lphi - math.cos(2.*theta)*(d2phidy2-d2phidx2))\n",
    "                random = xoroshiro128p_uniform_float32(rng_states, thread_id)\n",
    "                dphidt += a*16*g*((1-c[i][j])*H_A + c[i][j]*H_B)*(2.*random-1.)\n",
    "                dphidt *= M_phi\n",
    "\n",
    "                Dl = D_S+(phi[i-1][j]**3)*(10.-15.*phi[i-1][j]+6.*phi[i-1][j]**2)*(D_L-D_S)\n",
    "                Dr = D_S+(phi[i+1][j]**3)*(10.-15.*phi[i+1][j]+6.*phi[i+1][j]**2)*(D_L-D_S)\n",
    "                Du = D_S+(phi[i][j+1]**3)*(10.-15.*phi[i][j+1]+6.*phi[i][j+1]**2)*(D_L-D_S)\n",
    "                Dd = D_S+(phi[i][j-1]**3)*(10.-15.*phi[i][j-1]+6.*phi[i][j-1]**2)*(D_L-D_S)\n",
    "                Dc = D_S+(phi[i][j]**3)*(10.-15.*phi[i][j]+6.*phi[i][j]**2)*(D_L-D_S)\n",
    "\n",
    "                phi_temp = phi[i-1][j]\n",
    "                c_temp = c[i-1][j]\n",
    "                g = (phi_temp**2)*(1.-phi_temp)**2\n",
    "                gprime = 4.*phi_temp**3 - 6.*phi_temp**2 + 2.*phi_temp\n",
    "                H_A = W_A*gprime + 30.*g*L_A*(1./T-1./T_mA)\n",
    "                H_B = W_B*gprime + 30.*g*L_B*(1./T-1./T_mB)\n",
    "                templ = Dl*v_m*c_temp*(1-c_temp)*(H_B-H_A)/R\n",
    "                phi_temp = phi[i+1][j]\n",
    "                c_temp = c[i+1][j]\n",
    "                g = (phi_temp**2)*(1.-phi_temp)**2\n",
    "                gprime = 4.*phi_temp**3 - 6.*phi_temp**2 + 2.*phi_temp\n",
    "                H_A = W_A*gprime + 30.*g*L_A*(1./T-1./T_mA)\n",
    "                H_B = W_B*gprime + 30.*g*L_B*(1./T-1./T_mB)\n",
    "                tempr = Dr*v_m*c_temp*(1-c_temp)*(H_B-H_A)/R\n",
    "                phi_temp = phi[i][j+1]\n",
    "                c_temp = c[i][j+1]\n",
    "                g = (phi_temp**2)*(1.-phi_temp)**2\n",
    "                gprime = 4.*phi_temp**3 - 6.*phi_temp**2 + 2.*phi_temp\n",
    "                H_A = W_A*gprime + 30.*g*L_A*(1./T-1./T_mA)\n",
    "                H_B = W_B*gprime + 30.*g*L_B*(1./T-1./T_mB)\n",
    "                tempu = Du*v_m*c_temp*(1-c_temp)*(H_B-H_A)/R\n",
    "                phi_temp = phi[i][j-1]\n",
    "                c_temp = c[i][j-1]\n",
    "                g = (phi_temp**2)*(1.-phi_temp)**2\n",
    "                gprime = 4.*phi_temp**3 - 6.*phi_temp**2 + 2.*phi_temp\n",
    "                H_A = W_A*gprime + 30.*g*L_A*(1./T-1./T_mA)\n",
    "                H_B = W_B*gprime + 30.*g*L_B*(1./T-1./T_mB)\n",
    "                tempd = Dd*v_m*c_temp*(1-c_temp)*(H_B-H_A)/R\n",
    "                phi_temp = phi[i][j]\n",
    "                c_temp = c[i][j]\n",
    "                g = (phi_temp**2)*(1.-phi_temp)**2\n",
    "                gprime = 4.*phi_temp**3 - 6.*phi_temp**2 + 2.*phi_temp\n",
    "                H_A = W_A*gprime + 30.*g*L_A*(1./T-1./T_mA)\n",
    "                H_B = W_B*gprime + 30.*g*L_B*(1./T-1./T_mB)\n",
    "                tempc = Dc*v_m*c_temp*(1-c_temp)*(H_B-H_A)/R\n",
    "\n",
    "                dcdt = 0.5*idx*idx*((Dr + Dc)*(c[i+1][j] - c[i][j]) - (Dc + Dl)*(c[i][j] - c[i-1][j]))\n",
    "                dcdt += 0.5*idx*idx*((Du + Dc)*(c[i][j+1] - c[i][j]) - (Dc + Dd)*(c[i][j] - c[i][j-1]))\n",
    "                dcdt += 0.5*idx*idx*((tempr + tempc)*(phi[i+1][j] - phi[i][j]) - (tempc + templ)*(phi[i][j] - phi[i-1][j]))\n",
    "                dcdt += 0.5*idx*idx*((tempu + tempc)*(phi[i][j+1] - phi[i][j]) - (tempc + tempd)*(phi[i][j] - phi[i][j-1]))\n",
    "\n",
    "                phi_out[i][j] = phi[i][j] + dphidt*dt\n",
    "                c_out[i][j] = c[i][j] + dcdt*dt\n",
    "        #gr.sync()\n",
    "        \"\"\"\n",
    "        for i in range(starty+startx*stridey, phi.shape[1], stridey*stridex):\n",
    "            phi_out[0][i] = phi_out[1][i]\n",
    "            phi_out[phi.shape[0]-1][i] = phi_out[phi.shape[0]-2][i]\n",
    "            c_out[0][i] = c_out[1][i]\n",
    "            c_out[phi.shape[0]-1][i] = c_out[phi.shape[0]-2][i]\n",
    "        #gr.sync()\n",
    "        for i in range(starty+startx*stridey, phi.shape[0], stridey*stridex):\n",
    "            phi_out[i][0] = phi_out[i][1]\n",
    "            phi_out[i][phi.shape[1]-1] = phi_out[i][phi.shape[1]-2]\n",
    "            c_out[i][0] = c_out[i][1]\n",
    "            c_out[i][phi.shape[1]-1] = c_out[i][phi.shape[1]-2]\n",
    "        \"\"\"\n",
    "        #gr.sync()\n",
    "    \n",
    "@cuda.jit\n",
    "def neumann_boundary_conditions_kernel(out):\n",
    "    startx, starty = cuda.grid(2)     \n",
    "    stridex, stridey = cuda.gridsize(2) \n",
    "\n",
    "    # assuming x and y inputs are same length\n",
    "    for i in range(starty+startx*stridey, out.shape[1], stridey*stridex):\n",
    "            out[0][i] = out[1][i]\n",
    "            out[out.shape[0]-1][i] = out[out.shape[0]-2][i]\n",
    "    for i in range(starty+startx*stridey, out.shape[0], stridey*stridex):\n",
    "            out[i][0] = out[i][1]\n",
    "            out[i][out.shape[1]-1] = out[i][out.shape[1]-2]\n",
    "\n",
    "@cuda.jit\n",
    "def periodic_boundary_conditions_kernel(out):\n",
    "    startx, starty = cuda.grid(2)\n",
    "    stridex, stridey = cuda.gridsize(2)\n",
    "\n",
    "    # assuming x and y inputs are same length\n",
    "    for i in range(starty+startx*stridey, out.shape[1], stridey*stridex):\n",
    "            out[0][i] = out[out.shape[0]-2][i]\n",
    "            out[out.shape[0]-1][i] = out[1][i]\n",
    "    for i in range(starty+startx*stridey, out.shape[0], stridey*stridex):\n",
    "            out[i][0] = out[i][out.shape[1]-2]\n",
    "            out[i][out.shape[1]-1] = out[i][1]\n",
    "            \n",
    "for j in np.arange(1574, 1574.05, 0.1):\n",
    "\n",
    "    n = 4000\n",
    "    c = np.zeros((n,n)).astype(np.float64)\n",
    "    c[:] = 0.40831\n",
    "    c = np.transpose(c)\n",
    "    print(np.sum(c[1:-2,1:-2]))\n",
    "    phi = np.zeros((n,n)).astype(np.float64)\n",
    "    phi += 1\n",
    "    phi = np.transpose(phi)\n",
    "\n",
    "    diamond_size = 15\n",
    "    for i in range(diamond_size):\n",
    "        phi[0:(diamond_size-i),i] = 0\n",
    "        #phi[n//2-(diamond_size-i):n//2+(diamond_size-i),n//2-i:n//2+i] = 0\n",
    "    \n",
    "    phi_device = cuda.to_device(phi)\n",
    "    c_device = cuda.to_device(c)\n",
    "    phi_out_device = cuda.device_array_like(c)\n",
    "    c_out_device = cuda.device_array_like(c)\n",
    "    D_device = cuda.device_array_like(c)\n",
    "    temp_device = cuda.device_array_like(c)\n",
    "    \n",
    "    wall = np.zeros([4], dtype=int)\n",
    "    wall_device = cuda.to_device(wall)\n",
    "\n",
    "    threads_per_block = (16,16)\n",
    "    blocks_per_grid = (16,16)\n",
    "    t0 = time.time()\n",
    "    neumann_boundary_conditions_kernel[blocks_per_grid, threads_per_block](phi_device)\n",
    "    neumann_boundary_conditions_kernel[blocks_per_grid, threads_per_block](c_device)\n",
    "    rng_states = create_xoroshiro128p_states(256*256, seed=3)\n",
    "    for i in range(4000):\n",
    "        \"\"\"\n",
    "        warren1995_helper_kernel[blocks_per_grid, threads_per_block](phi_device, c_device, D_device, temp_device, j)\n",
    "        cuda.synchronize()\n",
    "        warren1995_kernel[blocks_per_grid, threads_per_block](phi_device, c_device, D_device, temp_device, phi_out_device, c_out_device, rng_states, j)\n",
    "        cuda.synchronize()\n",
    "        \"\"\"\n",
    "        warren1995_combined_kernel[blocks_per_grid, threads_per_block](phi_device, c_device, phi_out_device, c_out_device, rng_states, j, wall_device)\n",
    "        cuda.synchronize()\n",
    "        \n",
    "        neumann_boundary_conditions_kernel[blocks_per_grid, threads_per_block](phi_out_device)\n",
    "        neumann_boundary_conditions_kernel[blocks_per_grid, threads_per_block](c_out_device)\n",
    "        cuda.synchronize()\n",
    "        \n",
    "        temp = c_device\n",
    "        c_device = c_out_device\n",
    "        c_out_device = temp\n",
    "        temp = phi_device\n",
    "        phi_device = phi_out_device\n",
    "        phi_out_device = temp\n",
    "        \n",
    "        cuda.synchronize()\n",
    "    t1 = time.time()\n",
    "    print(t1-t0)\n",
    "    c_host = c_device.copy_to_host()\n",
    "    c_host = c_host[1:-2, 1:-2]\n",
    "    c_host = np.concatenate((c_host[::-1], c_host), axis=0)\n",
    "    c_host = np.concatenate((c_host[:,::-1], c_host), axis=1)\n",
    "    phi_host = phi_device.copy_to_host()\n",
    "    phi_host = phi_host[1:-2, 1:-2]\n",
    "    phi_host = np.concatenate((phi_host[::-1], phi_host), axis=0)\n",
    "    phi_host = np.concatenate((phi_host[:,::-1], phi_host), axis=1)\n",
    "    \n",
    "    plt.imshow(phi_host, interpolation=\"bicubic\")\n",
    "    #plt.text(1300, 1900, \"T = \"+str.format('{0:.1f}', j), color='black', fontsize=12)\n",
    "    #plt.savefig(\"phi_\"+str.format('{0:.1f}', j)+\".png\")\n",
    "    plt.show()\n",
    "    plt.imshow(c_host, interpolation=\"bicubic\")\n",
    "    #plt.text(1300, 1900, \"T = \"+str.format('{0:.1f}', j), color='white', fontsize=12)\n",
    "    #plt.savefig(\"c_\"+str.format('{0:.1f}', j)+\".png\")\n",
    "    plt.show()\n",
    "    print(np.sum(c_host[1:-2,1:-2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "module 'numba' has no attribute 'max_cooperative_grid_blocks'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[46], line 2\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mnumba\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mnumba\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmax_cooperative_grid_blocks\u001b[49m()\n",
      "\u001b[0;31mAttributeError\u001b[0m: module 'numba' has no attribute 'max_cooperative_grid_blocks'"
     ]
    }
   ],
   "source": [
    "import numba\n",
    "numba.max_cooperative_grid_blocks()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "17.4 s ± 227 ms per loop (mean ± std. dev. of 7 runs, 5 loops each)\n"
     ]
    }
   ],
   "source": [
    "import pyphasefield as ppf\n",
    "\n",
    "sim = ppf.Simulation(\"test\")\n",
    "sim.init_sim_Warren1995(dim=[1000,1000])\n",
    "%timeit -n5 sim.simulate(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 6304 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 6412 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "sim.plot_simulation()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Hybrid Kernel",
   "language": "python",
   "name": "my_conda_python_hybrid_kernel"
  },
  "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.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
