Praktikum zu Vorlesung Modellreduktion parametrisierter Systeme
Mario Ohlberger, Felix Schindler
Aktivieren Sie die virtuelle Umgebung zum Praktikum und starten Sie den Notebook server. Zur Erinnerung:
Terminal starten (super
-Taste/Windows
-Taste, terminal
eingeben, Enter
)
ins Projektverzeichnis wechseln
cd ~/vorlesung_modellreduktion
die virtuelle Umgebung aktivieren
source python_umgebung_praktikum_modellreduktion/bin/activate
Notebook server starten
jupyter-notebook --notebook-dir=notebooks
grid_interpolations
in grid_visualization
um.Erstellen Sie ein neues Python 3
notebook und benennen Sie es in interpolations
um.
Importieren Sie numpy
und pymor.basic
und machen Sie matplotlib
für das Notebook nutzbar.
Schreiben Sie eine Python Funktion visualize_fv(v_h, grid, title)
, die für eine diskrete Funktion $v_h = $ v_h
(gegeben als VectorArray
der Länge 1), Gitter $\mathcal{T}_h = $ grid
und Titel title
, die Funktion $v_h \in V_h^0$ visualisiert, wobei wie in [Blatt 00]
$$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 (Finite Volumen Raum) 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$).
PatchVisualizer
anzulegen und dessen visualize
Methode zu nuzten.v_h
die richtige Länge und Dimension hat.Schreiben Sie eine Python Funktion visualize_grid(grid)
, die ein gegebenes Gitter $\mathcal{T}_h = $ grid
visualisiert.
grid
zu erhalten, einen entsprechenden fv_space
als NumpyVectorSpace
anzulegen, die Funktion $v_h$ als Element von $V_h^0$ mit Hilfe von fv_space
zu erhalten.visualize_fv
Funktion.Testen Sie Ihre Funktionen, indem Sie ein Dreicksgitter $\mathcal{T}_h$ mit $1^2$ Intervallen des Gebiets $\Omega = [0, 1]^2$ visualisieren.
visualize_grid
Funktion auf.Zur Visualisierung einer Funktion $f: \Omega \to \mathbb{R}$ auf einem gegebenen Gitter $\mathcal{T}_h$ von $\Omega \subset \mathbb{R}^d$, $d = 1, 2, 3$, benötigen wir eine geeignete Approximation $f_h$. Für stetige Funktionen $f \in C^0$ bietet sich dazu die Lagrange-Interpolation an. Sei dazu
$$S_h^1 := \big\{ v \in C^0(\Omega) \;\big|\; v|_K \in \mathbb{P}_1(K)\quad\forall K \in \mathcal{T}_h\big\} \subset C^0(\Omega)$$der Raum der stetigen und stückweisen linearen Funktionen bezüglich des Gitters.
Sei $\mathcal{T}_h^d$ die Menge aller Knotenpunkte des Gitters (Entitäten mit Kodimension $d$) und $I := |\mathcal{T}_h^d| \in \mathbb{N}$ die Anzahl der Knotenpunkte. Dann ist eine Basis von $S_h^1$ gegeben durch
$$\big\{ \varphi_0, \dots, \varphi_{I - 1} \big\}$$wobei die Hütchenfunktion $\varphi_i$ zu einem Knotenpunkt $\nu_i \in \mathcal{T}_h^d$ eindeutig definiert ist durch
$$\varphi_i(\nu_j) := \delta_{i, j} := \begin{cases}1, & \text{falls }i = j,\\0, &\text{sonst}\end{cases}$$(diese Basis wird Lagrange-Basis genannt).
Damit ist jede Funktion $v_h \in S_h^1$ eindeutig definiert durch die Angabe ihrer Werte in den Knotenpunkten des Gitters, denn aus der Basisdarstellung
$$v_h(x) = \sum_{i = 0}^{I - 1} \underline{v_h}_i \varphi_i(x)$$und der Definition der Basis folgt, dass $\underline{v_h}_i = v_h(\nu_i)$.
Wir können also $S_h^1$ isomorph mit $\mathbb{R}^I$ identifizieren und jede Funktion $v_h \in S_h^1$ mit ihrem DoF Vektor (Degree of Freedom: Freiheitsgrad) $\underline{v_h} \in \mathbb{R}^I$, wobei $\underline{v_h}_i := v_h(\nu_i)$ für alle $0 \leq i_ < I$.
Um für eine beliebige Funktion $f: \Omega \to \mathbb{R}$ eine Approximation in $S_h^1$ zu erhalten, betrachten wir die Lagrange-Interpolation
$$\Pi_{S_h^1}: C^0(\Omega) \rightarrow S_h^1,\quad\quad f \mapsto \Pi_{S_h^1}[f],$$die eindeutig definiert ist durch die Angabe ihrer Werte in den Knotenpunkten,
$$\Pi_{S_h^1}[f](\nu_i) := f(\nu_i) \text{ für } 0 \leq i < I.$$Als Approximation von $f$ erhalten wir also $f_h \in S_h^1$ als $f_h := \Pi_{S_h^1}[f]$ und den dazugehörigen DoF Vektor $\underline{f_h} \in \mathbb{R}^I$ durch
$$\underline{f_h}_i := f(\nu_i), \text{ für alle } 0 \leq 1 < I.$$Bemerkung: Die Lagrange-Interpolation ist eine Projektion, denn $(\Pi_{S_h^1} \circ \Pi_{S_h^1})[v_h] = \Pi_{S_h^1}[v_h]$ für alle $v_h \in S_h^1$.
Schreiben Sie eine Python Funktion interpolate_lagrange_p1(f, grid)
, die für eine gegebene Funktion $f = $ f
und Gitter $\mathcal{T}_h = $ grid
die Lagrange-Interpolierte $f_h := \Pi_{S_h^1}[f]$ als geeignetes VectorArray
zurück gibt.
NumpyVectorSpace
entsprechender Dimension, mit der Kennung CG
(continuous Galerkin) und legen Sie ein entsprechendes Objekt cg_space
an.f
an allen Knotenpunkten des Gitters aus, um $\underline{f_h}$ zu erhalten.cg_space
nutzen.Testen Sie Ihre interpolate_lagrange_p1
Funktion, indem Sie die wie in [Blatt 00, Aufgabe 1] gegebene Funktion $f: \Omega \to \mathbb{R}$, $f(x_0, x_1) := x_0 \cdot x_1$ auf $\Omega = [0, 1]^2$ interpolieren.
ExpressionFunktion
.interpolate_lagrange_p1
mit dieser Funktion und dem Gitter aus Aufgabe 1 auf und geben Sie die Länge und Dimension des resultierenden VectorArray
s, sowie die Anzahl der Knotenpunkte des Gitters aus.Schreiben Sie eine Funktion visualize_lagrange_p1(v_h, grid, title)
, die für eine diskrete Funtion $v_h = $ v_h
(gegeben als VectorArray
der Länge 1), Gitter $\mathcal{T}_h = $ grid
und Titel title
, die Funktion $v_h \in S_h^1$ visualisiert.
v_h
die richtige Länge und Dimension hat.cg_visualizer
vom Typ PatchVisualizer, achten Sie auf die korrekte Kodimension!visualize
Methode, geben Sie mit legend=
einen Titel an, setzen Sie bei Bedarf d=None
.Testen Sie Ihre visualize_lagrange_p1
Funktion, indem Sie die Funktion $f$ für verschiede Gitter interpolieren und visualisieren, messen Sie dabei jeweils die Zeit für
Testen Sie mindestens folgende Gitter:
Für allgemeine (unstetige Funktionen) $f: \Omega \to \mathbb{R}$ bietet sich außerdem die Approximation (und Visualisierung) als Finite Volumen Funktion an, die wir schon zur Visualisierung des Gitters genutzt haben. Sei $\mathcal{T}_h$ ein Gitter mit $I := |\mathcal{T}_h| \in \mathbb{N}$ Elementen (Entitäten der Kodimension 0). Eine Basis des Finite Volumen Raumes $V_h^0$ ist durch
$$\big\{ \chi_{K_0}, \dots, \chi_{K_{I - 1}} \big\}$$gegeben, wobei
$$\chi_{K_i} := \begin{cases}1, &\text{für } x \in K_i\\0, &\text{sonst}\end{cases}$$die Indikatorfunktion bezüglich des Gitterelementes $K_i \in \mathcal{T}_h$ sei, für $0 \leq i < I$. Da jede Funktion $v_h \in V_h^0$ stückweise konstant bezüglich des Gitters $\mathcal{T}_h$ ist (vergleiche die Definition von $V_h^0$ oben), ist Sie eindeutig durch die Angabe eines Wertes $\underline{v_h}_i \in \mathbb{R}$ auf jedem Gitterelement $K_i \in \mathcal{T}_h$ gegeben, was aus der Basisdarstellung
$$v_h(x) := \sum_{i = 0}^{I - 1} \underline{v_h}_i \chi_{K_i}(x)$$und der Definition der Basis und $V_h^0$ folgt.
Um für eine beliebige Funktion $f \in L^2(\Omega)$ eine Approximation in $V_h^0$ zu erhalten, betrachten wir die Finite Volumen-Iterpolation
$$\Pi_{V_h^0}: L^2(\Omega) \rightarrow V_h^0,\quad\quad f \mapsto \Pi_{V_h^0}[f],$$die eindeutig definiert ist durch die Angabe ihrer Werte auf den Gitterelementen als Mittelwert der Funktion $f$,
$$\Pi_{V_h^0}[f]\Big|_{K_i} := |K_i|^{-1} \int_{K_i} f(x) \,\text{d}x \text{ für } 0 \leq i < I.$$Als Approximation von $f$ erhalten wir also $f_h \in V_h^0$ als $f_h := \Pi_{V_h^0}[f]$ und den dazugehörigen DoF Vektor $\underline{f_h} \in \mathbb{R}^I$ durch
$$\underline{f_h}_i := |K_i|^{-1} \int_{K_i} f(x) \,\text{d}x \text{ für } 0 \leq i < I.$$Bemerkung: Die Finite Volumen-Interpolation ist eine Projektion (genauer gesagt eine $L^2$-Projektion), denn $(\Pi_{V_h^0} \circ \Pi_{V_h^0})[v_h] = \Pi_{V_h^0}[v_h]$ für alle $v_h \in V_h^0$.
Schreiben Sie eine Python Funktion interpolate_fv(f, grid)
, die für eine gegebene Funktion $f = $ f
und Gitter $\mathcal{T}_h = $ grid
die Finite Volumen-Interpolierte $f_h := \Pi_{V_h^0}[f]$ als geeignetes VectorArray
zurück gibt.
NumpyVectorSpace
entsprechender Dimension, mit der Kennung FV
und legen Sie ein entsprechendes Objekt fv_space
an.fv_space
nutzen.interpolate_fv
Funktion, indem Sie die Funktionauf $\Omega = [0, 1]^2$ interpolieren.
ExpressionFunktion
.interpolate_fv
mit dieser Funktion und dem groben Dreiecksgitter auf und geben Sie die Länge und Dimension des resultierenden VectorArray
s, sowie die Anzahl der Elements des Gitters aus.Testen Sie Ihre interpolate_fv
und visualize_fv
Funktion von oben, indem Sie die Funktion $f$ für verschiede Gitter interpolieren und visualisieren, testen Sie mindestens folgende Gitter: