{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "### Example of a 1D Channel driven flow\n", "\n", "Model Setup\n", "-----------\n", "\n", "2D, Stokes Equation with noslip BC at top and bottom boundary and a lateral pressure gradient driving the flow, a.k.a. Poiseuille Flow.\n", "\n", "\\\\[\n", "\\frac{\\partial \\tau}{\\partial y} = \\mu \\frac{\\partial^{2} \\mathbf{u}}{\\partial{y}^{2}} = \\frac{\\partial p}{\\partial x}\n", "\\\\]\n", "\n", "\\\\[\n", "\\nabla \\cdot \\mathbf{u} = 0\n", "\\\\]\n", "\n", "with $ x_{a} \\leqslant x \\leqslant x_{b} $ and $ 0.0 \\leqslant y \\leqslant h $\n", "\n", "Boundary conditions:\n", "\n", " * $\\mathbf{u}(x,y=h) = \\mathbf{u}(x,y=0) = \\left[0,0 \\right]$\n", " * $P(x_a) = P_a$\n", " * $P(x_b) = P_b $\n", "\n", "------\n", "\n", "A 1D solution in $y$-axis, described by\n", "\n", "$ \\mathbf{u}(x,y) = \\left[ \\frac{1}{2 \\mu} \\frac{\\partial p }{\\partial x} ( y^{2} - h y ), 0.0 \\right]$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We implement the above boundary conditions using:\n", " * a `DirichletCondition` object for $\\mathbf{u}(x,y=1) = \\mathbf{u}(x,y=0) = \\left[0,0 \\right]$\n", " * a `NeumannCondition` object for $P(x_a) = P_a$ & $P(x_b) = P_b $\n", "\n", "The `NeumannCondition` object, used with the `Stokes` object, defines a stress along a boundary such that:\n", " * $ \\sigma_{ij} n_{j} = \\phi_{i} $ on $ \\Gamma_{\\phi} $\n", "\n", " where \n", " * $n$ is the surface normal pointing outwards,\n", " * $ \\sigma_{ij} = \\tau_{ij} - \\delta_{ij} P$ is the prescribed stress tensor, which is multiplied my $ n $ at $ \\Gamma_{\\phi} $ to produce $\\phi_{i}$, a surface traction on the given boundary." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import underworld as uw\n", "from underworld import function as fn\n", "import glucifer\n", "import math\n", "import numpy as np\n", "\n", "# for machines without matplotlib #\n", "make_graphs = True\n", "try:\n", " import matplotlib\n", "except ImportError:\n", " make_graphs=False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Setup parameters\n", "-----" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# domain height\n", "h = 1.0\n", "# Set a constant viscosity.\n", "viscosity = 1.4\n", "\n", "# position of walls and associated pressure on walls\n", "xa = -1.0\n", "pa = 4.0\n", "\n", "xb = 1.0\n", "pb = 3.0" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "mesh = uw.mesh.FeMesh_Cartesian( elementType = (\"Q1/dQ0\"), \n", " elementRes = (128, 128), \n", " minCoord = (xa, 0.), \n", " maxCoord = (xb, h))\n", "\n", "velocityField = mesh.add_variable( nodeDofCount=2 )\n", "pressureField = mesh.subMesh.add_variable( nodeDofCount=1 )\n", "appliedTractionField = mesh.add_variable( nodeDofCount=2 )\n", "\n", "# initialise velocity, pressure field\n", "velocityField.data[:] = [0.,0.]\n", "pressureField.data[:] = 0." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "jWalls = mesh.specialSets[\"MinJ_VertexSet\"] + mesh.specialSets[\"MaxJ_VertexSet\"]\n", "iWalls = mesh.specialSets[\"MinI_VertexSet\"] + mesh.specialSets[\"MaxI_VertexSet\"]\n", "allWalls = iWalls + jWalls" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-0.5\n" ] } ], "source": [ "vBC = uw.conditions.DirichletCondition( variable = velocityField, \n", " indexSetsPerDof = (jWalls, allWalls) )\n", "\n", "dp_dx = (pb-pa)/(xb-xa)\n", "\n", "# This stress is multiplied by the wall normal to produce a traction force.\n", "#############\n", "# Remember total stress = deviatoric - isotropic. \n", "# Thus +pressure is a negative stress.\n", "#############\n", "\n", "# The left wall normal unit vector is (-1,0)\n", "# The right wall normal unit vector is (1,0)\n", "\n", "# (-press) * normal_j = surface_force\n", "appliedTractionField.data[mesh.specialSets[\"MinI_VertexSet\"].data] = (pa,0.0)\n", "\n", "appliedTractionField.data[mesh.specialSets[\"MaxI_VertexSet\"].data] = (-1*pb,0.0)\n", "\n", "nbc = uw.conditions.NeumannCondition( fn_flux=appliedTractionField, \n", " variable=velocityField,\n", " indexSetsPerDof=(iWalls, None) )\n", "print dp_dx" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "stokes = uw.systems.Stokes( velocityField = velocityField, \n", " pressureField = pressureField,\n", " conditions = [vBC, nbc],\n", " fn_viscosity = viscosity, \n", " fn_bodyforce = 0.0 )\n", "\n", "solver = uw.systems.Solver( stokes )\n", "solver.solve()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = glucifer.Figure()\n", "velmagfield = uw.function.math.sqrt( uw.function.math.dot( velocityField, velocityField ) )\n", "fig.append( glucifer.objects.VectorArrows(mesh, velocityField, arrowHead=0.2, scaling=0.9) )\n", "# fig.append( glucifer.objects.Mesh(mesh) )\n", "fig.append( glucifer.objects.Surface( mesh, pressureField ) )\n", "fig.show()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "ids = mesh.specialSets[\"MaxI_VertexSet\"]\n", "coords = mesh.data[ids.data] # xcoords\n", "V = velocityField.evaluate(ids)\n", "gradV = velocityField.fn_gradient.evaluate(ids)\n", "\n", "u = V[:,0] ; v = V[:,1]\n", "du_dx = gradV[:,0] ; du_dy = gradV[:,1]\n", "dv_dx = gradV[:,2] ; dv_dy = gradV[:,3]\n", "\n", "strainRate = fn.tensor.symmetric( velocityField.fn_gradient )\n", "devstress = 2.0 * viscosity * strainRate" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def exact_vx(y):\n", " ana_u = 1.0 / (2.0 * viscosity)* dp_dx * (y**2 - h*y)\n", " return ana_u\n", "\n", "def exact_shearSR(y):\n", " shearSR = dp_dx / (2.0*viscosity) * (y - h/2 )\n", " return shearSR" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if make_graphs:\n", " uw.matplotlib_inline()\n", " import matplotlib.pyplot as pyplot\n", " import matplotlib.pylab as pylab\n", " pyplot.ion() # needed to ensure pure python jobs do now hang on show()\n", "\n", " pylab.rcParams[ 'figure.figsize'] = 12, 6\n", " pyplot.plot(coords[:,1], u, 'o', color = 'green', label='vx')\n", " pyplot.plot(coords[:,1], v, 'o', color = 'red', label='vy')\n", " big = np.linspace(0.0,h)\n", " pyplot.plot(big, exact_vx(big), 'D', color = 'purple', label='exact_vx', markersize=2)\n", " pyplot.legend()\n", " pyplot.xlabel('y coords at x=xmax')\n", " pyplot.ylabel('velocity')\n", " pyplot.show()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Relative error against analytic solution: 1.40525963472e-05\n" ] } ], "source": [ "ana_u = exact_vx(coords[:,1])\n", "\n", "abserr = uw.utils._nps_2norm(ana_u - u)\n", "mag = uw.utils._nps_2norm(ana_u)\n", "relerr = abserr / mag\n", "\n", "from mpi4py import MPI\n", "comm = MPI.COMM_WORLD\n", "\n", "\n", "if uw.rank() == 0:\n", " threshold = 1.0e-4\n", " print \"Relative error against analytic solution:\", relerr\n", " if relerr > threshold:\n", " raise RuntimeError(\"The numerical solution is outside the error threshold of the analytic solution.\" \\\n", " \"The Relative error was \", relerr,\" the threshold is \", threshold)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# Further analytics\n", "# pyplot.plot(coords[:,1], du_dy, 'o', color = 'purple', label='du_dy')\n", "# pyplot.plot(coords[:,1], du_dx, '+', color = 'black', label='du_dx')\n", "# pyplot.plot(coords[:,1], dv_dy, 'x', color = 'orange', label='dv_dy')\n", "# pyplot.plot(coords[:,1], dv_dx, '.', color = 'red', label='dv_dx')\n", "# pyplot.legend()\n", "# pyplot.xlabel('y coords at x=xmax')\n", "# pyplot.ylabel('velocity gradients')\n", "# pyplot.show()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# Further analytics\n", "# pyplot.plot(coords[:,1], sr, '-', label='exact_shearSR')\n", "# pyplot.plot(coords[:,1], strainRate.evaluate(ids)[:,2], 'o', color = 'purple', label='sr_shear')\n", "# pyplot.plot(coords[:,1], devstress.evaluate(ids)[:,2], '+', label='tau_shear')\n", "# pyplot.legend()\n", "# pyplot.xlabel('y coords at x=xmax')\n", "# pyplot.ylabel('strain rate')\n", "# pyplot.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.14" } }, "nbformat": 4, "nbformat_minor": 1 }