Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Lösen ein stationäres Wärmeleitproblem in der Ebene mittels FEM. Dabei bedeutet “stationär”, dass wir nicht die zeitliche Entwicklung simulieren, sondern den nach hinreichend langer Wartezeit vom betrachteten physikalischen System eingenommenen Zustand. Sind Wärmezufluss und -abfluss in einem Körper über einen langen Zeitraum konstant, so wird sich eine stabile Temperaturverteilung im Körper einstellen. Dieser stabile Zustand soll simuliert werden.

12.1Modell

Sei BR2B\subseteq\bbR^2 die Querschnittsfläche eines Kühlkörpers (z.B. einer CPU). Am unteren Rand

Γ2:={(x,0):  x[1,1]}\Gamma_2:=\{(x,0):\;x\in[-1,1]\}

erfolgt ein zeitlich konstanter Wärmeeintrag

g2(x,0):=100(1x2).g_2(x,0):=100\,(1-x^2).

Am restlichen Rand Γ1\Gamma_1 liegt die Umgebungstemperatur stets bei

g1(x,y)=20g_1(x,y)=20

(Luftstrom).

import matplotlib.pyplot as plt
import numpy as np

# Liste von Eckpunkten zur Beschreibung des polygonalen Gebiets
outline = [[-1, 0]]
for x in np.linspace(-1 + 0.1, 1 + 0.1, 5, endpoint=False):
    outline.extend([[x, 0.3], [x, 1], [x + 0.2, 1], [x + 0.2, 0.3]])
outline.append([1, 0])

# Randbedingungen
g1 = lambda x, y: 20
g2 = lambda x, y: 100 * (1 - x ** 2)

# Plot der Gebiets
fig, ax = plt.subplots(figsize=(10, 5))
x, y = zip(*(outline + [outline[0]]))
ax.plot(x, y, '-k')
ax.axis('equal')
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
<Figure size 1000x500 with 1 Axes>

Im Inneren des Kühlkörpers gilt

Δu=0\Delta u=0

für die Temperatur u:BRu:B\to\bbR.

12.2Schwache Formulierung

Die schwache Formulierung erhalten wir als Spezialfall der schwachen Formulierung der Poisson-Gleichung:

Finde u0Vu_0\in V, sodass

Bu0vdb=Γ2g2vdsBu1vdb\int_B \nabla u_0\circ\nabla v\diff b=\int_{\Gamma_2}g_2\,v\diff s-\int_B \nabla u_1\circ\nabla v\diff b

für alle vVv\in V gilt. Dabei ist

V:={vH1(B):  v(x)=0 fu¨xΓ1}V:=\{v\in H^1(B):\;v(x)=0\text{ für }x\in\Gamma_1\}

und u1H1(B)u_1\in H^1(B) ist eine Funktion, die auf Γ1\Gamma_1 gerade g1g_1 entspricht. Die gesuchte Lösung ist dann

u:=u0+u1.u:=u_0+u_1.

12.3Gebietszerlegung

Für die Zerlegung des Gebiets BB in Dreieckselemente nutzen wir das Python-Modul pygmsh.

import pygmsh

# Zerlegung in Dreieckselemente
with pygmsh.geo.Geometry() as geom:
    geom.add_polygon(outline, mesh_size=0.05)
    mesh = geom.generate_mesh()

# Knotenkoordinaten als NumPy-Array
#   axis 0: globale Knotennummer (0, 1,...)
#   axis 1: Koordinate (0 (x), 1 (y))
nodes = mesh.points[:, :2]

# globale Knotennummern der Randkanten als NumPy-Array
#   axis 0: Randkantennummer (0, 1,...)
#   axis 1: lokale Knotennummer (0, 1)
boundary_lines = mesh.cells[0].data

# globale Knotennummern der Dreieckselemente als NumPy-Array
# (Elementzusammenhangstabelle)
#   axis 0: Elementnummer (0, 1,...)
#   axis 1: lokale Knotennummer (0, 1, 2)
triangles = mesh.cells[1].data

del mesh  # nicht mehr benötigt

Zur späteren Verwendung trennen wir die von pygmsh generierten Knoten nach inneren Knoten, Knoten auf dem Dirichlet-Rand und Knoten auf dem Neumann-Rand.

# Knoten nach Lage auswählen (Rand, innen)
b_nodes = set.union(*[{int(n1), int(n2)} for n1, n2 in boundary_lines])
i_nodes = list(set(range(0, nodes.shape[0])) - b_nodes)

