{ "metadata": { "kernelspec": { "display_name": "Python 3", "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.5.4" }, "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Einf\u00fchrung in Python (numpy) und DUNE\n", "\n", "In der Vorlesung verwenden wir Python(3) mit den [`numpy`](http://www.numpy.org)- und [`scipy`](https://www.scipy.org)-Modulen.\n", "Sp\u00e4ter verwenden wir auch [DUNE](https://www.dune-project.org)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python-Grundlagen\n", "\n", "### Zahlen, Zeichenketten, Tupel und Listen\n", "\n", "Grundlegende Datentypen sind (Ganz-)zahlen, Zeichenketten, Tupel und Listen.\n", "\n", "Tupel k\u00f6nnen sp\u00e4ter nicht mehr ver\u00e4ndert werden, Listen hingegen schon.\n", "Ansonsten verhalten sich beide gleich." ] }, { "cell_type": "code", "collapsed": true, "input": [ "ganzzahl = 3\n", "andere_zahl = ganzzahl + 4**2\n", "zahl = 3.2\n", "hallo = \"Hallo Welt!\"\n", "tupel = (1, 2, \"Hallo\")\n", "liste = [1, 2, \"Hallo\"]" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mit der `str.format`-Methode k\u00f6nnen Ausgaben formatiert werden.\n", "Die eigentlich Ausgabe erfolgt \u00fcber die `print`-Funktion." ] }, { "cell_type": "code", "collapsed": false, "input": [ "ausgabe = \"Die Zahl ist {}; die andere Zahl ist {}\".format(ganzzahl, andere_zahl)\n", "print(ausgabe)\n", "print(hallo, zahl)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ist der letzte Befehl in einem Block nur ein Ausdruck, wird dieser Wert ausgeben.\n", "Die Darstellung kann sich von der Ausgabe durch `print` unterscheiden (`print(repr(...))` gibt aber die gleiche Darstelleung)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "ausgabe" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Bedingte Anweisungen, Schleifen\n", "\n", "In Python werden Bl\u00f6cke nach Bedingungen und in Schleifen durch Einr\u00fcckung ausgezeichnet.\n", "Vergleiche mit `==`; Verbinden von Ausdr\u00fccken mit `and`, `or`, `not`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "if ganzzahl % 2 == 0 or False:\n", " print(\"ganzzahl ist gerade\")\n", "else:\n", " print(\"ganzzahl ist ungerade\")" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "for i in range(0, 3): # oder auch nur `range(3)`\n", " print(i)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "for i in range(0, 50, 10):\n", " print(i)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "for i in tupel:\n", " print(i)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Funktionen" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def plus1(x):\n", " return x + 1\n", "\n", "plus1(2)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sehr kurze Funktionen, die wie `plus1` nur aus einer `return`-Anweisung bestehen, lassen sich auch als `lambda`-Ausdruck schreiben:`" ] }, { "cell_type": "code", "collapsed": false, "input": [ "plus2 = lambda x: x + 2\n", "\n", "plus2(2)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "F\u00fcr noch nicht implementierte Funktionen oder bedingte Anweisungen, kann `pass` verwendet werden damit das Programm syntaktisch korrekt bleibt:" ] }, { "cell_type": "code", "collapsed": true, "input": [ "def toBeDoneLater():\n", " pass" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Module laden\n", "\n", "Mit der `import`-Anweisung k\u00f6nnen Module oder einzelne Objekte aus Modulen geladen werden.\n", "Module k\u00f6nnen auch unter einem anderen Namen geladen werden; es ist z.B. \u00fcblich das `numpy`-Modul unter dem Namen `np` zu laden." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy\n", "import numpy as np\n", "from numpy import array" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Dichte Matrizen und Vektoren" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Vektoren" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy as np\n", "\n", "v = np.array([1, 2, 3])\n", "w = np.array([4, 5, 6])\n", "print(v, w)\n", "print(v[0])\n", "print(len(v))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "print(v+w)\n", "print(2*v)\n", "print(2*v+w)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Vorsicht**: * ist nicht das Skalarprodukt, sondern elementweises Produkt:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(v*w)\n", "print(v.dot(w))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Matrizen" ] }, { "cell_type": "code", "collapsed": false, "input": [ "m = np.array([[1,2],[3,4]])\n", "print(m)\n", "print(m[1,0])\n", "print(m[1,:])\n", "print(m[:,0])" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "m = np.zeros((3,3))\n", "print(m)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "m = np.eye(3)\n", "print(m)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "m = np.ones((3,3))\n", "print(m)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Vorsicht**: * ist nicht Matrix-Vektor-Multiplikation!" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(m*v)\n", "print(m.dot(v))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Lineare Gleichungssysteme" ] }, { "cell_type": "code", "collapsed": false, "input": [ "A = np.array([[1, 1], [0, 1]])\n", "b = np.array([2, 1])\n", "x = np.linalg.solve(A, b)\n", "print(x)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "## D\u00fcnn besetzte Matrizen\n", "\n", "Die Gleichungssysteme, die durch Diskretisierung einer PDE entstehen, k\u00f6nnen sehr gro\u00df werden, allerdings ist ein Gro\u00dfteil der Eintr\u00e4ge \"0\".\n", "Diese m\u00f6chte man nicht speichern und bei Rechenoperationen ebenfalls nicht verwenden.\n", "Um dies zu erreichen werden spezielle Datenstrukturen f\u00fcr d\u00fcnn besetzte Matrizen verwendet.\n", "In den \u00dcbungen verwenden wir das [`scipy` Python-Modul](https://www.scipy.org/) und beschr\u00e4nken uns zun\u00e4chst auf die beiden Klassen `lil_matrix` und `csr_matrix`.\n", "\n", "Die Klasse `lil_matrix` wird f\u00fcr das Aufstellen der Matrix verwendet; f\u00fcr die weiteren Rechnungen wird zu einer `csr_matrix` konvertiert und damit gerechnet.\n", "\n", "Hier kann man auch den Unterschied zwischen der Ausgabe von `print(m)` und nur `m` sehen." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from scipy.sparse import lil_matrix\n", "\n", "m = lil_matrix((10, 10))\n", "m[0, :] = np.array([1,2,3,4,5,6,7,8,9,10])\n", "for i in range(1, 10):\n", " m[i, i] = 1\n", "print(m)\n", "m" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "print(m.todense())" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "A = m.tocsr()\n", "A" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "import scipy.sparse.linalg\n", "\n", "b = np.ones(10)\n", "x = scipy.sparse.linalg.spsolve(A, b)\n", "x" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Matrizen visualisieren\n", "\n", "Es ist manchmal hilfreich Matrizen als Bild darzustellen:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "Adense = np.array(abs(A).todense())\n", "plt.figure(figsize=(10,10))\n", "plt.pcolormesh(Adense, cmap=plt.cm.gray_r)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "plt.matshow(np.eye(1024), cmap=plt.cm.gray_r)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "heading", "level": 2, "metadata": { "collapsed": true }, "source": [ "Punktgitter mit numpy" ] }, { "cell_type": "code", "collapsed": false, "input": [ "nx, ny = (5, 5)\n", "x = np.linspace(0, 1, nx)\n", "y = np.linspace(0, 1, ny)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "for i in range(nx):\n", " for j in range(ny):\n", " print(\"Point [{}, {}] is at {}\".format(i, j, (x[i], y[j])))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "m = np.zeros((nx, ny))\n", "for i in range(nx):\n", " for j in range(ny):\n", " p = x[i], y[j]\n", " m[i, j] = np.sin(p[0]) + p[1]" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "plt.pcolormesh(y, x, m)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "## DUNE\n", "\n", "DUNE, das [Distributed and Unified Numerics Environment](https://www.dune-project.org), ist ein C++-Framework f\u00fcr die Diskretisierung und L\u00f6sung von PDEs.\n", "F\u00fcr die \u00dcbungen werden wir die Python-Anbindung f\u00fcr Gitter und Funktionenr\u00e4ume verwenden.\n", "\n", "Werden bestimmte Datentypen das erste Mal verwendet, wird im Hintergrund der Python-Anbindung eine C++-Datei erzeugt und \u00fcbersetzt.\n", "Dies kann eine ganze Weile dauern..." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import dune.grid" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Gitter erzeugen\n", "\n", "Erzeuge ein strukturiertes 5x5-Gitter f\u00fcr das Einheitsquadrat:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "domain = dune.grid.cartesianDomain([0, 0], [1, 1], [5, 5])\n", "grid = dune.grid.yaspGrid(domain, dimgrid=2)\n", "print(grid)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "for e in grid.elements():\n", " print(e.geometry.center)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "F\u00fcr unstrukturierte Gitter verwenden wir `UGGrid` mit dem `gmsh`-Dateiformat:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "reader = (dune.grid.reader.gmsh, \"ldomain.msh\")\n", "grid = dune.grid.ugGrid(reader, dimgrid=2)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Beim Ausprobieren ist es f\u00fcr die automatische Vervollst\u00e4ndigung praktisch, ein konkretes Element zu haben:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "firstElement = next(iter(grid.elements()))\n", "print(firstElement.geometry.center)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null } ], "metadata": {} } ] }