Demo 10: Vektorfelter og deres integration langs kurver (det tangentielle kurveintegral)#

Demo af Christian Mikkelstrup, Hans Henrik Hermansen, Jakob Lemvig, Karl Johan Måstrup Kristensen og Magnus Troen. Revideret marts 2026 af shsp.

from sympy import *
from dtumathtools import *

init_printing()

Vektorfelter#

Som enhver anden vektorfunktion kan vektorfelter defineres enten som et Sympy-udtryk,

x, y, z = symbols("x,y,z", real=True)

V = Matrix([y * cos(x), y * sin(x), z])
V
\[\begin{split}\displaystyle \left[\begin{matrix}y \cos{\left(x \right)}\\y \sin{\left(x \right)}\\z\end{matrix}\right]\end{split}\]

eller som en Python-funktion, fx som en lambda-funktion:

V = lambda x, y, z: Matrix([y * cos(x), y * sin(x), z])
V(x, y, z)
\[\begin{split}\displaystyle \left[\begin{matrix}y \cos{\left(x \right)}\\y \sin{\left(x \right)}\\z\end{matrix}\right]\end{split}\]

Du vil også få brug for at indsætte parameterfremstillinger, som i sig selv er vektorfunktioner, ind i vektorfelter, og til det formål er sidstnævnte af de to ovennævnte definitioner nemmest at arbejde med. En parameterkurve,

\[\begin{equation*} \boldsymbol{r} = \begin{bmatrix} r_1(t) \\ r_2(t) \\ r_3(t) \end{bmatrix}, \end{equation*}\]
r1, r2, r3 = symbols("r1,r2,r3", cls=Function)
t = symbols("t")
r = Matrix([r1(t), r2(t), r3(t)])

indsættes nemt i vektorfeltet ved:

V(*r)
\[\begin{split}\displaystyle \left[\begin{matrix}r_{2}{\left(t \right)} \cos{\left(r_{1}{\left(t \right)} \right)}\\r_{2}{\left(t \right)} \sin{\left(r_{1}{\left(t \right)} \right)}\\r_{3}{\left(t \right)}\end{matrix}\right]\end{split}\]

På den anden side kan det være trættende at skulle taste V(x,y,z) hver eneste gang, du skal bruge vektorfeltet, og førstnævnte gør det nemt blot at taste V.

Vektorfelter plottes let. Bemærk, hvordan vi style’r pilene:

vectorfield_V = dtuplot.plot_vector(
    V(x,y,z),
    (x, -1, 1),(y, -1, 1),(z, 0, 6),
    n=5,
    quiver_kw={"alpha": 0.5, "length": 0.1, "color": "black"},
    colorbar=False
)
../_images/3dab0964fd2b62491a8b53ff114781abf52b63d4dec42420b86b0e90125c79a6.png

Hvis du får brug for at beregne flere af et vektorfelts egenskaber som fx rotationen eller divergensen, så findes der dertilegnede kommandoer i dtumathtools-pakken:

rotV = dtutools.rot(V(x, y, z), (x, y, z))
rotV
\[\begin{split}\displaystyle \left[\begin{matrix}0\\0\\y \cos{\left(x \right)} - \cos{\left(x \right)}\end{matrix}\right]\end{split}\]
divV = dtutools.div(V(x, y, z), (x, y, z))
divV
../_images/7e6f62d1a0212bead1852ac35e128c35e6b2a597dd771447a656195078cb3a8a.png

Det tangentielle kurveintegral#

Betragt vektorfeltet

\[\begin{equation*} \pmb{V}(x,y,z) = \begin{bmatrix} -y \\ x \\ 2z \end{bmatrix} \end{equation*}\]

samt de to kurver \({\mathcal K}_1\) og \({\mathcal K}_2\) med parameterfremstillingerne

\[\begin{equation*} \boldsymbol r_1(u) = \begin{bmatrix} \cos(u) \\ \sin(u) \\ \frac{u}{2} \end{bmatrix}\,, \qquad \boldsymbol r_2(u) = \begin{bmatrix} 1 \\ 0 \\ \frac{u}{2} \end{bmatrix}, \end{equation*}\]

hvor \(u \in [0,4\pi]\) for begge.

