import numpy as np from tqdm import tqdm #Kun for å få progress bar, fordi det ser kult ut import matplotlib.pyplot as plt # g(x) er det som står på høyre side av likningen når x' står alene på venstre side. def g(x): return -(1/x**2)*((np.e**(1/x))/((np.e**(1/x)-1)**2))*(x-100) #Siste tall (100) er T_k. #Vi definerer den derriverte av g(x) siden den brukes i noen av metodene. def gDeriv(x): return (g(x+0.0001)-g(x-0.0001))/0.0002 x0 = 1 # x(0) maxT = 10 #hvor stor definisjonsmengden til grafen vi skal plotte er steps = 10 #hvor mange skritt vi tar, høyere verdi = bedre resultat men saktere h = maxT/steps #Lengden av hvert skritt def eulersMethod(): x = [x0] #Lager en liste med y-verdier til grafen til x(t), første element er initialverdien x0 ts = [0] #lager en liste med x-verdier for n in tqdm(range(steps)): ts.append((n+1)*h) #Listen med x-verdier starter på 0, og for hver iterasjon legger vi på (n+1)*h, # slik at den ender opp som [0, 1h, 2h, 3h, 4h ... ] x.append(x[n] + h*g(x[n])) #Her bruker vi eulers eksplisitte metode til å finne hva neste x er, og legger # den til i lista som heter x. return ts, x #Her returneres de to listene slik at de kan plottes (se bunnen av koden) def eulerImplicitMethod(): x = [x0] ts = [0] for n in tqdm(range(steps)): ts.append(n*h+h) #Newtons metode #Her brukes newtons metode til å finne x_(n+1), ved å løse likningen x_(n+1) = x_n + h*g(x_(n+1)). #1: Skriv om likningen til 0 = -x_(n+1) + x_n + h*g(x_(n+1)), det som står på høyre side er nå f(x) funksjonen vi bruker i newtons metode. # altså, f(x) = -x_(n+1) + x_n + h*g(x_(n+1)) #2: Finn f'(x) ved å derrivere det over, da får vi f'(x) = h*g'(x_(n+1)) - 1 #3: Hvis vi nå setter inn f(x) og f'(x) i formelen for newtons metode, får vi at det man må gjøre hver # iterasjon er: x_(n+1) = x_(n+1) - (-x_(n+1) + x_n + h*g(x_(n+1))) / (h*g'(x_(n+1)) - 1) nextX = x[n] #Denne variabelen er x_(n+1) (det er ikke lov å bruke x_(n+1) som variabelnavn i python... ) for i in range(100): lastX = nextX #Dette er kun for å sjekke om newtons metode har konvergert nextX = nextX - ((-nextX+x[n]+h*g(nextX))/(h*gDeriv(nextX)-1)) #Her gjør vi iterasjonen if abs(nextX - lastX) < 0.000000001: break #Dersom den har konvergert avslutter vi loopen (for å ikke bruke unødvendig lang tid) x.append(nextX) #Nå når vi har funnet x_(n+1) med newtons metode legger vi den til i lista x return ts, x def trapesMethod(): x = [x0] ts = [0] for n in tqdm(range(steps)): ts.append(n*h+h) #Newtons Metode nextX = x[n] for i in range(100): lastX = nextX nextX = nextX - ((-nextX+x[n]+(h/2)*g(x[n])+(h/2)*g(nextX))/((h/2)*gDeriv(nextX)-1)) if abs(nextX - lastX) < 0.000000001: break x.append(nextX) return ts, x def heunsMethod(): x = [x0] ts = [0] for n in tqdm(range(steps)): ts.append(n*h+h) x.append(x[n] + (h/2)*(g(x[n]) + g(x[n] + h*g(x[n])))) return ts, x #Her plottes det en løsning med eulers metode xs, ys = heunsMethod() plt.plot(xs, ys, color="blue") #Her plottes det en løsning med trapesmetoden xs, ys = trapesMethod() plt.plot(xs, ys, color="red") #Her endrer vi steps til et veldig høyt tall og plotter løsning med heuns metode for å få en "fasit" på hvordan #grafen skal se ut, slik at vi kan se hvilken av eulers metode og trapesmetoden som er best. steps = 1000000 h = maxT/steps xs, ys = heunsMethod() plt.plot(xs, ys, color="green") plt.show()