7.1 ODE-løser som funksjon: forward Euler
Skrive en forward-Euler-løser fra bunnen som en funksjon — det enkleste ODE-mønsteret, og grunnlaget for å forstå det utleverte hierarkiet.
Differensiallikninger er ett av de fem temaene som står i alle de åtte gjennomgåtte avsluttende settene (100 %, 8 av 8). Del 7 er derfor et av kapitlene som må sitte — høyeste prioritet.
Dette kapitlet trener sjanger I — altså oppgavetypen «skriv en ODE-løser som en vanlig funksjon», der du selv setter opp tidspunktene, løsningsarrayet og løkka. Den går igjen jevnlig og er verdt rundt 5 poeng. Sjangeren dukker opp som fritekst-koding: du skriver koden i et tekstfelt i Inspera (UiOs digitale eksamenssystem), uten hjelpemidler og uten å kunne kjøre den.
De to store ODE-sjangrene kommer i kapitlene etter: sjanger J (bruke det utleverte løser-hierarkiet, 9–10 poeng, i hvert sett) i kap. 7.2 og kap. 7.3, og sjanger K (skrive en subklasse) i kap. 7.4. Dette kapitlet er grunnmuren under alle tre: skjønner du løkka her, leser du hierarkiet uten problemer.
Du får uttelling for riktig struktur selv om en indeks glipper. Det er nesten umulig å få alle indekser 100 % riktige på en hjelpemiddelfri eksamen, og de offisielle løsningsforslagene sier eksplisitt at god score gis til besvarelser som får den overordnede løkkestrukturen riktig.
Løkke 1 — hva en ODE er, og Eulers idé (~12 min) · Løkke 2 — hele løser-funksjonen (~15 min) · Løkke 3 — nøyaktighet og steglengde (~13 min) · Løkke 4 — varianter du kan bli bedt om (~15 min)
Forkunnskaper — sist du var her
Dette kapitlet bygger på tre ting fra tidligere i boka. Her er de, ferdig oppfrisket, så du ikke trenger å bla.
1. np.linspace og punkttelling (kap. 4.1). np.linspace(a, b, M) gir M punkter der begge endepunktene er med. Deler du i 30 like store steg, får du 31 punkter:
import numpy as np
t = np.linspace(0, 3, 31)
print("antall punkter:", len(t))
print("avstanden mellom to punkter:", t[1] - t[0])
print("siste punkt:", t[-1])
u = np.zeros_like(t)
print("u har form", u.shape, "og starter som", u[:4])Utskrift:
antall punkter: 31
avstanden mellom to punkter: 0.1
siste punkt: 3.0
u har form (31,) og starter som [0. 0. 0. 0.]2. En funksjon kan sendes som argument (kap. 1.6). Et funksjonsnavn uten parenteser er bare en verdi, og kan sendes videre og kalles inne i den andre funksjonen:
def bruk(g, x):
return g(x) + g(2*x)
def kvadrat(x):
return x**2
print(bruk(kvadrat, 3))Utskrift:
453. Differenslikning-mønsteret (kap. 6.2): allokér arrayet, sett startverdien FØR løkka, og la løkka fylle inn neste indeks.
import numpy as np
x = np.zeros(5)
x[0] = 100
for n in range(4):
x[n+1] = 1.5*x[n]
print(x)Utskrift:
[100. 150. 225. 337.5 506.25]Matematikken bak — hva en differensiallikning er, og hvordan de enkleste løses eksakt — står i Differensialligninger: separable og lineære første ordens. Du trenger den ikke for å kode, men den er nyttig når du skal sjekke svaret ditt.
Løkke 1 — hva en ODE er, og Eulers idé
En kopp kaffe på 80 grader står i et rom på 20 grader. Kaffen kjøles ned raskt i starten og saktere etter hvert, og farten avhenger av hvor varm kaffen er akkurat nå. Det er nettopp den situasjonen en differensiallikning beskriver: den forteller deg stigningstallet, ikke verdien.
Skriver vi for kaffetemperaturen, sier Newtons avkjølingslov at . Vi kjenner ikke , men vi kjenner farten i hvert punkt — uttrykt ved selv. En slik likning kalles en ordinær differensiallikning, forkortet ODE (fra engelsk ordinary differential equation).
Legger vi til startverdien , er problemet fastlagt: én temperatur i starten, og en regel for hvordan den endrer seg. Det er dette du skal løse numerisk.
Funksjonen kalles høyresiden: den tar tidspunktet og den nåværende verdien , og returnerer stigningstallet der. I Python er høyresiden en helt vanlig funksjon med to argumenter, og rekkefølgen er t først:
def f(t, u):
return -0.1*(u - 20)Legg merke til at t ikke behøver å brukes i kroppen. Argumentet skal likevel være med, fordi løseren alltid kaller f(t, u) med to argumenter.
Startverdien er data, ikke en del av f. Den sendes til løseren separat.
Det er hele metoden. Den kalles forlengs Euler (engelsk forward Euler), og er den eksplisitte metoden alt annet måles mot: neste verdi regnes ut direkte fra den forrige, uten å løse noen likning.
I Python blir oppdateringen én linje inne i en løkke:
u[n+1] = u[n] + dt*f(t[n], u[n])Tre ting å merke seg, alle tre er poenggivende detaljer på eksamen:
- f kalles med to argumenter, t[n] og u[n] — i den rekkefølgen.
- Både t[n] og u[n] er ett tall, ikke hele arrayet.
- Løkka skriver til indeks n+1, så den må stoppe én før slutten.
Løs med og steglengde . Regn ut de tre første stegene for hånd, og sjekk med en løkke.
For hånd, med :
-
-
-
Hvert steg ganger altså verdien med . Samme regnestykke i kode:
def f(t, u):
return -2*u
u = 1.0
t = 0.0
dt = 0.2
for n in range(3):
u = u + dt*f(t, u)
t = t + dt
print(f"t = {t:.1f} u = {u:.4f}")Utskrift:
t = 0.2 u = 0.6000
t = 0.4 u = 0.3600
t = 0.6 u = 0.2160Den eksakte løsningen er , som gir . Eulers svar 0,216 er altså tydelig for lavt — steglengden er stor. Det retter vi opp i Løkke 3.
Merk at denne varianten bare holder styr på én verdi av gangen. Skal du kunne plotte kurven etterpå, må alle verdiene lagres i et array. Det er neste løkke.
(Innsteg — punkttelling.) Du skal løse på intervallet med 40 steg.
a) Hvor mange punkter må tidsarrayet t ha?
b) Hva blir steglengden dt?
c) Hvor mange ganger kjører løkkekroppen som gjør oppdateringen?
Løkke 2 — hele løser-funksjonen
Nå skal alle verdiene lagres. Mønsteret er akkurat det samme som for differenslikninger: lag tidspunktene, allokér et løsningsarray av samme størrelse, sett startverdien, og la løkka fylle resten.
Signaturen boka bruker — og som eksamensoppgavene i denne sjangeren spør etter — er forward_euler(f, T, N, u0): høyresiden, sluttiden, antall steg og startverdien. Funksjonen returnerer to ting: tidspunktene og løsningen.
Lager et array med jevnt fordelte tall fra a til b, der begge endepunktene er med. Det tredje argumentet er antall PUNKTER, ikke antall steg.
Skal intervallet deles i N like store steg, trenger du derfor N+1 punkter:
import numpy as np
print(np.linspace(0, 1, 5))Utskrift:
[0. 0.25 0.5 0.75 1. ]Fire steg på 0,25 — fem punkter. Dette er kilden til den hyppigste feilen i faget, og den har eget nummer i feilkatalogen: #1 — av-én-feilen på antall punkter.
Lager et nytt array med samme form og samme datatype som t, fylt med nuller. Brukes til å allokere løsningsarrayet, så det garantert blir like langt som tidsarrayet:
import numpy as np
t = np.linspace(0, 1, 4)
u = np.zeros_like(t)
print(u, u.shape)Utskrift:
[0. 0. 0. 0.] (4,)Alternativet np.zeros(N+1) gjør det samme når du vet tallet. Fordelen med zeros_like er at formen ikke kan komme i utakt med t.
Fire linjer i fast rekkefølge — dette er skjelettet du skal kunne skrive uten å tenke:
1. t = np.linspace(0, T, N+1) — tidspunktene. N steg, N+1 punkter.
2. u = np.zeros_like(t) — plass til løsningen, like lang som t.
3. u[0] = u0 — startverdien, før løkka.
4. for n in range(N): u[n+1] = u[n] + dt*f(t[n], u[n]) — N oppdateringer.
Deretter return t, u.
import numpy as np
def forward_euler(f, T, N, u0):
t = np.linspace(0, T, N+1)
u = np.zeros_like(t)
u[0] = u0
dt = t[1] - t[0]
for n in range(N):
u[n+1] = u[n] + dt*f(t[n], u[n])
return t, uUtskrift: ingen (funksjonen definerer bare mønsteret; den kalles i eksempelet under).
Legg merke til at range(N) gir n = 0, 1, …, N-1, slik at siste tilordning treffer u[N] — det siste punktet. Bytter du til range(N+1), krasjer programmet med IndexError på siste runde.
Bruk forward_euler til å løse , , på med 30 steg. Hvor mange punkter har løsningen? Sammenlign sluttverdien med den eksakte .
import numpy as np
def forward_euler(f, T, N, u0):
t = np.linspace(0, T, N+1)
u = np.zeros_like(t)
u[0] = u0
dt = t[1] - t[0]
for n in range(N):
u[n+1] = u[n] + dt*f(t[n], u[n])
return t, u
def f(t, u):
return -2*u
t, u = forward_euler(f, 3, 30, 1)
print("antall punkter:", len(t))
print("dt =", t[1] - t[0])
print(f"u(3) numerisk = {u[-1]:.6f}")
print(f"u(3) eksakt = {np.exp(-6):.6f}")Utskrift:
antall punkter: 31
dt = 0.1
u(3) numerisk = 0.001238
u(3) eksakt = 0.00247931 punkter — det er svaret på spørsmålet oppgaven stiller, og det er alltid N+1.
Sluttverdien er omtrent halvparten av den riktige. Det er ikke en programmeringsfeil: forlengs Euler underestimerer systematisk når løsningen er konveks og avtakende, og med og er steget grovt. Absolutt sett er avviket bittelite (0,0012), men relativt er det stort. Løkke 3 viser hvordan feilen oppfører seg når du forfiner.
Fire feil står for nesten alle tapte poeng i denne sjangeren.
#1 — av-én på antall punkter. np.zeros(N) i stedet for np.zeros(N+1), eller np.linspace(0, T, N). Da mangler siste punkt, og siste tilordning gir IndexError. Regelen: N steg, N+1 punkter.
Sette u[0] etter løkka. Da regner løkka med nuller hele veien, og du får et array fullt av nuller med startverdien limt på til slutt. Startverdien skal settes før løkka.
Regne dt feil. dt = T/N er riktig når du starter i 0, men dt = T/(N+1) er galt, og dt = t[1] - t[0] er alltid riktig. Bruk den formen — den følger av arrayet du nettopp lagde.
#14 — feil argumentrekkefølge til f. Boka og alle nyere sett bruker f(t, u). Kaller du f(u[n], t[n]), kompilerer det fint og gir tull. Mer om denne API-driften nedenfor.
a) Skriv funksjonen forward_euler(f, T, N, u0) som løser et vilkårlig initialverdiproblem med forlengs Euler og returnerer t, u.
b) Bruk den til å løse likningen over på med 50 steg, og skriv ut vannhøyden ved .
Løkke 3 — nøyaktighet og steglengde
— naturlig pausepunkt —
Eksempel 2 ga et svar som var nesten dobbelt for lite. Spørsmålet er hva som skjer når du gjør stegene mindre. Svaret er en av de få «teoretiske» tingene du kan bli spurt om i denne sjangeren, og den er lett å huske fordi du kan måle den.
Mål feilen som det største avviket fra den eksakte løsningen over alle punktene, og halvér steglengden gang på gang.
Steglengden lest ut av tidsarrayet, i stedet for regnet ut på nytt. Den er alltid riktig når t kommer fra np.linspace, og du unngår å blande antall punkter og antall steg.
import numpy as np
t = np.linspace(0, 3, 31)
print(t[1] - t[0], 3/30, 3/31)Utskrift:
0.1 0.1 0.0967741935483871De to første er like, den tredje er den klassiske av-én-feilen (#1). Merk symbolkollisjonen: i numerisk derivasjon het steget h (kap. 6.1), her heter det dt fordi det er et steg i tid. Det er samme slags størrelse.
En metode har konvergensorden hvis feilen oppfører seg som når steget blir lite. Praktisk konsekvens, og det du måler i en tabell:
- orden 1: halvér feilen halveres (faktor 2)
- orden 2: halvér feilen firedeles (faktor 4)
- orden 4: halvér feilen deles på 16
Forlengs Euler har orden 1. Det er derfor den er billig per steg, men trenger mange steg for god nøyaktighet.
Løs , , på med steg. Mål det største avviket fra den eksakte løsningen , og avgjør hvilken orden metoden har.
import numpy as np
def forward_euler(f, T, N, u0):
t = np.linspace(0, T, N+1)
u = np.zeros_like(t)
u[0] = u0
dt = t[1] - t[0]
for n in range(N):
u[n+1] = u[n] + dt*f(t[n], u[n])
return t, u
def f(t, u):
return -2*u
print(" N dt maks feil")
for N in [30, 60, 120, 240]:
t, u = forward_euler(f, 3, N, 1)
feil = np.max(np.abs(u - np.exp(-2*t)))
print(f"{N:6d} {t[1]-t[0]:8.5f} {feil:12.4e}")Utskrift:
N dt maks feil
30 0.10000 4.0199e-02
60 0.05000 1.9201e-02
120 0.02500 9.3935e-03
240 0.01250 4.6470e-03Feilen går fra 4,02e-02 til 1,92e-02 til 9,39e-03 til 4,65e-03. Hver gang steget halveres, halveres feilen: forholdet er 2,09, 2,04 og 2,02. Det er orden 1, akkurat som teorien sier.
To detaljer verdt å legge seg på minnet:
- np.exp(-2*t) regner den eksakte løsningen i alle punktene på én gang — t er et array, så resultatet er et array (vektorisering, kap. 4.2).
- np.max(np.abs(...)) er standardmåten å måle «største avvik» på, og den forventes i besvarelser som skal vise nøyaktighet.
Bruk forward_euler fra oppgave 2 på , , over , der den eksakte løsningen er .
a) Skriv kode som regner ut det største avviket for og for .
b) Skriv ut forholdet mellom de to feilene, og forklar hva tallet forteller.
(Midtveisnivå, sjanger A — kodesporing, altså «hva skriver dette programmet ut?».) Skriv utskriften nøyaktig, med mellomrom slik terminalen viser den.
import numpy as np
u = np.zeros(4)
u[0] = 2
dt = 0.5
for n in range(3):
u[n+1] = u[n] + dt*(1 - u[n])
print(f"{u[n+1]:.3f}", end=' ')Løkke 4 — de variantene du kan bli bedt om
Oppgaveteksten spør sjelden om forlengs Euler alene. Den ber om «en løser etter dette skjemaet», og så står det en litt annen formel. Da skal du gjenkjenne at bare oppdateringslinja endres — de fire linjene rundt er de samme.
To varianter er verdt å kunne skrive fra bunnen: baklengs Euler for det enkle henfallsproblemet, og en av de to-stegs metodene (Heun eller midtpunkt).
Den ukjente står på begge sider — metoden er implisitt. For den spesielle høyresiden kan du løse for med algebra:
I kode blir det én linje:
u[n+1] = u[n]/(1 + dt*lam)Metoden har også orden 1, men den er stabil for alle steglengder: nevneren er alltid større enn 1, så løsningen kan aldri vokse. For en generell høyreside må du løse en likning i hvert steg — det gjør vi i kap. 7.4.
Løs , , på med bare 10 steg, med forlengs og baklengs Euler. Hva skjer?
import numpy as np
def forward_euler_lam(lam, T, N, u0):
t = np.linspace(0, T, N+1)
u = np.zeros_like(t)
u[0] = u0
dt = t[1] - t[0]
for n in range(N):
u[n+1] = u[n] - dt*lam*u[n]
return t, u
def backward_euler_lam(lam, T, N, u0):
t = np.linspace(0, T, N+1)
u = np.zeros_like(t)
u[0] = u0
dt = t[1] - t[0]
for n in range(N):
u[n+1] = u[n]/(1 + dt*lam)
return t, u
t, uf = forward_euler_lam(50, 1, 10, 1)
t, ub = backward_euler_lam(50, 1, 10, 1)
print(" t forlengs baklengs")
for n in range(5):
print(f"{t[n]:5.1f} {uf[n]:11.2f} {ub[n]:12.6f}")Utskrift:
t forlengs baklengs
0.0 1.00 1.000000
0.1 -4.00 0.166667
0.2 16.00 0.027778
0.3 -64.00 0.004630
0.4 256.00 0.000772Forlengs Euler bytter fortegn og firedobler seg hvert steg: faktoren er . Løsningen sprenger, selv om den eksakte løsningen faller mot null. Baklengs Euler ganger med hvert steg og oppfører seg pent.
Dette er hele poenget med stive problemer: er stor, krever en eksplisitt metode små steg for å ikke sprenge. Med forlengs Euler må her, altså minst 25 steg.
Merk at begge funksjonene er skrevet for den spesielle høyresiden , og tar lam i stedet for en funksjon f. Det er et bevisst valg fordi den lukkede formelen for baklengs Euler bare gjelder denne høyresiden. Det er verdt en kommentar i en eksamensbesvarelse.
I kode er det tre linjer inne i løkka:
k1 = f(t[n], u[n])
k2 = f(t[n] + dt, u[n] + dt*k1)
u[n+1] = u[n] + dt*(k1 + k2)/2Utskrift: ingen (fragmentet hører inne i løkka i eksempelet under).
Metoden har orden 2: halvert steg gir en firedel av feilen. Prisen er to kall til f per steg i stedet for ett.
Skriv heun(f, T, N, u0) etter samme mønster som forward_euler, og mål feilen for på med .
import numpy as np
def heun(f, T, N, u0):
t = np.linspace(0, T, N+1)
u = np.zeros_like(t)
u[0] = u0
dt = t[1] - t[0]
for n in range(N):
k1 = f(t[n], u[n])
k2 = f(t[n] + dt, u[n] + dt*k1)
u[n+1] = u[n] + dt*(k1 + k2)/2
return t, u
def f(t, u):
return -2*u
print(" N maks feil")
for N in [30, 60, 120, 240]:
t, u = heun(f, 3, N, 1)
print(f"{N:6d} {np.max(np.abs(u - np.exp(-2*t))):12.4e}")Utskrift:
N maks feil
30 2.8604e-03
60 6.6154e-04
120 1.5918e-04
240 3.9049e-05Forholdene er 4,32, 4,16 og 4,08 — feilen firedeles når steget halveres, altså orden 2. Sammenlign med Eksempel 3: med 30 steg er Heun ca. 14 ganger nøyaktigere enn forlengs Euler, for dobbelt så mange funksjonskall.
Legg merke til at bare de tre linjene inne i løkka er nye. Alt annet — linspace med N+1, zeros_like, u[0] før løkka, range(N), return t, u — er ordrett det samme som i forward_euler. Det er slik du skal lese en oppgave som ber om «en annen metode etter samme skjema».
f(t, u) — tid først. I eldre sett (2020–2022) var rekkefølgen omvendt, f(u, t). Boka bruker konsekvent den nye, f(t, u), fordi det er den du møter nå. To forholdsregler på eksamen:- Les vedlegget. Får du en ODE-modul utlevert, står rekkefølgen der. Den kan endres fra år til år.
- Vær konsekvent. Skriver du selv løseren og høyresiden, er alle konsistente valg riktige — men de må stemme med hverandre. En besvarelse som er konsekvent, får uttelling selv om den bruker den gamle rekkefølgen.
Rekursjon er utenfor pensum. Oppdateringsformelen ser rekursiv ut, og det er fristende å skrive en funksjon som kaller seg selv. Ikke gjør det: rekursjon er utenfor pensum i dette emnet, gir dårligere eller ingen uttelling, og markeres som uønsket i de offisielle løsningsforslagene. Alt løses med løkke som lagrer verdiene i et array — i tillegg til at du da har hele løsningen tilgjengelig for plotting.
Radioaktivt henfall følger med .
a) Skriv backward_euler_lam(lam, T, N, u0) som bruker den lukkede oppdateringsformelen for baklengs Euler.
b) Kjør den for , , og , og skriv ut alle verdiene sammen med den eksakte løsningen.
c) Ville forlengs Euler vært brukbar med samme steglengde? Grunngi med ett regnestykke.
Runge–Kutta-metoder av orden 2 gjengir polynomer av grad 2 eksakt. Det gir en presis test.
a) Skriv heun(f, T, N, u0).
b) Skriv en testfunksjon test_heun() uten argumenter som sjekker at løseren treffer den eksakte løsningen av , (altså ) i sluttpunktet, med toleranse .
c) Kall testfunksjonen og skriv ut en bekreftelse.
En kopp kaffe på 80 °C står i et rom på 20 °C og følger Newtons avkjølingslov med per minutt.
a) Løs likningen på (minutter) med forward_euler og 600 steg.
b) Finn det første tidspunktet der temperaturen er under 60 °C, ved å løkke gjennom løsningen.
c) Skriv ut temperaturen etter én time.
Begrepsbank
Begrepsbanken er flashcard-/repetisjonsstoff — den gjentar det du nettopp har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet gjelder kjernestoffet.
Python-funksjonen som gir stigningstallet i et initialverdiproblem. Tar to argumenter — tid først, tilstand etterpå — og returnerer i det punktet.
def f(t, u):
return -2*uBoka og alle sett fra 2023 og senere bruker denne rekkefølgen. Argumentet t skal med selv om kroppen ikke bruker det.
Avstanden i tid mellom to nabopunkter i løsningen. Regnes ut som t[1] - t[0] eller T/N, aldri T/(N+1).
Mindre dt gir mindre feil, men flere steg. For forlengs Euler er feilen omtrent proporsjonal med dt.
Bokas viktigste tellergel. Deler du et intervall i N like store steg, er det N+1 punkter fordi startpunktet også teller.
Konsekvens: np.linspace(0, T, N+1), np.zeros(N+1) og for n in range(N). Feil her er feilkode #1, den hyppigste i faget.
En metode der neste verdi regnes direkte ut av verdier du allerede har. Forlengs Euler og Heun er eksplisitte.
Fordel: én enkel oppdateringslinje. Ulempe: steget må være lite nok, ellers sprenger løsningen (se stabilitet).
En metode der den ukjente u[n+1] står på begge sider av oppdateringen, slik som baklengs Euler.
Da må hvert steg løse en likning. For kan du løse den med algebra; for en generell høyreside trenger du en likningsløser (kap. 7.4).
Brytes det, veksler verdiene fortegn og vokser. Baklengs Euler er stabil for alle steglengder.
Et problem der en av prosessene går mye raskere enn de andre, typisk stor . Da tvinger stabilitetskravet en eksplisitt metode til å bruke veldig små steg selv om løsningen er kjedelig.
Implisitte metoder er svaret på stive problemer.
Startverdien settes utenfor løkka, og løkka fyller bare inn u[1] … u[N].
Settes den etter løkka, regner løkka med nuller hele veien og du får et array av nuller med startverdien limt på. Det er en av de klassiske strukturfeilene i denne sjangeren.
En løser returnerer både tidspunktene og løsningen, som en tuppel. Kalleren pakker ut med to navn:
t, u = forward_euler(f, 3, 30, 1)
print(len(t), len(u))Utskrift:
31 31Uten t kan du verken plotte eller finne ut når noe skjer.
Standardmålet på hvor god en numerisk løsning er: det største avviket over alle punktene.
Både u og eksakt er arrays, så subtraksjonen skjer elementvis og np.abs virker på hele arrayet. Bruk dette, ikke feilen i ett tilfeldig punkt.
Siste element i løsningsarrayet, altså verdien i sluttiden T. Negativ indeks teller fra slutten.
Mange oppgaver spør nettopp «hva er verdien ved » — svaret er u[-1], ikke u[N-1].
At f sendes inn til løseren, er det som gjør løseren gjenbrukbar: samme funksjon løser alle initialverdiproblemer.
Send funksjonsnavnet uten parenteser (forward_euler(f, ...)). Skriver du f(t, u) i kallet, sender du et tall, og løseren krasjer med TypeError når den prøver å kalle det.
Slik måler du orden uten teori: kjør med N og 2N steg og se på forholdet mellom feilene.
Forhold ca. 2 betyr orden 1, ca. 4 betyr orden 2, ca. 16 betyr orden 4. Metoden fungerer bare hvis du har en eksakt løsning å måle mot.
Mellomresultatene i en to-stegs metode: k1 er stigningstallet der du står, k2 stigningstallet i et prøvepunkt.
Heun bruker gjennomsnittet av de to. Midtpunktsmetoden bruker k2 alene, målt et halvt steg fram. Begge har orden 2.
En verdi med gir stigningstall null: løsningen står stille hvis den starter der.
Rask fornuftssjekk av en ODE-besvarelse: regn ut f(0, u0). Er den null, skal løsningen være konstant — og er den det, virker koden.
n er indeksen inne i løkka, N er antall steg. for n in range(N) gir n fra 0 til N-1, og oppdateringen skriver til u[n+1].Blander du de to (range(N+1)), treffer siste tilordning u[N+1], som ikke finnes: IndexError.
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.
Skolesaga er en uavhengig læringsressurs og er ikke tilknyttet eller godkjent av Universitetet i Oslo. Dette er ikke offisielt studiemateriell. Les mer.