# Randknoten in Dirichlet und Neumann trennen
d_nodes = []
n_nodes = []
for n in b_nodes:
    if -1 < nodes[n, 0] < 1 and nodes[n, 1] == 0:
        n_nodes.append(n)
    else:
        d_nodes.append(n)

del b_nodes, boundary_lines  # nicht mehr benötigt

Die Gebietszerlegung sollte immer visuell geprüft werden. Insbesondere sollten die Dreiecke möglichst nah an der Form eines gleichseitigen Dreiecks sein.

# Plot der Gebietszerlegung
fig, ax = plt.subplots(figsize=(10, 5))

# Dreiecke
for n1, n2, n3 in triangles:
    n1231 = [n1, n2, n3, n1]
    ax.plot(nodes[n1231, 0], nodes[n1231, 1], '-k', lw=1)

# Knoten
ax.plot(nodes[i_nodes, 0], nodes[i_nodes, 1], 'og', label='innen')
ax.plot(nodes[d_nodes, 0], nodes[d_nodes, 1], 'or', label='Dirichlet')
ax.plot(nodes[n_nodes, 0], nodes[n_nodes, 1], 'ob', label='Neumann')

# Knotennummern
#for n, (x, y) in enumerate(nodes):
#    ax.text(x + 0.02, y + 0.02, str(n))

ax.axis('equal')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend()

plt.show()
<Figure size 1000x500 with 1 Axes>

Für den Aufbau der Systemmatrix weiter unten sind die Nachbarschaftsbeziehungen zwischen Knoten sowie zwischen Knoten und Dreieckselementen von Bedeutung.

# alle Knoten außer Dirichlet-Rand
ni_nodes = n_nodes + i_nodes

# Dreiecke für jeden Knoten
#   Listenindex ist globale Knotennummer
#   Listeneinträge sind Mengen von Elementnummern
tris_of_nodes = [set() for _ in nodes]
for tri, (n1, n2, n3) in enumerate(triangles):
    tris_of_nodes[n1].add(tri)
    tris_of_nodes[n2].add(tri)
    tris_of_nodes[n3].add(tri)

# benachbarte Knoten (kleine Knotennummer zuerst)
neighbors = set()
for node, tris_of_node in enumerate(tris_of_nodes):
    for tri in tris_of_node:
        for n in set(triangles[tri, :]) - {node}:
            neighbors.add((node, n) if node < n else (n, node))

12.4Systemmatrix und rechte Seite

Für die numerische Berechnung der in der schwachen Formulierung auftretenden Bereichsintegrale verwenden wir stückweise lineare Funktionen auf der Dreieckszerlegung. Für jeden Knoten wird also eine Basisfunktionen vk:BRv_k:B\to\bbR eingeführt, die am entsprechenden Knoten den Wert 1 annimmt und an allen anderen Knoten den Wert 0 hat.

12.4.1Dirichlet-Randbedingungen

Im kontinuierlichen Modell wird die Lösung uu zerlegt in die Summe u=u0+u1u=u_0+u_1, wobei u0u_0 auf dem Dirichlet-Rand Γ1\Gamma_1 Null ist und u1u_1 auf dem Dirichlet-Rand die Randbedingung erfüllt. Die Funktion u1u_1 ist abseits von Γ1\Gamma_1 frei wählbar. Sei u1u_1 also Null im Inneren des Gebiets und auf dem Neumann-Rand.

Im diskretisierten Zustand hat u0u_0 nur Nicht-Null-Koeffizienten for Basisfunktionen vkv_k, die zu einem inneren Knoten oder zu einem Knoten auf dem Neumann-Rand gehören. Die Systemmatrix wird als weniger Zeilen bzw. Spalten haben als es Knoten (Basisfunktionen) gibt. Umgekehrt genügen für die diskretisierte Darstellung der Funktion u1u_1 die Basisfunktionen die zu einem Knoten auf dem Dirichlet-Rand gehören.

# Abbildung der Knotennummern (ohne Dirichlet-Rand) auf Matrixzeilen/-spalten
node2idx = {n: idx for idx, n in enumerate(ni_nodes)}

Die Systemmatrix wird dünn besetzt sein, sodass wir die Einträge zunächst in Listen sammeln und dann später daraus mit SciPy eine dünn besetzte Matrix generieren.

