8.1 Fra ODE til kode: Euler–Cromer-løkka
Diskretiser tiden, skriv akselerasjonen fra ODE-en, oppdater fart så posisjon — og begrunn hvorfor Euler–Cromer er sensorens foretrukne metode.
Dette er den ene ferdigheten formelarket ikke redder deg på. «Formelarket» er det fagspesifikke arket du får utdelt på eksamen, ved siden av den matematiske formelsamlingen Rottmann og en godkjent kalkulator. Der står bevegelseslikninger, kraftmodeller og standardformler — men ingen kodemal. Løkka må sitte i fingrene.
Slik ligger poengene, ut fra sensorveiledningene i H2023, V2024 og V2025 (tre av løsningsforslagene i arkivet har en innebygd sensorveiledning med poenggiving per deloppgave):
| Del av svaret | Uttelling |
|---|---|
| Riktige initialbetingelser i indeks 0 | 1 poeng |
| Riktig akselerasjonsuttrykk fra differensiallikningen | 3 poeng |
| Riktig oppbygd oppdateringsløkke | 1 poeng |
| Begrunnelsen for metodevalget | trekkes fram som skille mot toppkarakter |
Syntaksfeil straffes ikke. Alle programmeringsspråk godtas, og kandidaten skriver ikke et helt program — bare initialbetingelser og løkke, for hånd, med penn på papir. Du trenger aldri huske
import-linjer utenat.Høyeste prioritet — dette må sitte.
Øktforslag: kapitlet er på 70 minutter. Løkke 1–2 (diskretisering og akselerasjonslinja) er en naturlig første økt, løkke 3–4 (selve løkka og metodebegrunnelsen) den neste, og løkke 5 (kontroll av koden) en kort tredje.
Forkunnskaper — sist du var her
Dette kapitlet bygger på kap. 7.1. Det du trenger derfra, ferdig oppfrisket:
Bevegelseslikningen er Newtons 2. lov med akselerasjonen skrevet som andrederivert av posisjonen:
Høyresiden er summen av kreftene, og den kan avhenge av hvor legemet er, hvor fort det går, og hva klokka er.
Tilstandsform — én andreordens likning skrives om til to førsteordens:
Denne omskrivingen er hele broa til koden: de to likningene blir de to oppdateringslinjene i løkka.
Initialbetingelser. En likning av orden trenger opplysninger om starttilstanden. For en andreordens bevegelseslikning betyr det posisjonen og farten — akkurat de to tallene som blir x[0] og v[0] i koden.
Fra matematikken: Numerisk integrasjon og Programmering av integrasjon gir ideen om å erstatte en kontinuerlig størrelse med en sum over små steg. Numerisk modellering av bevegelse viser den samme løkka i en enklere innpakning — du kan ha møtt den i Fysikk 1 eller Fysikk 2 på videregående.
Python-grunnlaget — lister, for-løkker og numpy-tabeller — hører hjemme i programmeringsemnet IN1900, som ikke er bygget i dette systemet. Alt du faktisk trenger her, blir forklart underveis: fire linjer kode og én løkke.
Notasjonsavtale for kapitlet. Vi bruker om posisjonen langs én akse, om farten med fortegn, om akselerasjonen, om tiden, om steglengden i tid og om antallet lagrede tidspunkt. Variabelnavnene i koden er de samme bokstavene, slik at fysikken og koden ser like ut. Vi bruker .
Løkke 1 — tiden i skiver (~14 min)
Et videokamera som filmer en fallende ball, ser ikke en kontinuerlig bevegelse. Det tar 50 bilder i sekundet, og mellom to bilder vet kameraet ingenting. Likevel klarer du å lese av hele bevegelsen fra bildeserien, fordi bildene ligger tett nok.
En numerisk løsning gjør nøyaktig det samme. I stedet for en formel som gjelder for alle tidspunkt, regner vi ut posisjonen i en serie tidspunkt som ligger tett nok. Svaret er ikke en funksjon, men en tabell av tall.
Intuisjon: analytisk løsning gir deg fasiten i én formel. Numerisk løsning gir deg fasiten som en filmstrimmel. Er strimmelen tett nok, ser du det samme.
Det er tre ting som må på plass før løkka kan starte: et tidsrutenett, en steglengde, og plass til å lagre svaret.
Tallet kalles indeksen, og det er den som teller hvilket tidspunkt vi står i. I koden svarer til t[i].
Å erstatte kontinuerlig tid med et slikt rutenett kalles å diskretisere. Ordet er ikke mer mystisk enn «å dele opp i skiver» — og det er hele grunnideen bak numerisk løsning av en differensiallikning.
Tidsavstanden mellom to nabotidspunkt i rutenettet, målt i sekunder.
Steglengden er den ene knappen du kan skru på i en numerisk beregning. Liten gir et tettere rutenett og et mer nøyaktig svar, men flere steg og lengre regnetid. Stor går fort, men svaret kan bli ubrukelig.
En brukbar tommelfingerregel for svingninger og kast er at skal være et par tusen ganger mindre enn den karakteristiske tiden i problemet — svingeperioden, falltiden eller tidskonstanten. Har systemet en periode på ett sekund, er et trygt valg.
Sammenhengen mellom antall punkt og sluttiden er : velger du to av de tre størrelsene, er den tredje låst.
Tabeller som opprettes med full lengde før løkka starter, slik at hvert tidspunkt har sin ferdige plass å skrive svaret sitt inn i.
t = np.zeros(N)
x = np.zeros(N)
v = np.zeros(N)np.zeros(N) lager en tabell med nuller. Etter løkka inneholder x posisjonen ved hvert av de tidspunktene, og du kan lese ut, plotte eller lete i hele forløpet.
Hvorfor gjøre det på forhånd? Fordi løkka da bare skal fylle inn, ikke utvide. Det er raskere, og — viktigere for eksamen — det tvinger fram indeksskrivemåten x[i], som er nettopp det sensor ser etter.
x[0] = 0.100 # m
v[0] = 0.0 # m/sHer ligger ett av de fem poengene i en typisk kodedeloppgave. Det er også det billigste poenget i hele oppgaven: to linjer, og de kan skrives selv om du står helt fast på resten.
Intuisjon: differensiallikningen er loven som styrer bevegelsen. Initialbetingelsene er den ene bevegelsen loven faktisk beskriver. Uten dem har koden ingenting å begynne med.
Forklar med egne ord, i to–tre setninger hver:
a) hva som er forskjellen på en analytisk og en numerisk løsning av en bevegelseslikning,
b) hva np.zeros(N) gjør, og hvorfor tabellene lages før løkka starter,
c) hvorfor en andreordens bevegelseslikning trenger nøyaktig to initialbetingelser i koden.
Løkke 2 — akselerasjonslinja (~14 min)
Nå kommer den delen som gir flest poeng. Av de fem poengene i en typisk kodedeloppgave ligger tre i én eneste linje: uttrykket for akselerasjonen.
Grunnen er enkel. Akselerasjonslinja er det eneste stedet i koden der fysikken i akkurat ditt problem står. Resten av løkka er den samme uansett om du modellerer en fjær, en pendel, et kast eller en komet.
Alt på høyresiden må være noe koden allerede kjenner: konstantene (, , , ) og tilstanden i indeks (x[i] og v[i]).
Dette er de tre poengene. En akselerasjonslinje med riktig fortegn, riktige krefter og riktig masse-deling er selve fysikken i deloppgaven — resten av løkka er mal.
Intuisjon: dette er det samme steget som i kap. 7.1. Koden gjør ikke fysikken for deg.
Steg 2 — isolér den høyeste deriverte. Del på massen, slik at står alene.
Intuisjon: maskinen kan bare oppdatere det den får servert direkte. En likning der akselerasjonen er blandet inn i et større uttrykk, kan ikke oversettes linje for linje.
Steg 3 — bytt symbol med indeks. Alt som er , blir x[i]. Alt som er , blir v[i]. Konstantene beholder navnene sine.
Intuisjon: indeksen sier «slik ser høyresiden ut akkurat nå», og det er det eneste maskinen kan vite i det øyeblikket.
Steg 4 — sett akselerasjonen inn i løkka, oppdater farten, og deretter posisjonen.
Intuisjon: likningen forteller hvordan tilstanden endrer seg. Løkka gjør endringen om til en ny tilstand.
Tre eksempler på steg 1–3:
| Bevegelseslikning | Akselerasjonslinje |
|---|---|
a = -(k / m) * x[i] | |
a = g - (kv / m) * v[i] | |
a = -(g / L) * np.sin(theta[i]) |
Legg merke til at massen faller ut i den siste — men det er noe du ser etter å ha delt, ikke noe du antar på forhånd.
En vogn med masse ruller uten friksjon på en luftputebane og er festet til en fjær med fjærkonstant . Ved trekkes vogna ut fra likevekt og slippes fra ro.
a) Sett opp bevegelseslikningen og akselerasjonslinja.
b) Skriv en fullstendig kode som løser likningen numerisk over 20 sekunder, og kjør den.
c) Kontroller resultatet mot den analytiske løsningen fra kap. 7.2.
a) Vogna er ett legeme. Tyngden og normalkraften er loddrette og opphever hverandre, så fjærkraften er den eneste vannrette kraften:
Akselerasjonslinja blir dermed a = -(k / m) * x[i].
b) Vi velger . Svingeperioden er , så steglengden er om lag 1 300 ganger mindre enn perioden — godt innenfor tommelfingerregelen. Med punkt blir sluttiden , altså snaut 16 svingninger.
import numpy as np
m = 1.00 # kg
k = 25.0 # N/m
N = 20001 # antall tidspunkt
dt = 0.0010 # s
t = np.zeros(N)
x = np.zeros(N)
v = np.zeros(N)
x[0] = 0.100 # m, utslag ved t = 0
v[0] = 0.0 # m/s, sluppet fra ro
for i in range(N - 1):
a = -(k / m) * x[i]
v[i + 1] = v[i] + a * dt
x[i + 1] = x[i] + v[i + 1] * dt
t[i + 1] = t[i] + dt
print("sluttid ", round(t[-1], 3))
print("x ved slutt ", round(x[-1], 5))
print("v ved slutt ", round(v[-1], 5))
print("storste utslag ", round(np.max(np.abs(x)), 7))Utskrift:
sluttid 20.0
x ved slutt 0.08636
v ved slutt 0.25314
storste utslag 0.1000003c) Den analytiske løsningen er med , altså
Koden gir . Avviket er , altså av amplituden — etter nesten seksten svingninger.
Legg merke til hva slags feil det er. Det største utslaget er mot eksakt : amplituden er praktisk talt uendret. Hele avviket er en liten faseforskyvning — den numeriske svingningen går et ubetydelig lite hakk i utakt med den eksakte. Det er nøyaktig den oppførselen som gjør Euler–Cromer brukbar over lange tider, og vi kommer tilbake til den i løkke 4.
Sensorblikk: oppgaveteksten på eksamen ber om «en kode» eller «pseudokode», ikke om et kjørbart program. De fem poengene sitter i x[0] og v[0], i akselerasjonslinja, og i de to oppdateringslinjene i riktig rekkefølge. Import-linja og print gir ingen poeng — men de koster heller ingenting.
Skriv akselerasjonslinja i kode for hver av bevegelseslikningene. Bruk variabelnavnene som står i parentes, og anta at tilstanden i tidspunkt heter x[i] og v[i].
a) (variabler m, k, g)
b) (variabler m, g, kv)
c) , med tiden tilgjengelig som t[i] (variabler m, g, F0, w)
d) Hvilken av de tre linjene er den eneste der massen ikke faller ut? Hva betyr det praktisk?
Løkke 3 — selve løkka, og den ene indeksen som avgjør alt (~16 min)
Nå står akselerasjonen der. Spørsmålet er hvordan vi kommer fra tilstanden i tidspunkt til tilstanden i tidspunkt .
Ideen er den enkleste tenkelige. Over et lite tidssteg er akselerasjonen omtrent konstant, så farten endrer seg med . Og over det samme steget er farten omtrent konstant, så posisjonen endrer seg med :
Og så kommer spørsmålet som hele dette kapitlet handler om: hvilken skal stå i den andre linja — den gamle , eller den nye ?
Svaret virker som en detalj. Det er det ikke.
I kode:
v[i+1] = v[i] + a*dt
x[i+1] = x[i] + v[i+1]*dtMetoden er oppkalt etter Alar Cromer, som beskrev den i 1981 som en «forbløffende enkel» rettelse av standardmetoden for mekanikk-simuleringer.
Dette er metoden dette emnet bygger på, og den sensor forventer. Grunnen er at den holder energien i sjakk over lange tider — se løkke 4.
I kode:
x[i+1] = x[i] + v[i]*dt
v[i+1] = v[i] + a*dtMetoden er den mest opplagte oversettelsen av differensiallikningen, og den brukes mye i andre sammenhenger. For svingninger og baner er den systematisk dårlig: den tilfører energi til systemet steg for steg, slik at amplituden vokser og banene spiraler utover.
Legg merke til at forskjellen fra Euler–Cromer er én indeks. Bytter du rekkefølgen på de to linjene uten å endre indeksene, har du byttet metode.
Kravet om at hver størrelse i løkka skal skrives med den indeksen som sier hvilket tidspunkt den hører til: v[i], v[i+1], x[i], x[i+1].
Skriver du v = v + a*dt uten indeks, forsvinner nettopp den opplysningen løkka handler om. På eksamen koster det typisk 2 poeng, selv når meningen er åpenbar for en leser — og i en kode som faktisk skal kjøre, ødelegger det lagringen av forløpet, siden bare den siste verdien overlever.
Unntaket er akselerasjonen. a regnes ut på nytt i hvert eneste gjennomløp og brukes umiddelbart, så den trenger ikke lagres. Vil du likevel ha den som array, skriver du a[i] — det er også riktig, bare mer arbeid for hånd.
v uten indeks i integrasjonsløkka. Koster typisk 2 poeng. Riktig form er v[i+1] = v[i] + a*dt. Dette er den enkeltfeilen sensorveiledningene i H2023, V2024 og V2025 påpeker oftest i kodedeloppgavene.Gammel fart i posisjonsoppdateringen. Skriver du x[i+1] = x[i] + v[i]*dt, har du byttet til Forward Euler uten å mene det. Koden kjører, tallene ser plausible ut i noen få steg, og amplituden vokser sakte. Feilen er usynlig i én periode og ødeleggende i femti.
Glemte initialbetingelser. Uten x[0] og v[0] starter alt i null, og en fjær som starter i likevekt uten fart, blir stående i ro for alltid. Koden kjører feilfritt og gir bare nuller — den mest lumske av alle utfall, fordi ingenting krasjer.
range(N) i stedet for range(N - 1). Siste gjennomløp prøver da å skrive til x[N], som ikke finnes, og programmet stopper med en indeksfeil. På papiret straffes det ikke, men det er et unødvendig signal om at løkka ikke er tenkt igjennom.
Feil fortegn i akselerasjonslinja. Fjærkraften er , ikke . Med feil fortegn får du en likning som beskriver en kloss som skyves lenger og lenger vekk fra likevekt, og posisjonen eksploderer i løpet av få steg. En løsning som vokser uten grense der du ventet en svingning, er nesten alltid et tapt minustegn.
Å ikke begrunne metodevalget. De tre sensorveiledningene skiller eksplisitt mellom en kandidat som skriver riktig løkke og en som skriver riktig løkke og sier hvorfor Euler–Cromer er valgt. Det er to setninger, og de er blant de billigste poengene i settet.
En medstudent har skrevet denne løkka for fjærpendelen i eksempel 1. Den kjører uten feilmelding, men gir gale svar.
N = 20001
dt = 0.0010
x = np.zeros(N)
v = np.zeros(N)
for i in range(N - 1):
a = (k / m) * x[i]
x[i + 1] = x[i] + v[i] * dt
v = v[i] + a * dta) Finn de tre feilene, og si for hver av dem hva den gjør med resultatet.
b) Hvorfor gir koden bare nuller uansett, slik den står?
c) Skriv den rettede løkka.
Løkke 4 — hvorfor Euler–Cromer, og hvorfor det er verdt poeng (~14 min)
Begge metodene gjør en feil i hvert steg, og feilen er like stor i begge. Forskjellen ligger i hvordan feilene legger seg sammen over tid.
Tenk på en svingende fjær. Halve tiden går klossen utover, halve tiden innover.
- Euler–Cromer bruker den nye farten i posisjonsoppdateringen. Den overvurderer forflytningen i noen deler av svingningen og undervurderer den i andre — den tar av og til for mye og av og til for lite. Over en hel periode kansellerer bidragene hverandre nesten fullstendig, og energien vandrer bare litt fram og tilbake rundt riktig verdi.
- Forward Euler bruker den gamle farten. På vei utover er den gamle farten større enn gjennomsnittsfarten i steget, så klossen flyttes for langt. På vei innover er den gamle farten også større i tallverdi, så klossen flyttes for langt inn — men fjæren rekker å presse hardere. Nettoeffekten er systematisk: energien vokser i hvert eneste steg.
Intuisjon: Euler–Cromer gjør en feil som svinger; Forward Euler gjør en feil som drar. Det er drivingen som ødelegger, ikke størrelsen på enkeltfeilen.
At den beregnede mekaniske energien i et system endrer seg systematisk gjennom simuleringen, selv om den fysisk skal være bevart.
Energidrift er en metodefeil, ikke fysikk. Symptomene er lette å kjenne igjen:
- en oscillator der amplituden vokser jevnt periode for periode;
- en planet- eller kometbane som spiraler utover i stedet for å lukke seg;
- en pendel som svinger høyere og høyere uten at noe tilfører den energi.
Forward Euler har energidrift oppover for svingninger og baner. Euler–Cromer har det ikke: energien svinger rundt riktig verdi uten å vandre av gårde. Det er derfor metoden er standard i mekanikk-simuleringer, og det er nettopp dette du skal kunne si i de to setningene som begrunner metodevalget.
Kjør fjærpendelen fra eksempel 1 med begge metodene i 20 svingeperioder, med samme steglengde . Sammenlikn amplituden og den mekaniske energien til slutt.
Den mekaniske energien er , og amplituden kan leses ut av den: .
Perioden er , så 20 perioder er , altså punkt med .
import numpy as np
m = 1.00
k = 25.0
dt = 0.0010
N = 25133 # 20 perioder
for metode in ["Euler-Cromer", "Forward Euler"]:
x = np.zeros(N)
v = np.zeros(N)
x[0] = 0.100
for i in range(N - 1):
a = -(k / m) * x[i]
if metode == "Euler-Cromer":
v[i + 1] = v[i] + a * dt
x[i + 1] = x[i] + v[i + 1] * dt
else:
x[i + 1] = x[i] + v[i] * dt
v[i + 1] = v[i] + a * dt
E = 0.5 * m * v**2 + 0.5 * k * x**2
print(metode, " amplitude:", round(np.sqrt(2 * E[-1] / k), 6),
" E/E0:", round(E[-1] / E[0], 6))Utskrift:
Euler-Cromer amplitude: 0.100001 E/E0: 1.000018
Forward Euler amplitude: 0.136909 E/E0: 1.874407Tolkning. Euler–Cromer har en amplitude på mot eksakt , og energien er for høy — altså praktisk talt bevart. Forward Euler har en amplitude på , som er for stor, og en energi som er for høy. Systemet har fått nesten dobbelt så mye energi som det startet med, av ingenting.
Poenget er ikke at Forward Euler er unøyaktig — begge metodene har feil av samme størrelsesorden i ett enkelt steg. Poenget er at Euler–Cromers feil svinger rundt null mens Forward Eulers feil peker samme vei hver gang. Etter 25 000 steg er forskjellen mellom en feil som kansellerer og en som akkumulerer, forskjellen mellom et brukbart og et ubrukelig svar.
Kontroll av rimeligheten: amplitudeveksten hos Forward Euler kan anslås. Energien vokser med om lag en faktor per steg, altså . Over steg gir det — nøyaktig det utskriften viser. At et anslag treffer på to desimaler, er den beste kontrollen du kan få på at koden gjør det du tror.
a) En medstudent sier: «Forward Euler og Euler–Cromer er like nøyaktige, siden begge er førsteordens metoder. Forskjellen betyr ingenting i praksis.» Er påstanden riktig? Begrunn.
b) Du simulerer en pendel og ser at utslaget vokser sakte gjennom hele simuleringen. Nevn to mulige forklaringer, og si hvordan du skiller dem fra hverandre.
c) Formuler de to setningene du ville skrevet på eksamen for å begrunne metodevalget.
Løkke 5 — kontroll av et numerisk svar (~14 min)
En kode som kjører, er ikke en kode som er riktig. Den kan gi et helt korrekt svar på et annet problem enn det du stilte — som i oppgave 3, der de manglende initialbetingelsene ga en perfekt beregnet nulløsning.
Det finnes to kontroller som til sammen fanger nesten alt, og begge tar under et minutt.
Et spesialtilfelle av det samme problemet der du kjenner svaret fra en formel, og som du kjører koden på før du stoler på den.
For en kode som skal håndtere en fjær med luftmotstand, er kontrollcaset å sette motstanden til null: da må koden gi med . For en kode som skal håndtere et kast med drag, er kontrollcaset : da må rekkevidden bli .
Regelen er enkel: slå av det leddet som gjør problemet vanskelig, og sjekk at koden gjenskaper det du kan regne ut for hånd. Gjør den ikke det, er feilen i infrastrukturen — og da hjelper det ikke å finpusse på det vanskelige leddet.
Å kjøre den samme koden på nytt med halvert steglengde og se om svaret endrer seg vesentlig.
Endrer svaret seg lite, er liten nok. Endrer det seg mye, er den ikke det — og da forteller ingen enkeltkjøring deg hva som er riktig.
Testen skiller også metodefeil fra modellfeil: en feil som skyldes for grov diskretisering, krymper når krymper. En feil som ligger i fysikken — et tapt kraftledd, et galt fortegn, en feil initialbetingelse — står helt uendret.
Dette er den mest undervurderte kontrollen som finnes, og den er verdt en setning i en besvarelse selv når du ikke har en maskin å kjøre på: «steglengden bør kontrolleres ved å halvere og se at svaret er stabilt».
En metode der feilen i sluttsvaret er tilnærmet proporsjonal med steglengden: halverer du , halveres feilen.
Både Euler–Cromer og Forward Euler er førsteordens i denne forstand. For fjærpendelen i eksempel 1, målt mot den analytiske løsningen ved :
| avvik i | |
|---|---|
Ti ganger mindre steg gir om lag ti ganger mindre feil — akkurat som en førsteordens metode skal. Dette er også den enkleste måten å bevise at et avvik er en diskretiseringsfeil og ikke en modellfeil.
a) Forklar hvorfor denne likningen ikke kan løses analytisk, og hva småvinkeltilnærmingen fra kap. 7.2 gjør med den.
b) Skisser en Euler–Cromer-kode som løser den fulle likningen med startutslaget og null starthastighet. Begrunn metodevalget.
c) Kjør koden, og kontroller resultatet mot energibevaring.
d) Kjøringen gir en svingeperiode på . Sammenlikn med småvinkelformelen og kommenter.
a) Ulineariteten kommer av . Småvinkeltilnærmingen er førsteordensleddet i Taylor-rekka, for små i radianer, og den gjør likningen om til
som er den harmoniske oscillatoren med og perioden . Dette er en tilnærming, ikke en omskriving: den er god for små utslag og blir gradvis dårligere når utslaget vokser.
b) Vinkelen svarer til posisjonen og vinkelfarten til farten, så malen er den samme — bare med nye navn:
import numpy as np
g = 9.81
L = 0.800
N = 5001
dt = 0.0010
t = np.zeros(N)
theta = np.zeros(N)
omega = np.zeros(N)
theta[0] = 0.600 # rad, om lag 34 grader
omega[0] = 0.0
for i in range(N - 1):
a = -(g / L) * np.sin(theta[i])
omega[i + 1] = omega[i] + a * dt
theta[i + 1] = theta[i] + omega[i + 1] * dt
t[i + 1] = t[i] + dt
print("storste utslag ", round(np.max(np.abs(theta)), 4))
print("storste omega ", round(np.max(np.abs(omega)), 4))
print("omega fra energi", round(np.sqrt(2 * g / L * (1 - np.cos(0.600))), 4))Utskrift:
storste utslag 0.6
storste omega 2.0697
omega fra energi 2.0697Begrunnelse for metodevalget: pendelen er konservativ — bare tyngden gjør arbeid, og snordraget står vinkelrett på bevegelsen. Euler–Cromer oppdaterer farten først og bruker den oppdaterte farten i posisjonsoppdateringen, og feilen kansellerer derfor over hver periode. Forward Euler ville lagt til energi i hvert steg, og utslaget ville vokst gjennom simuleringen — som ville sett ut som fysikk, men vært en metodefeil.
c) To kontroller:
Amplitude. Det største utslaget er , altså nøyaktig startutslaget. En konservativ pendel som slippes fra ro, skal komme like høyt opp hver gang, og gjør det.
Energi. Energibevaring fra ytterstilling til bunnpunkt gir
Koden gir — samsvar på fire desimaler. Dette er en ekte kontroll, ikke en sirkelslutning: energibevaringen er et fysisk argument som ikke inngår i koden noe sted. At de to veiene lander på samme tall, betyr at både akselerasjonslinja og løkka er riktige.
d) Småvinkelformelen gir
Den fulle likningen gir , altså lengre. Perioden er ikke uavhengig av amplituden for en ekte pendel — den vokser med utslaget, fordi er mindre enn , slik at den gjenopprettende kraften er svakere enn den lineære modellen sier. Ved (om lag ) er avviket .
Sensorblikk: en deloppgave som ber om en kode, gir uttelling for løkka. En deloppgave som ber om en sammenlikning med den analytiske modellen, gir uttelling for tolkningen — og her er tolkningen at småvinkeltilnærmingen er god til noen få grader og systematisk for kort periode utover det. Å oppgi tallet uten den setningen er å la poeng ligge.
— naturlig pausepunkt —
En kloss med masse ligger på et vannrett, friksjonsfritt bord festet til en fjær med . Ved står klossen i likevekt og får et slag som gir den farten mot høyre.
a) Sett opp bevegelseslikningen og akselerasjonslinja.
b) Skriv initialbetingelsene i kode, og forklar hver av dem fysisk.
c) Hvilken ville du valgt, og hvorfor? Hvor mange punkt trengs for å dekke fem svingeperioder?
d) Uten å kjøre koden: hva blir det største utslaget? Bruk energibevaring, og forklar hvorfor dette er et godt kontrolltall for en kode.
a) Sett opp bevegelseslikningen, og skriv den på eksplisitt form med akselerasjonen isolert.
b) Skisser en Python-kode som løser likningen numerisk. Angi initialbetingelsene for en kule som slippes fra ro i , og skriv Euler–Cromer-løkka.
c) Begrunn i to setninger hvorfor du velger Euler–Cromer framfor Forward Euler her.
d) Hvordan ville du kontrollert at koden er riktig, uten å kjenne den analytiske løsningen av den fulle likningen?
e) Hva blir likevektsposisjonen, og hva skjer med den hvis luftmotstanden dobles?
En student simulerer den udempede fjærpendelen fra eksempel 1 og lurer på hvor liten må være.
a) Kjøringene med Euler–Cromer gir disse avvikene fra den analytiske løsningen ved : gir , gir , og gir . Hva slags sammenheng er dette, og hva forteller den?
b) Anslå hvilken som trengs for å komme under ved , og hvor mange steg det blir.
c) Studenten foreslår i stedet å kjøre med «siden det er tjue ganger mindre enn perioden». Vurder forslaget.
d) Hvorfor hjelper det ikke å redusere hvis akselerasjonslinja mangler et kraftledd?
a) Er begrunnelsen god nok? Hva mangler?
b) Ville argumentet vært annerledes hvis oppgaven gjaldt et legeme i fritt fall uten luftmotstand, over ett sekund? Begrunn.
c) Nevn én situasjon der Forward Euler og Euler–Cromer gir praktisk talt samme svar, og forklar hvorfor.
Begrepsbank
Begrepsbanken er flashcard- og repetisjonsstoff — den gjentar det du nettopp har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet gjelder kjernestoffet.
De to tallene som beskriver starttilstanden, skrevet inn i indeks 0 av tabellene:
x[0] = ... # hvor legemet er ved t = 0
v[0] = ... # hvor fort det gaar ved t = 0De er verdt 1 poeng i en typisk kodedeloppgave, og de er det eneste stedet i koden der opplysningene fra oppgaveteksten om starttilstanden dukker opp.
Den vanligste feilen er å sette begge til null av vane. «Slippes fra ro i utslaget » gir x[0] = A, v[0] = 0; «passerer likevekt med farten » gir x[0] = 0, v[0] = v0. Les setningen to ganger.
Med range(N) ville siste gjennomløp prøvd å skrive til x[N], som ikke finnes, og programmet stopper. På papiret straffes det ikke, men det er et unødvendig signal om at løkka ikke er tenkt igjennom.
Huskeregelen: antall steg er alltid én mindre enn antall punkt. Med punkt går det mellomrom.
En metode der den nye tilstanden regnes ut direkte fra den gamle, uten at man må løse en likning underveis.
Både Euler–Cromer og Forward Euler er eksplisitte: høyresiden inneholder bare størrelser du allerede kjenner, og oppdateringen er ren innsetting.
Alternativet er implisitte metoder, der den nye tilstanden står på begge sider og må løses ut. De er mer stabile for enkelte problemer, men langt tyngre å skrive for hånd, og de er ikke pensum i dette emnet.
Å se koblingen mellom de to formene er selve broa fra kap. 7.1 til dette kapitlet: hver førsteordens likning i tilstandsformen blir én oppdateringslinje.
Kode skrevet for å bli lest av et menneske, ikke kjørt av en maskin: riktig struktur og riktige uttrykk, men uten krav om at hvert komma sitter.
På eksamen er dette formen som forventes. Syntaksfeil straffes ikke, alle programmeringsspråk godtas, og du skriver ikke et helt program — bare initialbetingelser og løkke.
Det som likevel må være presist, er indeksene og rekkefølgen: v[i+1] før x[i+1], og den oppdaterte farten i posisjonslinja. Der er pseudokode like streng som ekte kode.
Feilen som oppstår i ett enkelt tidssteg, fordi vi behandler akselerasjonen som konstant gjennom steget mens den i virkeligheten endrer seg.
Feilen kommer av at vi kutter Taylor-rekka for posisjonen etter førsteordensleddet: det neste leddet er , og det er størrelsesordenen på feilen per steg.
Feilen per steg går altså som , mens den samlede feilen etter steg går som . Det er nettopp derfor metodene kalles førsteordens, selv om enkeltsteget er andreordens nøyaktig.
Velger du hvor lenge simuleringen skal vare og hvor fint du vil regne, er antall punkt bestemt. Vil du dekke fem svingeperioder à med , trenger du .
Den praktiske konsekvensen er at finere oppløsning koster proporsjonalt med regnetid: halverer du , dobles antall steg for samme sluttid.
Et krav om at løkka skal avsluttes når noe fysisk inntreffer, i stedet for etter et fast antall steg.
For et kast er det naturlige kriteriet at legemet treffer bakken:
if y[i+1] < 0:
breakAlternativet er å velge stort nok og lete opp nedslaget i etterkant. Begge deler godtas.
Vær oppmerksom på at et stoppkriterium alltid treffer litt for sent: løkka oppdager først at er blitt negativ, altså i steget etter nedslaget. Trenger du nedslagspunktet nøyaktig, interpolerer du mellom de to siste punktene.
Regelen om at alle tall som mates inn i koden, skal være i SI-enheter — meter, kilogram, sekund — og at svaret dermed også kommer i SI.
Koden regner uten å vite noe om enheter. Blander du og , eller og , kommer det ingen feilmelding: du får et pent tall som er galt med en faktor tusen.
Det praktiske grepet er å skrive enheten som kommentar bak hver konstant når du setter opp koden. Det tar to sekunder og fanger den ene feilen ingen kontroll ellers oppdager.
Skillet mellom størrelser som må lagres for hvert tidspunkt, og størrelser som bare brukes og kastes.
Lagres (egen array): posisjon, fart, tid — alt du vil kunne plotte, lete i eller lese av til slutt.
Kastes (vanlig variabel): akselerasjonen, farten regnet ut av komponentene, avstanden til sentrum. De regnes på nytt i hvert gjennomløp og trengs ikke etterpå.
Denne inndelingen forklarer hvorfor a skrives uten indeks mens v alltid har indeks — og det er verdt å si i en besvarelse, slik at den manglende indeksen på a ikke leses som slurv.
Kravet om at du skriver hvorfor du valgte Euler–Cromer, ikke bare at du gjorde det.
Sensorveiledningene i H2023, V2024 og V2025 trekker dette fram som et skille mot toppkarakter. En fullgod begrunnelse har to ledd: hva Euler–Cromer gjør (oppdaterer farten først og bruker den oppdaterte farten videre, slik at feilen kansellerer over en periode), og hva alternativet gjør galt (Forward Euler bruker den gamle farten og tilfører energi systematisk).
To setninger. De koster et halvt minutt og er blant de billigste poengene i hele settet.
Å regne ut én egenskap ved bevegelsen på en helt annen måte enn koden gjør, og sammenlikne.
De tre beste kontrollene i mekanikk er:
Energi. Er systemet konservativt, skal være konstant. Amplituder og maksfarter kan regnes ut av energibevaring uten å løse likningen.
Grensetilfelle. Slå av det vanskelige leddet og sammenlikn med den kjente løsningen.
Størrelsesorden. Er tallet fysisk rimelig? En pendel med sekundperiode, en ball som når tjue meter, en terminalfart på noen titalls meter per sekund.
Ingen av dem krever en maskin, og alle tre kan skrives inn i en håndskrevet besvarelse som en kontrollsetning.
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 den aktuelle utdanningsinstitusjonen. Dette er ikke offisielt studiemateriell. Les mer.