Praktikum zu Vorlesung Modellreduktion parametrisierter Systeme
Mario Ohlberger, Felix Schindler
Dazu müssen auf Ihrem Rechner die Befehle python3
und virtualenv
verfügbar sein. Das können Sie überprüfen, indem Sie ein Terminal starten (unter Ubuntu: Super/Windows Taste, terminal eingeben, Return) und die folgenden Befehle eingeben:
python3 --version
virtualenv --version
Beide Befehle sollten Ihnen die jeweilige Version des Programms anzeigen (und keine Fehlermeldung). Zur Einrichtung gehen Sie folgendermaßen vor:
HOME
Verzeichnis wechseln und einen Projekt-Ordner anlegencd # ins HOME Verzeichnis wechseln
pwd # Ort des aktuellen Verzeichnises anzeigen
ls -lh # Inhalt des aktuellen Verzeichnisses anzeigen
mkdir vorlesung_modellreduktion # ein neues Verzeichnis erstellen
cd vorlesung_modellreduktion # in dieses Verzeichnis wechseln
pwd
ls -lh
virtualenv --python=python3 python_umgebung_praktikum_modellreduktion
ls -lh
source python_umgebung_praktikum_modellreduktion/bin/activate
pip install --upgrade pip
pip install pymor[full]
pip install notebook
du -sh python_umgebung_praktikum_modellreduktion
Dabei installiert pip install pymor[full]
das neueste Release von pyMOR
(momentan 0.5.2
). Mehr dazu finden Sie auf https://pymor.org (gehen Sie dort auf View on Github
und wählen anstelle von branch: master
links oben Tags: 0.5.2
aus, um die entsprechende README.md anzuzeigen).
mkdir notebooks
cd ~/vorlesung_modellreduktion
source python_umgebung_praktikum_modellreduktion/bin/activate
jupyter-notebook --notebook-dir=notebooks
Aktivieren Sie die virtuelle Umgebung zum Praktikum und starten Sie den Notebook server (falls noch nicht geschehen)
Erstellen Sie ein neues Python 3
notebook und benennen Sie es in grid_interpolations
um.
Geben Sie folgende Befehle in die erste Zelle ein und führen Sie sie aus (mit STRG
+ Return
):
%matplotlib notebook
import numpy as np
from pymor.basic import *
Ab jetzt ist die numpy Bibliothek unter np
verfügbar und alles aus pymor.basic
direkt verfügbar.
%matplotlib notebook
import numpy as np
from pymor.basic import *
omega
an. Nutzen Sie dazu auch die Möglichkeit des jupyter Notebooks, sich zu einem beliebigen Objekt mit Hilfe des ?
-postfix die Dokumentation anzeigen zu lassen (z.B. np.array?
).# => API Dokumentation http://docs.pymor.org/en/0.5.1/index.html#api-documentation
# => Modul "domaindescriptions": http://docs.pymor.org/en/0.5.1/generated/pymor.domaindescriptions.html
# => Klasse RectDomain, diese ist Dank des * imports direkt verfügbar
# => Hilfe zu RectDomain anzeigen lassen: RectDomain?
omega = RectDomain(([0, 0], [1, 1]))
Suchen Sie nach einer Möglichkeit ein konformes Dreiecksgitter $\mathcal{T}_h$ als Partitionierung des Gebiets $\Omega$ mit 16 Dreiecken zu erstellen, und geben Sie folgende Informationen aus:
d
des Gittersd
Entitäten, Punkte) im Gitterfor
-SchleifeVergleichen Sie die Positionen der Knoten mit der Dokumentation.
# => API Dokumentation, Modul grid, Klasse TriaGrid
# => Hilfe anzeigen lassen: TriaGrid?
grid = TriaGrid(num_intervals=(2, 2), domain=omega.domain)
print(grid)
print()
print('grid lives in a {}-dimensional space'.format(grid.dim))
print('grid has {} simplices'.format(grid.size(0)))
print('grid has {} edges'.format(grid.size(1)))
print('grid has {} vertices'.format(grid.size(2)))
vertices = grid.centers(grid.dim)
print()
print(type(vertices))
print(vertices.shape)
print()
print('vertices:')
counter = 0
for vertex in vertices:
print('vertex {} has position {}'.format(counter, vertex))
counter += 1
Visualisieren Sie "das Gitter", indem Sie die Funktion
$$v_h \in V_h^0,\quad\quad v_h|_K := \text{index of } K \text{ in the grid},\quad\forall K \in \mathcal{T}_h$$
visualisieren, wobei
$$V_h^0 := \big\{ v \in L^2(\Omega) \;\big|\; v|_K \in \mathbb{P}_0(K)\quad\forall K \in \mathcal{T}_h\big\}$$
den Raum der stückweise konstanten Funktionen bzgl. des Gitters bezeichnet ($\mathbb{P}_p(\omega)$ ist dabei der Raum der Polynome vom Grad kleiner gleich $p \in \mathbb{N}$ über einem Gebiet $\omega \subset \mathbb{R}^d$). Der Raum $V_h^0$ spielt insbesondere bei Finite Volumen Verfahren eine Rolle.
NumpyVectorSpace
und legen Sie ein entsprechendes Objekt fv_space
an.fv_space.from_data
.fv_visualizer
vom Typ PatchVisualizer, achten Sie auf die korrekte Kodimension! Importieren Sie dazu das nötige Modul (nicht Teil von pymor.basic
, also noch nicht verfügbar).visualize
Methode, geben Sie mit legend=
einen Titel an, setzen Sie bei Bedarf d=None
.fv_space = NumpyVectorSpace(dim=grid.size(0), id_='FV')
print(fv_space)
v_h = np.arange(15)
print()
print(v_h)
v_h = fv_space.from_data(np.arange(fv_space.dim))
print()
print(type(v_h))
print(v_h)
print(len(v_h))
print(v_h.dim)
# => v_h ist ein NumpyVectorArray (http://docs.pymor.org/en/0.5.1/generated/pymor.vectorarrays.html#module-pymor.vectorarrays.numpy),
# also insbesondere vom Typ VectorArrayInterface (http://docs.pymor.org/en/0.5.1/generated/pymor.vectorarrays.html#pymor.vectorarrays.interfaces.VectorArrayInterface)
# siehe auch http://docs.pymor.org/en/0.5.1/technical_overview.html#three-central-classes
from pymor.gui.visualizers import PatchVisualizer
fv_visualizer = PatchVisualizer(grid, bounding_box=grid.bounding_box, codim=0)
fv_visualizer.visualize(v_h, d=None, legend='element indices of a TriaGrid with {} elements'.format(grid.size(0)))
Sei $f: \Omega \to \mathbb{R}$ gegeben durch $f(x_0, x_1) := x_0 \cdot x_1$.
f
, die die Auswertung von $f$ and einem Punkt $x$ modelliert und werten Sie die Funktion f
für jeden Knotenpunkt des Gitters einzeln mit Hilfe einer for
-Schleife aus.def f(x):
return x[0]*x[1]
for x in vertices:
print('f({}) = {}'.format(x, f(x)))
f
an jedem Knotenpunkt des feineren Gitters auszuwerten.fine_grid = TriaGrid(num_intervals=(1024, 1024), domain=omega.domain)
print(fine_grid)
import time
tic = time.time()
values = f(fine_grid.centers(grid.dim))
toc = time.time() - tic
print()
print('evaluating non-vectorized function took {}s'.format(toc))
f
an allen Knotenpunkten des groben Gitters gleichzeitig auszuwerten. Warum funktioniert das nicht?# => an allen Punkten gleichzeitig auswerten
values = f(vertices)
print(values)
print(len(vertices))
print(len(values))
# Warum kommt das raus?
# Beim Aufruf f(vertices) passiert
vertices[0]*vertices[1]
# also eine elementweise Multiplikation des 0ten und 1ten Knotens
f
, welche die elementweisen Operationen des numpy.ndarray
ausnutzt.# Gegeben eine Menge von Punkten als Matrix
print(vertices)
print(vertices.shape)
# extrahiere 0te und 1te Komponente für alle Punkte gleichzeitig
x_0s = vertices[..., 0] # 0te Spalte
x_1s = vertices[..., 1] # 1te Spalte
print()
print(type(x_0s))
print(x_0s)
print(x_1s)
# Das ganze kompakt in einer Funktion
def f(x):
return x[..., 0]*x[..., 1]
# Kann an einem Punkt ausgewertet werden ...
print(f(vertices[0]))
# ... oder an allen Punkten gleichzeitig
print(f(vertices))
tic = time.time()
values = f(fine_grid.centers(grid.dim))
toc = time.time() - tic
print('took {}s'.format(toc))
ExpressionFunction
, um $f$ zu modellieren, werten Sie diese an allen Knotenpunkten des feinen Gitters aus und messen Sie die benötigte Zeit.f = ExpressionFunction('x[..., 0]*x[..., 1]', dim_domain=2, shape_range=())
tic = time.time()
values = f.evaluate(fine_grid.centers(grid.dim))
toc = time.time() - tic
print('took {}s'.format(toc))