# leere (dünn besetzte) Matrix, rechte Seite zunächst überall 0
Adata = []
Acols = []
Arows = []
b = np.zeros(len(ni_nodes), dtype=float)

12.4.2Gradient der Basisfunktionen

Sei PkP_k der Knoten zur globale Knotennummer kk. Der Gradient der zugehörigen Basisfunktion vkv_k ist Null auf allen Dreieckselemente, die nicht an den Knoten PkP_k grenzen. Auf an den Knoten PkP_k angrenzenden Dreiecken ist der Gradient konstant.

Die Berechnung des Gradients von vkv_k auf einem Dreieck mit Eckknoten Pk,Pl,PmP_k,P_l,P_m kann leicht durch Transformation des Dreiecks auf das Referenzdreieck mit den Eckpunkten (0,0)(0,0), (1,0)(1,0), (0,1)(0,1) erfolgen:

Die Transformation der Ecken des Referenzdreiecks auf die Eckknoten Pk,Pl,PmP_k,P_l,P_m ist durch

Φ(ξ,η):=Pk+ξ1(PlPk)+ξ2(PmPk)\Phi(\xi,\eta):=P_k+\xi_1\,(P_l-P_k)+\xi_2\,(P_m-P_k)

gegeben. Die zum betrachteten Dreieck und zur Basisfunktion vkv_k passende Formfunktion ist φ1\varphi_1 (vgl. Section 11.4.3). Mit ihr gilt

(vkΦ)(ξ,η)=φ1(ξ,η).(v_k\circ\Phi)(\xi,\eta)=\varphi_1(\xi,\eta).

Andererseits liefert die Kettenregel

(vkΦ)(ξ,η)=JΦ(ξ,η)T(vk)(Φ(ξ,η))\nabla(v_k\circ\Phi)(\xi,\eta)=J_\Phi(\xi,\eta)^\rmT\,(\nabla v_k)(\Phi(\xi,\eta))

(IDVID 1210), wobei

JΦ(ξ,η)=[[PlPk]1[PmPk]1[PlPk]2[PmPk]2]J_\Phi(\xi,\eta)={\begin{bmatrix} [P_l-P_k]_1& [P_m-P_k]_1\\ [P_l-P_k]_2& [P_m-P_k]_2\end{bmatrix}}

die Jacobi-Matrix zu Φ\Phi ist. Somit

(vk)(Φ(ξ,η))=JΦ(ξ,η)T(vkΦ)(ξ,η)=JΦ(ξ,η)Tφ1(ξ,η).{\begin{align} (\nabla v_k)(\Phi(\xi,\eta)) &=J_\Phi(\xi,\eta)^{-\rmT}\,\nabla(v_k\circ\Phi)(\xi,\eta)\\ &=J_\Phi(\xi,\eta)^{-\rmT}\,\nabla\varphi_1(\xi,\eta). \end{align}}

Analog folgt

(vl)(Φ(ξ,η))=JΦ(ξ,η)Tφ2(ξ,η).(\nabla v_l)(\Phi(\xi,\eta))=J_\Phi(\xi,\eta)^{-\rmT}\,\nabla\varphi_2(\xi,\eta).

12.4.3Bereichsintegrale

Für die Berechnung der Einträge der Systemmatrix und der rechten Seite benötigen wir die Bereichsintegrale

B(vk)Tvldb\int_B(\nabla v_k)^\rmT\,\nabla v_l\diff b

für alle Paare von Basisfunktionen und auch für k=lk=l.

Sind entsprechenden Knoten PkP_k und PlP_l nicht benachbart, so ist das Integral Null. Bei benachbarten Knoten ist der Integrand nur auf den beiden Dreiecken von Null verschieden, die sowohl PkP_k als auch PlP_l als Eckknoten haben. Bezeichnen wir diese beien Dreiecke mit TT und T~\tilde{T}, so gilt

B(vk)Tvldb=T(vk)Tvldb+T~(vk)Tvldb.\int_B(\nabla v_k)^\rmT\,\nabla v_l\diff b=\int_T(\nabla v_k)^\rmT\,\nabla v_l\diff b+\int_{\tilde{T}}(\nabla v_k)^\rmT\,\nabla v_l\diff b.

Auf TT und T~\tilde T ist der Integrand jeweils konstant.