x, y, z, u = symbols("x y z u", real=True)
r1 = Matrix([cos(u), sin(u), u / 2])
r2 = Matrix([1, 0, u / 2])
V = Matrix([-y, x, 2 * z])
u_interval = (u, 0, 4 * pi)

\(\boldsymbol r_1\) tegner et stykke af en heliks (eller skruelinje), mens \(\boldsymbol r_2(u)\) tegner et lodret linjestykke. Bemærk, at de begge starter i \(A = (1,0,0)\) og ender i \(B = (1,0,2\pi)\). Her er et samlet plot:

K1 = dtuplot.plot3d_parametric_line(
    *r1, u_interval, show=False, rendering_kw={"color": "red"}, colorbar=False
)
K2 = dtuplot.plot3d_parametric_line(
    *r2, u_interval, show=False, rendering_kw={"color": "blue"}, colorbar=False
)
vektorfelt_V = dtuplot.plot_vector(V,(x, -1, 1),(y, -1, 1),(z, 0, 6),
    n=5,
    quiver_kw={"alpha": 0.5, "length": 0.1, "color": "black"},
    colorbar=False,
    show=False,
)

kombineret = K1 + K2 + vektorfelt_V
kombineret.legend = False
kombineret.show()
../_images/6a92e8412632dc03903151e0e43e98b0ab3b0fa79a8d34b6cfd90bd930725e73.png

Vi vil nu beregne det tangentielle kurveintegral af \(\pmb{V}\) langs hver af de to kurver fra \(A\) til \(B\). Lærebogen giver os følgende formel (hvor \(a\) og \(b\) er de \(u\)-værdier, der svarer til hhv. punkterne \(A\) og \(B\), altså \(A=\boldsymbol r(a),B=\boldsymbol r(b)\)):

