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