Sei PmP_m der dritte Eckknoten im Dreieck TT und sei Φ\Phi die Transformation des Referenzdreiecks auf das Dreieck TT (vgl. oben). Dann gilt

T(vk)Tvldb=0101ξh(ξ,η)detJΦ(ξ,η)dηdξ\int_T(\nabla v_k)^\rmT\,\nabla v_l\diff b =\int_0^1\int_0^{1-\xi}h(\xi,\eta)\,|\det J_\Phi(\xi,\eta)|\diff\eta\diff\xi

mit

h(ξ,η)=(vk(Φ(ξ,η)))Tvl(Φ(ξ,η))=(JΦ(ξ,η)Tφ1(ξ,η))TJΦ(ξ,η)Tφ2(ξ,η)=(φ1(ξ,η))TJΦ(ξ,η)1JΦ(ξ,η)Tφ2(ξ,η)=(φ1(ξ,η))T(JΦ(ξ,η)TJΦ(ξ,η))1φ2(ξ,η){\begin{align*} h(\xi,\eta) &=\bigl(\nabla v_k(\Phi(\xi,\eta))\bigr)^\rmT\,\nabla v_l(\Phi(\xi,\eta))\\ &=\bigl(J_\Phi(\xi,\eta)^{-\rmT}\,\nabla\varphi_1(\xi,\eta)\bigr)^\rmT\,J_\Phi(\xi,\eta)^{-\rmT}\,\nabla\varphi_2(\xi,\eta)\\ &=\bigl(\nabla\varphi_1(\xi,\eta)\bigr)^\rmT\,J_\Phi(\xi,\eta)^{-1}\,J_\Phi(\xi,\eta)^{-\rmT}\,\nabla\varphi_2(\xi,\eta)\\ &=\bigl(\nabla\varphi_1(\xi,\eta)\bigr)^\rmT\,\bigl(J_\Phi(\xi,\eta)^\rmT\,J_\Phi(\xi,\eta)\bigr)^{-1}\,\nabla\varphi_2(\xi,\eta) \end{align*}}

und

detJΦ(ξ,η)=det(JΦ(ξ,η)TJΦ(ξ,η)).\det J_\Phi(\xi,\eta)=\sqrt{\det\bigl(J_\Phi(\xi,\eta)^\rmT\,J_\Phi(\xi,\eta)\bigr)}.

Die symmetrische und positiv definite Matrix JΦ(ξ,η)TJΦ(ξ,η)J_\Phi(\xi,\eta)^\rmT\,J_\Phi(\xi,\eta) nimmt für alle ξ\xi und η\eta den gleichen Wert

JΦ(ξ,η)TJΦ(ξ,η)=[αββγ]J_\Phi(\xi,\eta)^\rmT\,J_\Phi(\xi,\eta)={\begin{bmatrix}\alpha&\beta\\\beta&\gamma\end{bmatrix}}

mit Zahlen α,β,γ,δR\alpha,\beta,\gamma,\delta\in\bbR an. Auch die Gradienten der Formfunktionen hängen nicht von ξ\xi und η\eta ab:

φ1(ξ,η)=[11],φ2(ξ,η)=[10].\nabla\varphi_1(\xi,\eta)={\begin{bmatrix}-1\\-1\end{bmatrix}},\qquad \nabla\varphi_2(\xi,\eta)={\begin{bmatrix}1\\0\end{bmatrix}}.

Der Integrand ist also konstant und der Integrationsbereich (Referenzdreieck) hat den Flächeninhalt 12\frac{1}{2}. Somit

T(vk)Tvldb=121αγβ2[11][γββα][10]αγβ2=βγ2αγβ2.{\begin{align} \int_T(\nabla v_k)^\rmT\,\nabla v_l\diff b &=\frac{1}{2}\,\frac{1}{\alpha\,\gamma-\beta^2}\,{\begin{bmatrix}-1&-1\end{bmatrix}}\,{\begin{bmatrix}\gamma&-\beta\\-\beta&\alpha\end{bmatrix}}\,{\begin{bmatrix}1\\0\end{bmatrix}}\,\sqrt{\alpha\,\gamma-\beta^2}\\ &=\frac{\beta-\gamma}{2\,\sqrt{\alpha\,\gamma-\beta^2}}. \end{align}}

Für k=lk=l erhält man völlig analog (zweimal φ1\varphi_1 statt φ1\varphi1 mit φ2\varphi_2)