\[\begin{equation*} \int_{\mathcal K_i} \pmb{V} \cdot \mathrm{d}\pmb{s} = \int_a^b \pmb{V}(\boldsymbol r(u))\cdot \boldsymbol r'(u) \,\mathrm{d}u. \end{equation*}\]

Først tangentvektorerne:

r1d = r1.diff(u)
r2d = r2.diff(u)
r1d, r2d
\[\begin{split}\displaystyle \left( \left[\begin{matrix}- \sin{\left(u \right)}\\\cos{\left(u \right)}\\\frac{1}{2}\end{matrix}\right], \ \left[\begin{matrix}0\\0\\\frac{1}{2}\end{matrix}\right]\right)\end{split}\]

Så integranderne, som er prikprodukter:

integrand1 = V.subs({x: r1[0], y: r1[1], z: r1[2]}).dot(r1d)
integrand2 = V.subs({x: r2[0], y: r2[1], z: r2[2]}).dot(r2d)
integrand1.simplify(), integrand2.simplify()
../_images/857d13e0810fe2a6910cc3785be84c08c58d18f202fbb81daaa363d597927644.png

Det tangentuelle kurveintegral langs \({\mathcal K}_1\) findes altså som \(\displaystyle\int_{{\mathcal K}_1} \pmb{V} \cdot \mathrm{d}\pmb{s} = \int_0^{4\pi} \frac{u}{2} + 1 \,\mathrm{d}u\), og langs \({\mathcal K}_2\) findes det som \(\displaystyle\int_{{\mathcal K}_2} \pmb{V} \cdot \mathrm{d}\pmb{s} = \int_0^{4\pi} \frac{u}{2} \,\mathrm{d}u\):

Tan_K1=integrate(integrand1, (u, 0, 4 * pi))
Tan_K2=integrate(integrand2, (u, 0, 4 * pi))
Tan_K1,Tan_K2
../_images/7c849aca7a18dd12c1b07171a59ca9737b504f073abbb9c6272e2c35748a3a73.png

Vi får ikke samme resultat, hvilket betyder, at det tangentielle kurveintegral afhænger af ruten. Lærebogen fortæller om konsekvenserne af dette, fx at \(\boldsymbol V\) dermed ikke kan være et gradientvektorfelt (dvs., at den ikke har nogen stamfunktion).

Gradientvektorfelter og stamfunktionsbestemmelse#

Hvis et glat vektorfelt er et gradientvektorfelt, så fortæller lærebogen os at:

  • det har en stamfunktion (altså, en funktion som den er gradient for).

  • et tangentielt kurveintegral af det langs enhver kurve fra origo til et vilkårligt punkt \(\pmb{x}\) vil være en stamfunktion.

  • tangentielle kurveintegraler af det er uafhængige af ruten.

Det er altså brugbart at vide, om et vektorfelt er et gradientvektorfelt. Vi kan undersøge, om det er tilfældet, ved at beregne det tangentielle kurveintegral langs en hvilken som helst kurve, hvorefter vi kan tjekke, om første punkt i listen er opfyldt. Da vi kan vælge en hvilken som helst rute, er et ofte-benyttet valg en såkaldt trappelinje.

Trappelinjemetoden#

Lad os betragte et glat vektorfelt i \(\Bbb R^3\):

\[\begin{equation*} \pmb{V}(x,y,z) = \begin{bmatrix} V_1(x,y,z) \\ V_2(x,y,z) \\ V_3(x,y,z) \end{bmatrix}. \end{equation*}\]

Ved trappelinjen \({\mathcal T}\) fra origo \(\pmb{x}_0=(0,0,0)\) til et vilkårligt punkt \(\pmb{x}=(x,y,z)\) menes der ruten, du ville følge, hvis du skulle gå langs med \(x\)-aksen, så langs \(y\)-aksen og så langs \(z\)-aksen. Disse tre stykker er akseparallelle rette linjer og derfor nemme at parametrisere:

\[\begin{split}\boldsymbol r_1(u)=(u,0,0)\,,\,u\in[0,x]\\ \boldsymbol r_2(u)=(x,u,0)\,,\,u\in[0,y]\\ \boldsymbol r_3(u)=(x,y,u)\,,\,u\in[0,z].\end{split}\]
r1 = Matrix([u, 0, 0])
r2 = Matrix([x, u, 0])
r3 = Matrix([x, y, u])

For \((x,y,z)=(1,1,1)\) som et eksempelpunkt kan vi plotte trappelinjen:

u_range = (u, 0, 1)

# Trappelinjens trin
p1 = dtuplot.plot3d_parametric_line(u, 0, 0, u_range, show=False, rendering_kw={"color": "red"}, colorbar=False)
p2 = dtuplot.plot3d_parametric_line(1, u, 0, u_range, show=False, rendering_kw={"color": "red"}, colorbar=False)
p3 = dtuplot.plot3d_parametric_line(1, 1, u, u_range, show=False, rendering_kw={"color": "red"}, colorbar=False)

# Punktet
xyz = dtuplot.scatter(Matrix([1, 1, 1]), show=False, rendering_kw={"color": "black"})

kombineret = p1 + p2 + p3 + xyz
kombineret.legend = False
kombineret.camera = {"azim": 37, "elev": 16}

kombineret.show()
../_images/33ba8fa95895e25e20138393e13de5ec46dbebf46535188f2bc4021787097258.png

Et tangentielt kurveintegral af \(\boldsymbol V\) langs en trappelinje \({\mathcal T}\) kan findes som summen af de tangentielle kurveintegraler langs hver af de tre linjestykker. Og her ser vi fordelen ved trappelinjemetoden; deres tangentvektorer er nemlig meget simple:

r1d = r1.diff(u)
r2d = r2.diff(u)
r3d = r3.diff(u)
r1d, r2d, r3d
\[\begin{split}\displaystyle \left( \left[\begin{matrix}1\\0\\0\end{matrix}\right], \ \left[\begin{matrix}0\\1\\0\end{matrix}\right], \ \left[\begin{matrix}0\\0\\1\end{matrix}\right]\right)\end{split}\]

hvilket gør de tre integrander særdeles simple:

\[\begin{equation*} \begin{aligned} \pmb{V}(\boldsymbol r_1(u)) \cdot \boldsymbol r_1'(u) = V_1(u,0,0),\\ \pmb{V}(\boldsymbol r_2(u)) \cdot \boldsymbol r_2'(u) = V_2(x,u,0),\\ \pmb{V}(\boldsymbol r_3(u)) \cdot \boldsymbol r_3'(u) = V_3(x,y,u). \end{aligned} \end{equation*}\]

Vi er dermed nået frem til følgende formel for det tangentielle kurveintegral af \(\pmb{V}\) langs en trappelinje til et vilkårligt punkt i \(\Bbb R^3\):

\[\begin{equation*} \int_{\mathcal T} \pmb{V} \cdot \mathrm{d}\pmb{s} = \int_0^x V_1(u,0,0) \,\mathrm{d}u + \int_0^y V_2(x,u,0) \,\mathrm{d}u +\int_0^z V_3(x,y,u) \,\mathrm{d}u. \end{equation*}\]

Gradientfelt eller ej?#

Vi ønsker at undersøge, hvorvidt følgende vektorfelt \(\pmb{V}\) er et gradientvektorfelt:

\[\begin{equation*} \pmb{V}(x,y,z) = \begin{bmatrix} y^2 + z \\ 2yz^2 + 2yx \\ 2y^2z + x \end{bmatrix}. \end{equation*}\]
V = Matrix([y**2 + z, 2 * y * z**2 + 2 * y * x, 2 * y**2 * z + x])
V
\[\begin{split}\displaystyle \left[\begin{matrix}y^{2} + z\\2 x y + 2 y z^{2}\\x + 2 y^{2} z\end{matrix}\right]\end{split}\]

Lad os finde det tangentielle kurveintegral af \(\pmb{V}\) langs trappelinjen til et vilkårligt punkt. Vi anvender formlen fra forrige afsnit og opdeler integrationen i tre bidder, hvis tre integrander bliver:

integrand1 = V[0].subs({x: u, y: 0, z: 0})
integrand2 = V[1].subs({y: u, z: 0})
integrand3 = V[2].subs({z: u})

integrand1, integrand2, integrand3
../_images/290fca0d7f736c0e378c7d8f557eac4e6cc75ba94af04463b4726b722ac15e02.png

Det tangentielle kurveintegral bliver:

F = (integrate(integrand1,(u,0,x)) + integrate(integrand2,(u,0,y)) + integrate(integrand3,(u,0,z)))
F
../_images/0aff10dc8f3aff3bc3ff3bec06b3c258f783d5c8d0e6a2d4d0f1b4d084920eb2.png

Dette er en funktion i \(x,y,z\). Lad os finde dens gradient:

F_grad = dtutools.gradient(F)
F_grad, Eq(F_grad, V)
\[\begin{split}\displaystyle \left( \left[\begin{matrix}y^{2} + z\\2 x y + 2 y z^{2}\\x + 2 y^{2} z\end{matrix}\right], \ \text{True}\right)\end{split}\]

Da \(\pmb{V}\) er identisk med gradienten af \(F\), så er \(F\) en stamfunktion til \(\pmb{V}\), og \(\pmb{V}\) er et gradientvektorfelt!

Cirkulation i et gradientvektorfelt#

Betragt vektorfeltet \(\pmb{V}\) fra forrige afsnit samt følgende knude, parametriseret med \(t \in[-\pi,\pi]\):

t = symbols("t")
knude = (
    Matrix([-10 * cos(t) - 2 * cos(5 * t) + 15 * sin(2 * t),
            -15 * cos(2 * t) + 10 * sin(t) - 2 * sin(5 * t),
            10 * cos(3 * t)])
    *S(1)/10
)
knude
\[\begin{split}\displaystyle \left[\begin{matrix}\frac{3 \sin{\left(2 t \right)}}{2} - \cos{\left(t \right)} - \frac{\cos{\left(5 t \right)}}{5}\\\sin{\left(t \right)} - \frac{\sin{\left(5 t \right)}}{5} - \frac{3 \cos{\left(2 t \right)}}{2}\\\cos{\left(3 t \right)}\end{matrix}\right]\end{split}\]
dtuplot.plot3d_parametric_line(*knude, (t, -pi, pi), rendering_kw={"color": "blue"}, legend=False,colorbar=False)
../_images/d425b03c475c45b41bd819bcf93b227ecc73e3314dd5148b5735b40e35607d21.png
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7fa52cd51e50>

En knude er en lukket kurve. Tangentielle kurveintegraler langs lukkede kurver kaldes også cirkulationer. Lad os beregne det tangentielle kurveintegral af \(\pmb{V}\) langs denne knude. Udkommentér følgende kodelinje, og kør den, når du er klar - vær tålmodig, da dette integral kan tage mere end et minut for Sympy at udregne:

#integrate(V.subs({x: knude[0], y: knude[1], z: knude[2]}).dot(knude.diff(t)), (t, -pi, pi))

Du burde få resultatet \(0\).

Det tangentielle kurveintegral af et gradientfelt er uafhængigt af ruten og afhænger dermed kun af endepunkterne, \(\boldsymbol a\) og \(\boldsymbol b\). Integralregningens fundamentalsætning fortæller ligefrem for gradientvektorfelter, at:

\[\int_K \pmb{V} \cdot \mathrm{d}\pmb{s}=F(\boldsymbol b)-F(\boldsymbol a),\]

hvor \(F\) er en stamfunktion. Det er åbenlyst, at det tangentielle kurveintegral af et gradientvektorfelt langs en hvilken som helst lukket kurve altid vil være nul. Med andre ord, enhver cirkulation af et gradientvektorfelt er nul.

Integralkurver (flowkurver)#

Forestil dig, at du til tiden \(t=0\) slipper en partikel i et kraftvektorfelt i punktet \(\pmb{x}_0\). Hvordan vil denne partikel bevæge sig? Hvilken bane vil den følge? Banen vil være en kurve, hvis parameterfremstilling kan betegnes \(\pmb{r}(t)\), der kan fortolkes som positionen som funktion af tiden i et fysisk scenario. Et mere intuitivt billede kunne være en støvpartikel, der “flyver omkring” i vinden.

Sådanne kurver kaldes integralkurver eller nogle gange flowkurver. Bemærk, at det i de ovenstående fysiske analogier er vigtigt, at partiklen opfattes som masseløs, så inertieffekter ikke har nogen indflydelse - en flowkurve er den rute, en partikel vil følge, hvis den kun er under indflydelse af vektorfeltet.

Lærebogen fortæller, at flowkurver er løsninger til følgende differentialligningssystem:

\[\begin{equation*} \pmb{r}'(t) = \pmb V(\pmb{r}(t)), \quad \pmb{r}(0) = \pmb{x}_0, \end{equation*}\]

hvor \(\pmb{x}_0\) er startpunktet.

Betragt følgende vektorfelt i \(\Bbb R^2\):

\[\begin{equation*} \pmb{V}(x,y) = \left[\begin{matrix}-\frac{1}{4}x + \frac{1}{2}y\\\frac{1}{2}x + \frac{1}{4}y\end{matrix}\right]. \end{equation*}\]
x,y = symbols('x y')
V = Matrix([-S(1)/4*x + S(1)/2*y,S(1)/2*x + S(1)/4*y])
V
\[\begin{split}\displaystyle \left[\begin{matrix}- \frac{x}{4} + \frac{y}{2}\\\frac{x}{2} + \frac{y}{4}\end{matrix}\right]\end{split}\]

Lad to partikler \(A\) og \(B\) starte i punkterne hhv. \(\boldsymbol s_A\) og \(\boldsymbol s_B\):

\[\begin{equation*} s_A = (5, 0),\quad s_B = (-3, \frac{1}{2}). \end{equation*}\]
sA, sB = Matrix([5, 0]), Matrix([-3, S(1)/2])

Det differentialligningssystem, der nu skal løses, er:

\[\begin{equation*} \begin{bmatrix}r_1'(t)\\r_2'(t)\end{bmatrix} = \begin{bmatrix}-\frac{1}{4}r_1(t) + \frac{1}{2}r_2(t)\\\frac{1}{2}r_1(t) + \frac{1}{4}r_2(t) \end{bmatrix} =\begin{bmatrix}-\frac{1}{4} & \frac{1}{2}\\\frac{1}{2} & \frac{1}{4}\end{bmatrix} \begin{bmatrix}r_1(t)\\r_2(t)\end{bmatrix}. \end{equation*}\]

hvor \(\boldsymbol r = (r_1,r_2)\). Anvendes begyndelsesværdibetingelsen \(\boldsymbol r(0)=\boldsymbol s_A=(5,0)\), så dannes flowkurven for partikel \(A\), mens \(\boldsymbol r(0)=\boldsymbol s_B=(-3,\frac12)\) danner flowkurven for \(B\).

Bemærk, at følgende tilgang til løsning af systemer af ordinære differentialligninger (eng: ordinary differential equations, ODEs) med Sympy blev behandlet i en Python-demo i kurset Matematik 1a. Har du brug for flere detaljer eller en langsommere gennemgang af metoden, vil vi referere dig dertil.

Vi definerer systemets matrix:

A = Matrix(2, 2, [S("-1/4"), S("1/2"), S("1/2"), S("1/4")])

og opstiller de ubekendte koordinatfunktioner som Sympy-funktioner, hvorefter de differentieres, så vi kan opstille ovenstående matrixligning:

r1 = Function('r1')
r2 = Function('r2')
r = Matrix([r1(t),r2(t)])

dr = diff(r,t)

ode_sys = dr - A * r
ode_sys
\[\begin{split}\displaystyle \left[\begin{matrix}\frac{r_{1}{\left(t \right)}}{4} - \frac{r_{2}{\left(t \right)}}{2} + \frac{d}{d t} r_{1}{\left(t \right)}\\- \frac{r_{1}{\left(t \right)}}{2} - \frac{r_{2}{\left(t \right)}}{4} + \frac{d}{d t} r_{2}{\left(t \right)}\end{matrix}\right]\end{split}\]

Vi løser systemet med dsolve-kommandoen fra dtutools (bemærk, at vi flyttede alt over på venstresiden i ode_sys = dr - A * r, da dsolve antager en nul-højreside):

dtutools.dsolve(ode_sys)
../_images/1d2cef4d3f80c1611ab39aca07a5181e287b63a33c79e374e812a4bfab9dd112.png

Dette udtryk beskriver de to koordinatfunktioner til enhver flowkurve. Vælges specifikke værdier til de ubekendte konstanter, så opnås én specifik flowkurve. Vi gør dette ved at tilføje den givne begyndelsesværdibetingelse med ics-argumentet:

rA_losn = dtutools.dsolve(ode_sys, ics = {r1(0):sA[0], r2(0):sA[1]})
rA_losn
../_images/1d871eb367ef0118ac30f46397549b31196ac3291aab42c0f346dd77e53ef65a.png
rB_losn = dtutools.dsolve(ode_sys, ics = {r1(0):sB[0], r2(0):sB[1]})
rB_losn
../_images/b01de794631e212fe2f8f19da5e15481fc3daa7c761a24ca802d1ff61839fa18.png

Vi udtrækker parameterkurverne:

rA = Matrix([rA_losn[r1(t)], rA_losn[r2(t)]])
rB = Matrix([rB_losn[r1(t)], rB_losn[r2(t)]])
rA, rB
\[\begin{split}\displaystyle \left( \left[\begin{matrix}\frac{\left(5 - \sqrt{5}\right) e^{\frac{\sqrt{5} t}{4}}}{2} + \frac{\left(\sqrt{5} + 5\right) e^{- \frac{\sqrt{5} t}{4}}}{2}\\\sqrt{5} e^{\frac{\sqrt{5} t}{4}} - \sqrt{5} e^{- \frac{\sqrt{5} t}{4}}\end{matrix}\right], \ \left[\begin{matrix}- \frac{\left(15 - 4 \sqrt{5}\right) e^{\frac{\sqrt{5} t}{4}}}{10} - \frac{\left(4 \sqrt{5} + 15\right) e^{- \frac{\sqrt{5} t}{4}}}{10}\\\frac{\left(5 - 11 \sqrt{5}\right) e^{\frac{\sqrt{5} t}{4}}}{20} + \frac{\left(5 + 11 \sqrt{5}\right) e^{- \frac{\sqrt{5} t}{4}}}{20}\end{matrix}\right]\right)\end{split}\]

Et plot af de to kurver:

v_felt = dtuplot.plot_vector(A * Matrix([x, y]),n=10,scalar=False,colorbar=False,quiver_kw={"color": "black"},show=False)

rA_plot = dtuplot.plot_parametric(
    *rA, [t, 0, 3], rendering_kw={"color": "red"}, colorbar=False, show=False
)
rB_plot = dtuplot.plot_parametric(
    *rB, (t, 0, 4), rendering_kw={"color": "blue"}, colorbar=False, show=False
)

(v_felt + rA_plot + rB_plot).show()
No ranges were provided. This function will attempt to find them, however the order will be arbitrary, which means the visualization might be flipped.
../_images/424b27939ba05dc91fc441fcdf18f7915a0f8bd2581b2653eb1f16339fb24d74.png