1*edab6123Sjeremylt{ 2*edab6123Sjeremylt "cells": [ 3*edab6123Sjeremylt { 4*edab6123Sjeremylt "cell_type": "markdown", 5*edab6123Sjeremylt "metadata": {}, 6*edab6123Sjeremylt "source": [ 7*edab6123Sjeremylt "# libCEED for Python examples\n", 8*edab6123Sjeremylt "\n", 9*edab6123Sjeremylt "This is a tutorial to illustrate the main feautures of the Python interface for [libCEED](https://github.com/CEED/libCEED/), the low-level API library for efficient high-order discretization methods developed by the co-design [Center for Efficient Exascale Discretizations](https://ceed.exascaleproject.org/) (CEED) of the [Exascale Computing Project](https://www.exascaleproject.org/) (ECP).\n", 10*edab6123Sjeremylt "\n", 11*edab6123Sjeremylt "While libCEED's focus is on high-order finite/spectral element method implementations, the approach is mostly algebraic and thus applicable to other discretizations in factored form, as explained in the [user manual](https://libceed.readthedocs.io/)." 12*edab6123Sjeremylt ] 13*edab6123Sjeremylt }, 14*edab6123Sjeremylt { 15*edab6123Sjeremylt "cell_type": "markdown", 16*edab6123Sjeremylt "metadata": {}, 17*edab6123Sjeremylt "source": [ 18*edab6123Sjeremylt "## Setting up libCEED for Python\n", 19*edab6123Sjeremylt "\n", 20*edab6123Sjeremylt "Install libCEED for Python by running" 21*edab6123Sjeremylt ] 22*edab6123Sjeremylt }, 23*edab6123Sjeremylt { 24*edab6123Sjeremylt "cell_type": "code", 25*edab6123Sjeremylt "execution_count": null, 26*edab6123Sjeremylt "metadata": {}, 27*edab6123Sjeremylt "outputs": [], 28*edab6123Sjeremylt "source": [ 29*edab6123Sjeremylt "! python -m pip install libceed" 30*edab6123Sjeremylt ] 31*edab6123Sjeremylt }, 32*edab6123Sjeremylt { 33*edab6123Sjeremylt "cell_type": "markdown", 34*edab6123Sjeremylt "metadata": {}, 35*edab6123Sjeremylt "source": [ 36*edab6123Sjeremylt "## CeedElemRestriction\n", 37*edab6123Sjeremylt "\n", 38*edab6123Sjeremylt "Here we show some basic examples to illustrate the `libceed.ElemRestriction` class. In libCEED, a `libceed.ElemRestriction` groups the degrees of freedom (dofs) of the local vector according to the different elements they belong to (see [the API documentation](https://libceed.readthedocs.io/en/latest/libCEEDapi.html#finite-element-operator-decomposition)).\n", 39*edab6123Sjeremylt "\n", 40*edab6123Sjeremylt "Here we illustrate the simple creation and application of a `libceed.ElemRestriction`, with user provided dof indices" 41*edab6123Sjeremylt ] 42*edab6123Sjeremylt }, 43*edab6123Sjeremylt { 44*edab6123Sjeremylt "cell_type": "code", 45*edab6123Sjeremylt "execution_count": null, 46*edab6123Sjeremylt "metadata": {}, 47*edab6123Sjeremylt "outputs": [], 48*edab6123Sjeremylt "source": [ 49*edab6123Sjeremylt "import libceed\n", 50*edab6123Sjeremylt "import numpy as np\n", 51*edab6123Sjeremylt "\n", 52*edab6123Sjeremylt "# In this 1D example, the dofs are indexed as\n", 53*edab6123Sjeremylt "#\n", 54*edab6123Sjeremylt "# Restriction input:\n", 55*edab6123Sjeremylt "# x -- x -- x -- x\n", 56*edab6123Sjeremylt "# 10 -- 11 -- 12 -- 13\n", 57*edab6123Sjeremylt "#\n", 58*edab6123Sjeremylt "# Restriction output:\n", 59*edab6123Sjeremylt "# x -- x | x -- x | x -- x\n", 60*edab6123Sjeremylt "# 10 -- 11 | 11 -- 12 | 12 -- 13\n", 61*edab6123Sjeremylt "\n", 62*edab6123Sjeremylt "ceed = libceed.Ceed()\n", 63*edab6123Sjeremylt "\n", 64*edab6123Sjeremylt "ne = 3\n", 65*edab6123Sjeremylt "\n", 66*edab6123Sjeremylt "x = ceed.Vector(ne+1)\n", 67*edab6123Sjeremylt "a = np.arange(10, 10 + ne+1, dtype=\"float64\")\n", 68*edab6123Sjeremylt "x.set_array(a, cmode=libceed.USE_POINTER)\n", 69*edab6123Sjeremylt "\n", 70*edab6123Sjeremylt "ind = np.zeros(2*ne, dtype=\"int32\")\n", 71*edab6123Sjeremylt "for i in range(ne):\n", 72*edab6123Sjeremylt " ind[2*i+0] = i\n", 73*edab6123Sjeremylt " ind[2*i+1] = i+1\n", 74*edab6123Sjeremylt " \n", 75*edab6123Sjeremylt "r = ceed.ElemRestriction(ne, 2, 1, 1, ne+1, ind, cmode=libceed.USE_POINTER)\n", 76*edab6123Sjeremylt "\n", 77*edab6123Sjeremylt "y = ceed.Vector(2*ne)\n", 78*edab6123Sjeremylt "y.set_value(0)\n", 79*edab6123Sjeremylt "\n", 80*edab6123Sjeremylt "r.apply(x, y)\n", 81*edab6123Sjeremylt "\n", 82*edab6123Sjeremylt "with y.array_read() as y_array:\n", 83*edab6123Sjeremylt " print('y =', y_array)\n" 84*edab6123Sjeremylt ] 85*edab6123Sjeremylt }, 86*edab6123Sjeremylt { 87*edab6123Sjeremylt "cell_type": "markdown", 88*edab6123Sjeremylt "metadata": {}, 89*edab6123Sjeremylt "source": [ 90*edab6123Sjeremylt "* In the following example, we illustrate how to extract the multiplicity of indices in an element restriction" 91*edab6123Sjeremylt ] 92*edab6123Sjeremylt }, 93*edab6123Sjeremylt { 94*edab6123Sjeremylt "cell_type": "code", 95*edab6123Sjeremylt "execution_count": null, 96*edab6123Sjeremylt "metadata": {}, 97*edab6123Sjeremylt "outputs": [], 98*edab6123Sjeremylt "source": [ 99*edab6123Sjeremylt "# In this 1D example, there are four nodes per element\n", 100*edab6123Sjeremylt "# \n", 101*edab6123Sjeremylt "# x -- o -- o -- x -- o -- o -- x -- o -- o -- x\n", 102*edab6123Sjeremylt "\n", 103*edab6123Sjeremylt "ne = 3\n", 104*edab6123Sjeremylt "\n", 105*edab6123Sjeremylt "ind = np.zeros(4*ne, dtype=\"int32\")\n", 106*edab6123Sjeremylt "\n", 107*edab6123Sjeremylt "for i in range(ne):\n", 108*edab6123Sjeremylt " ind[4*i+0] = i*3+0\n", 109*edab6123Sjeremylt " ind[4*i+1] = i*3+1\n", 110*edab6123Sjeremylt " ind[4*i+2] = i*3+2\n", 111*edab6123Sjeremylt " ind[4*i+3] = i*3+3\n", 112*edab6123Sjeremylt "\n", 113*edab6123Sjeremylt "r = ceed.ElemRestriction(ne, 4, 1, 1, 3*ne+1, ind, cmode=libceed.USE_POINTER)\n", 114*edab6123Sjeremylt "\n", 115*edab6123Sjeremylt "mult = r.get_multiplicity()\n", 116*edab6123Sjeremylt "\n", 117*edab6123Sjeremylt "with mult.array_read() as m_array:\n", 118*edab6123Sjeremylt " print('mult =', m_array)\n" 119*edab6123Sjeremylt ] 120*edab6123Sjeremylt }, 121*edab6123Sjeremylt { 122*edab6123Sjeremylt "cell_type": "markdown", 123*edab6123Sjeremylt "metadata": {}, 124*edab6123Sjeremylt "source": [ 125*edab6123Sjeremylt "* In the following example, we illustrate the creation and use of a strided (identity) element restriction. Strided restrictions are typically used for data stored at quadrature points or for vectors stored in the [E-vector](https://libceed.readthedocs.io/en/latest/libCEEDapi.html#finite-element-operator-decomposition) format, such as in Discontinuous Galerkin approximations." 126*edab6123Sjeremylt ] 127*edab6123Sjeremylt }, 128*edab6123Sjeremylt { 129*edab6123Sjeremylt "cell_type": "code", 130*edab6123Sjeremylt "execution_count": null, 131*edab6123Sjeremylt "metadata": {}, 132*edab6123Sjeremylt "outputs": [], 133*edab6123Sjeremylt "source": [ 134*edab6123Sjeremylt "# In this 1D example, the dofs are indexed as\n", 135*edab6123Sjeremylt "#\n", 136*edab6123Sjeremylt "# Restriction input:\n", 137*edab6123Sjeremylt "# x -- x -- x\n", 138*edab6123Sjeremylt "# 10-11 -- 12-13 -- 14-15\n", 139*edab6123Sjeremylt "#\n", 140*edab6123Sjeremylt "# Restriction output:\n", 141*edab6123Sjeremylt "# x -- x | x -- x | x -- x\n", 142*edab6123Sjeremylt "# 10 -- 11 | 12 -- 13 | 14 -- 15\n", 143*edab6123Sjeremylt "\n", 144*edab6123Sjeremylt "ne = 3\n", 145*edab6123Sjeremylt "\n", 146*edab6123Sjeremylt "x = ceed.Vector(2*ne)\n", 147*edab6123Sjeremylt "a = np.arange(10, 10 + 2*ne, dtype=\"float64\")\n", 148*edab6123Sjeremylt "x.set_array(a, cmode=libceed.USE_POINTER)\n", 149*edab6123Sjeremylt "\n", 150*edab6123Sjeremylt "strides = np.array([1, 2, 2], dtype=\"int32\")\n", 151*edab6123Sjeremylt "\n", 152*edab6123Sjeremylt "r = ceed.StridedElemRestriction(ne, 2, 1, 2*ne, strides)\n", 153*edab6123Sjeremylt "\n", 154*edab6123Sjeremylt "y = ceed.Vector(2*ne)\n", 155*edab6123Sjeremylt "y.set_value(0)\n", 156*edab6123Sjeremylt "\n", 157*edab6123Sjeremylt "r.apply(x, y)\n", 158*edab6123Sjeremylt "\n", 159*edab6123Sjeremylt "with y.array_read() as y_array:\n", 160*edab6123Sjeremylt " print('y =', y_array)\n" 161*edab6123Sjeremylt ] 162*edab6123Sjeremylt }, 163*edab6123Sjeremylt { 164*edab6123Sjeremylt "cell_type": "markdown", 165*edab6123Sjeremylt "metadata": {}, 166*edab6123Sjeremylt "source": [ 167*edab6123Sjeremylt "* In the following example, we illustrate the creation and view of a blocked strided (identity) element restriction" 168*edab6123Sjeremylt ] 169*edab6123Sjeremylt }, 170*edab6123Sjeremylt { 171*edab6123Sjeremylt "cell_type": "code", 172*edab6123Sjeremylt "execution_count": null, 173*edab6123Sjeremylt "metadata": {}, 174*edab6123Sjeremylt "outputs": [], 175*edab6123Sjeremylt "source": [ 176*edab6123Sjeremylt "# In this 1D example, there are three elements (four nodes in total) \n", 177*edab6123Sjeremylt "# \n", 178*edab6123Sjeremylt "# x -- x -- x -- x\n", 179*edab6123Sjeremylt "\n", 180*edab6123Sjeremylt "ne = 3\n", 181*edab6123Sjeremylt "\n", 182*edab6123Sjeremylt "strides = np.array([1, 2, 2], dtype=\"int32\")\n", 183*edab6123Sjeremylt "\n", 184*edab6123Sjeremylt "r = ceed.BlockedStridedElemRestriction(ne, 2, 2, 1, ne+1, strides)\n", 185*edab6123Sjeremylt "\n", 186*edab6123Sjeremylt "print(r)" 187*edab6123Sjeremylt ] 188*edab6123Sjeremylt }, 189*edab6123Sjeremylt { 190*edab6123Sjeremylt "cell_type": "markdown", 191*edab6123Sjeremylt "metadata": {}, 192*edab6123Sjeremylt "source": [ 193*edab6123Sjeremylt "### Advanced topics" 194*edab6123Sjeremylt ] 195*edab6123Sjeremylt }, 196*edab6123Sjeremylt { 197*edab6123Sjeremylt "cell_type": "markdown", 198*edab6123Sjeremylt "metadata": {}, 199*edab6123Sjeremylt "source": [ 200*edab6123Sjeremylt "* In the following example (intended for backend developers), we illustrate the creation of a blocked element restriction (from an L-vector to an E-vector) and its transpose (inverse operation, from an E-vector to an L-vector)" 201*edab6123Sjeremylt ] 202*edab6123Sjeremylt }, 203*edab6123Sjeremylt { 204*edab6123Sjeremylt "cell_type": "code", 205*edab6123Sjeremylt "execution_count": null, 206*edab6123Sjeremylt "metadata": {}, 207*edab6123Sjeremylt "outputs": [], 208*edab6123Sjeremylt "source": [ 209*edab6123Sjeremylt "# In this 1D example, the dofs are indexed as\n", 210*edab6123Sjeremylt "# \n", 211*edab6123Sjeremylt "# x -- x -- x -- x -- x -- x -- x -- x -- x\n", 212*edab6123Sjeremylt "# 10 -- 11 -- 12 -- 13 -- 14 -- 15 -- 16 -- 17 -- 18\n", 213*edab6123Sjeremylt "# \n", 214*edab6123Sjeremylt "# We block elements into groups of 5:\n", 215*edab6123Sjeremylt "# ________________________________________________________________________________________\n", 216*edab6123Sjeremylt "# | block 0: | block 1: |\n", 217*edab6123Sjeremylt "# | e0 | e1 | e2 | e3 | e4 | e0 | e1 | e2 |\n", 218*edab6123Sjeremylt "# | | |\n", 219*edab6123Sjeremylt "# | x -- x | x -- x | x -- x | x -- x | x -- x | x -- x | x -- x | x -- x |\n", 220*edab6123Sjeremylt "# | 10 -- 11 | 11 12 | 12 13 | 13 14 | 14 15 | 15 16 | 16 17 | 17 18 |\n", 221*edab6123Sjeremylt "#\n", 222*edab6123Sjeremylt "# Intermediate logical representation:\n", 223*edab6123Sjeremylt "# ______________________________________________________________________________\n", 224*edab6123Sjeremylt "# | block 0: | block 1: |\n", 225*edab6123Sjeremylt "# | node0: node1: | node0: node1: |\n", 226*edab6123Sjeremylt "# | 10-11-12-13-14 11-12-13-14-15 | 15-16-17- *- * 16-17-18- *- * |\n", 227*edab6123Sjeremylt "# | e0 e1 e2 e3 e4 e0 e1 e2 e3 e4 | e0 e1 e2 e3 e4 e0 e1 e2 e3 e4 |\n", 228*edab6123Sjeremylt "#\n", 229*edab6123Sjeremylt "# Forward restriction output:\n", 230*edab6123Sjeremylt "# ______________________________________________________________________________\n", 231*edab6123Sjeremylt "# | block 0: | block 1: |\n", 232*edab6123Sjeremylt "# | node0: node1: | node0: node1: |\n", 233*edab6123Sjeremylt "# | 10-11-12-13-14 11-12-13-14-15 | 15-16-17-17-17 16-17-18-18-18 |\n", 234*edab6123Sjeremylt "# | e0 e1 e2 e3 e4 e0 e1 e2 e3 e4 | e0 e1 e2 e3 e4 e0 e1 e2 e3 e4 |\n", 235*edab6123Sjeremylt "\n", 236*edab6123Sjeremylt "ne = 8\n", 237*edab6123Sjeremylt "blksize = 5\n", 238*edab6123Sjeremylt "\n", 239*edab6123Sjeremylt "x = ceed.Vector(ne+1)\n", 240*edab6123Sjeremylt "a = np.arange(10, 10 + ne+1, dtype=\"float64\")\n", 241*edab6123Sjeremylt "x.set_array(a, cmode=libceed.USE_POINTER)\n", 242*edab6123Sjeremylt "\n", 243*edab6123Sjeremylt "ind = np.zeros(2*ne, dtype=\"int32\")\n", 244*edab6123Sjeremylt "for i in range(ne):\n", 245*edab6123Sjeremylt " ind[2*i+0] = i\n", 246*edab6123Sjeremylt " ind[2*i+1] = i+1\n", 247*edab6123Sjeremylt "\n", 248*edab6123Sjeremylt "r = ceed.BlockedElemRestriction(ne, 2, blksize, 1, 1, ne+1, ind,\n", 249*edab6123Sjeremylt " cmode=libceed.USE_POINTER)\n", 250*edab6123Sjeremylt "\n", 251*edab6123Sjeremylt "y = ceed.Vector(2*blksize*2)\n", 252*edab6123Sjeremylt "y.set_value(0)\n", 253*edab6123Sjeremylt "\n", 254*edab6123Sjeremylt "r.apply(x, y)\n", 255*edab6123Sjeremylt "\n", 256*edab6123Sjeremylt "with y.array_read() as y_array:\n", 257*edab6123Sjeremylt " print('y =', y_array)\n", 258*edab6123Sjeremylt "\n", 259*edab6123Sjeremylt "x.set_value(0)\n", 260*edab6123Sjeremylt "r.T.apply(y, x)\n", 261*edab6123Sjeremylt "\n", 262*edab6123Sjeremylt "with x.array_read() as x_array:\n", 263*edab6123Sjeremylt " print('x =', x_array)" 264*edab6123Sjeremylt ] 265*edab6123Sjeremylt }, 266*edab6123Sjeremylt { 267*edab6123Sjeremylt "cell_type": "markdown", 268*edab6123Sjeremylt "metadata": {}, 269*edab6123Sjeremylt "source": [ 270*edab6123Sjeremylt "* In the following example (intended for backend developers), we illustrate the creation and application of a blocked element restriction (from an L-vector to an E-vector) and its transpose (inverse operation, from an E-vector to an L-vector)" 271*edab6123Sjeremylt ] 272*edab6123Sjeremylt }, 273*edab6123Sjeremylt { 274*edab6123Sjeremylt "cell_type": "code", 275*edab6123Sjeremylt "execution_count": null, 276*edab6123Sjeremylt "metadata": {}, 277*edab6123Sjeremylt "outputs": [], 278*edab6123Sjeremylt "source": [ 279*edab6123Sjeremylt "# In this 1D example, the dofs are indexed as\n", 280*edab6123Sjeremylt "# \n", 281*edab6123Sjeremylt "# x -- x -- x -- x -- x -- x -- x -- x -- x\n", 282*edab6123Sjeremylt "# 10 -- 11 -- 12 -- 13 -- 14 -- 15 -- 16 -- 17 -- 18\n", 283*edab6123Sjeremylt "#\n", 284*edab6123Sjeremylt "# We block elements into groups of 5:\n", 285*edab6123Sjeremylt "# ________________________________________________________________________________________\n", 286*edab6123Sjeremylt "# | block 0: | block 1: |\n", 287*edab6123Sjeremylt "# | e0 | e1 | e2 | e3 | e4 | e0 | e1 | e2 |\n", 288*edab6123Sjeremylt "# | | |\n", 289*edab6123Sjeremylt "# | x -- x | x -- x | x -- x | x -- x | x -- x | x -- x | x -- x | x -- x |\n", 290*edab6123Sjeremylt "# | 10 -- 11 | 11 12 | 12 13 | 13 14 | 14 15 | 15 16 | 16 17 | 17 18 |\n", 291*edab6123Sjeremylt "#\n", 292*edab6123Sjeremylt "# Intermediate logical representation (extraction of block1 only in this case):\n", 293*edab6123Sjeremylt "# _______________________________________\n", 294*edab6123Sjeremylt "# | block 1: |\n", 295*edab6123Sjeremylt "# | node0: node1: |\n", 296*edab6123Sjeremylt "# | 15-16-17- *- * 16-17-18- *- * |\n", 297*edab6123Sjeremylt "# | e0 e1 e2 e3 e4 e0 e1 e2 e3 e4 |\n", 298*edab6123Sjeremylt "#\n", 299*edab6123Sjeremylt "# Forward restriction output:\n", 300*edab6123Sjeremylt "# _______________________________________\n", 301*edab6123Sjeremylt "# | block 1: |\n", 302*edab6123Sjeremylt "# | node0: node1: |\n", 303*edab6123Sjeremylt "# | 15-16-17-17-17 16-17-18-18-18 |\n", 304*edab6123Sjeremylt "# | e0 e1 e2 e3 e4 e0 e1 e2 e3 e4 |\n", 305*edab6123Sjeremylt "\n", 306*edab6123Sjeremylt "ne = 8\n", 307*edab6123Sjeremylt "blksize = 5\n", 308*edab6123Sjeremylt "\n", 309*edab6123Sjeremylt "x = ceed.Vector(ne+1)\n", 310*edab6123Sjeremylt "a = np.arange(10, 10 + ne+1, dtype=\"float64\")\n", 311*edab6123Sjeremylt "x.set_array(a, cmode=libceed.USE_POINTER)\n", 312*edab6123Sjeremylt "\n", 313*edab6123Sjeremylt "ind = np.zeros(2*ne, dtype=\"int32\")\n", 314*edab6123Sjeremylt "for i in range(ne):\n", 315*edab6123Sjeremylt " ind[2*i+0] = i\n", 316*edab6123Sjeremylt " ind[2*i+1] = i+1\n", 317*edab6123Sjeremylt "\n", 318*edab6123Sjeremylt "r = ceed.BlockedElemRestriction(ne, 2, blksize, 1, 1, ne+1, ind,\n", 319*edab6123Sjeremylt " cmode=libceed.USE_POINTER)\n", 320*edab6123Sjeremylt "\n", 321*edab6123Sjeremylt "y = ceed.Vector(blksize*2)\n", 322*edab6123Sjeremylt "y.set_value(0)\n", 323*edab6123Sjeremylt "\n", 324*edab6123Sjeremylt "r.apply_block(1, x, y)\n", 325*edab6123Sjeremylt "\n", 326*edab6123Sjeremylt "with y.array_read() as y_array:\n", 327*edab6123Sjeremylt " print('y =', y_array)\n", 328*edab6123Sjeremylt "\n", 329*edab6123Sjeremylt "x.set_value(0)\n", 330*edab6123Sjeremylt "r.T.apply_block(1, y, x)\n", 331*edab6123Sjeremylt "\n", 332*edab6123Sjeremylt "with x.array_read() as array:\n", 333*edab6123Sjeremylt " print('x =', x_array)" 334*edab6123Sjeremylt ] 335*edab6123Sjeremylt }, 336*edab6123Sjeremylt { 337*edab6123Sjeremylt "cell_type": "markdown", 338*edab6123Sjeremylt "metadata": {}, 339*edab6123Sjeremylt "source": [ 340*edab6123Sjeremylt "Note that the nodes at the boundary between elements have multiplicty 2, while the internal nodes and the outer boundary nodes, have multiplicity 1." 341*edab6123Sjeremylt ] 342*edab6123Sjeremylt } 343*edab6123Sjeremylt ], 344*edab6123Sjeremylt "metadata": { 345*edab6123Sjeremylt "kernelspec": { 346*edab6123Sjeremylt "display_name": "Python 3", 347*edab6123Sjeremylt "language": "python", 348*edab6123Sjeremylt "name": "python3" 349*edab6123Sjeremylt }, 350*edab6123Sjeremylt "language_info": { 351*edab6123Sjeremylt "codemirror_mode": { 352*edab6123Sjeremylt "name": "ipython", 353*edab6123Sjeremylt "version": 3 354*edab6123Sjeremylt }, 355*edab6123Sjeremylt "file_extension": ".py", 356*edab6123Sjeremylt "mimetype": "text/x-python", 357*edab6123Sjeremylt "name": "python", 358*edab6123Sjeremylt "nbconvert_exporter": "python", 359*edab6123Sjeremylt "pygments_lexer": "ipython3", 360*edab6123Sjeremylt "version": "3.8.5" 361*edab6123Sjeremylt } 362*edab6123Sjeremylt }, 363*edab6123Sjeremylt "nbformat": 4, 364*edab6123Sjeremylt "nbformat_minor": 4 365*edab6123Sjeremylt} 366