T(vk)Tvkdb=α+γ2β2αγβ2.\int_T(\nabla v_k)^\rmT\,\nabla v_k\diff b=\frac{\alpha+\gamma-2\,\beta}{2\,\sqrt{\alpha\,\gamma-\beta^2}}.

Ist PkP_k oder PlP_l ein Knoten auf dem Dirichlet-Rand, so spielt der Wert a(vk,vl)a(v_k,v_l) keine Rolle in der Systemmatrix, taucht aber bei der Berechnung des Bereichsintegrals a(u1,vk)a(u_1,v_k) bzw. a(u1,vl)a(u_1,v_l) in der rechten Seite bb auf.

# Matrix A ohne Diagonale, Dirichlet-Anteil von b
for n1, n2 in neighbors:

    # a(v_n1, v_n2) berechnen
    int_gradgrad = 0
    for tri in tris_of_nodes[n1] & tris_of_nodes[n2]:  # höchstens 2 Läufe
        n3 = next(iter(set(triangles[tri, :]) - {n1, n2}))  # dritter Knoten des Dreiecks
        J = np.vstack((nodes[n2, :] - nodes[n1, :], nodes[n3, :] - nodes[n1, :])).T
        JJ = np.matmul(J.T, J)
        detJJ = JJ[0, 0] * JJ[1, 1] - JJ[0, 1] ** 2
        int_gradgrad += (JJ[0, 1] - JJ[1, 1]) / (2 * np.sqrt(detJJ)) 

    # in Matrix A oder in rechte Seite schreiben?
    n1d = n1 in d_nodes
    n2d = n2 in d_nodes
    if not n1d and not n2d:
        i1 = node2idx[n1]
        i2 = node2idx[n2]
        Acols.append(i1)
        Arows.append(i2)
        Adata.append(int_gradgrad)
        Acols.append(i2)
        Arows.append(i1)
        Adata.append(int_gradgrad)
    elif n1d and not n2d:
        i2 = node2idx[n2]
        b[i2] += -g1(nodes[n1, 0], nodes[n1, 1]) * int_gradgrad
    elif n2d and not n1d:
        i1 = node2idx[n1]
        b[i1] += -g1(nodes[n2, 0], nodes[n2, 1]) * int_gradgrad
    else:  # Dirichlet-Randkante
        pass

# Diagonale von A
for n1 in ni_nodes:
    i1 = node2idx[n1]

    # a(v_n1, v_n1) berechnen
    int_gradgrad = 0
    for tri in tris_of_nodes[n1]:
        n2, n3 = set(triangles[tri, :]) - {n1}
        J = np.vstack((nodes[n2, :] - nodes[n1, :], nodes[n3, :] - nodes[n1, :])).T
        JJ = np.matmul(J.T, J)
        detJJ = JJ[0, 0] * JJ[1, 1] - JJ[0, 1] ** 2
        int_gradgrad += (JJ[0, 0] + JJ[1, 1] - 2 * JJ[0, 1]) / (2 * np.sqrt(detJJ)) 

    # in Matrix schreiben
    Acols.append(i1)
    Arows.append(i1)
    Adata.append(int_gradgrad)

12.4.4Neumann-Randbedingungen

In die rechte Seite bb müssen noch die Integrale

Γ2g2vkds\int_{\Gamma_2}g_2\,v_k\diff s

eingebracht werden, wobei kk die globalen Knotennummern der Knoten auf dem Neumann-Rand durchläuft.

Das Integrationsgebiet Γ2\Gamma_2 kann in einzelne Randkanten zerlegt werden, wobei für jede Kante die Endknoten entweder beide auf dem Neumann-Rand liegen oder ein Endknoten auf dem Neumann- und ein Endknoten auf dem Dirichlet-Rand liegt.

In das Integral über eine Randkante gehen nur zwei Basisfunktionen (zwei Neumann-Knoten) oder nur eine Basisfunktion (Dirichlet-Knoten und Neumann-Knoten) ein.

Seien PkP_k und PlP_l die Endknoten einer Randkante KK. Dann ist durch

Ψ(ζ):=Pk+ζ(PlPk)\Psi(\zeta):=P_k+\zeta\,(P_l-P_k)

eine Abbildung des Intervalls [0,1][0,1] auf die Randkante gegeben. Damit erhalten wir

Kg2vkds=01g2(Ψ(ζ))(1ζ)dζ\int_K g_2\,v_k\diff s=\int_0^1 g_2(\Psi(\zeta))\,(1-\zeta)\diff\zeta

und

Kg2vlds=01g2(Ψ(ζ))ζdζ,\int_K g_2\,v_l\diff s=\int_0^1 g_2(\Psi(\zeta))\,\zeta\diff\zeta,

wobei wir

vk(Ψ(θ))=1ζundvl(Ψ(θ))=ζv_k(\Psi(\theta))=1-\zeta\qquad\text{und}\qquad v_l(\Psi(\theta))=\zeta

verwendet haben.

Diese Integrale können leicht mittels numerischer Integration berechnet werden.

from scipy.integrate import quad

# Neumann-Anteil von b
for n1, n2 in neighbors:

    # mindestens ein Neumann-Randknoten
    n1n = n1 in n_nodes
    n2n = n2 in n_nodes
    n1d = n1 in d_nodes
    n2d = n2 in d_nodes
    if not((n1n and n2n) or (n1n and n2d) or (n1d and n2n)):
        continue  # keine Neumann-Randkante

    # Integral von g_2 * v_n1 und von g_2 * v_n2
    P1 = nodes[n1, :]
    P2 = nodes[n2, :]
    distP1P2 = np.sqrt((P1[0] - P2[0]) ** 2 + (P1[1] - P2[1]) ** 2)
    if n1n:  # Basisfunktion bei D-Knoten trägt nicht zum Integral bei
        i1 = node2idx[n1]
        func = lambda t: g2(*(P1 - t * (P2 - P1))) * (1 - t)
        b[i1] += distP1P2 * quad(func, 0, 1)[0]
    if n2n:
        i2 = node2idx[n2]
        func = lambda t: g2(*(P1 - t * (P2 - P1))) * t
        b[i2] += distP1P2 * quad(func, 0, 1)[0]

12.5Lösen des Gleichungssystems

Das Gleichungssystem kann mit Standardverfahren für dünn besetzte Matrizen gelöst werden.

import scipy.sparse as ss

# Matrix A als SciPy-Objekt
A = ss.csr_array(
    (Adata, (Arows, Acols)), 
    shape=(len(ni_nodes), len(ni_nodes))
)

# Gleichungssystem lösen
u0 = ss.linalg.spsolve(A, b)

12.6Zusammensetzen der Lösung

Das Array u0 enthält nun die Funktionswerte der Lösungsfunktion an den inneren Knoten und an den Randknotes des Neumann-Randes. Auf dem Dirichlet-Rand ist die Lösung bekannt.

# Lösung zusammensetzen
u = np.zeros(len(nodes), dtype=float)
u[d_nodes] = g1(nodes[d_nodes, 0], nodes[d_nodes, 1])
u[ni_nodes] = u0

Für die Darstellung der Lösung kann der Bereich zwischen den Knoten linear interpoliert werden. Dies entspricht der kontinuierlichen Darstellung der Lösung als Summe stückweise linearer Ansatzfunktionen.

# Plot der Lösung
fig, ax = plt.subplots(figsize=(10, 5))

# Lösung
contour_plot = ax.tricontourf(
    nodes[:, 0], nodes[:, 1], triangles, u, cmap='jet', levels=100
)
fig.colorbar(contour_plot, ax=ax, orientation='vertical')

# Dreiecke
for n1, n2, n3 in triangles:
    n1231 = [n1, n2, n3, n1]
    ax.plot(nodes[n1231, 0], nodes[n1231, 1], '-w', lw=0.5)

ax.axis('equal')
ax.set_xlabel('x')
ax.set_ylabel('y')

plt.show()
<Figure size 1000x500 with 2 Axes>

12.7Realitätsnähe

Die Modellierung mit Dirichlet-Randbedingungen ist wenig realitätnah. Um die Oberflächentemperatur konstant bei 20°C zu halten, müsste das Bauteil beispielsweise von einer 20°C warmen Luftströmung umströmt werden, die beliebig viel Wärme aufnehmen kann. Realistischer sind Robin-Randbedingungen, die die Wärmeabgabe proportional zur Differenz zwischen Oberflächen- und Umgebungstemperatur modellieren (vgl. Diffusionsgleichung).

Bei der schwachen Formulierung mit Robin-Randbedingungen erhält man sowohl in der Bilinearform aa als auch in der rechten seite bb zusätzlich ein Kurvenintegral über den Robinrand.