In Fortran kunnen we functies gebruiken om specifieke berekeningen uit te voeren, wat essentieel is voor numerieke analyses. Functies kunnen één, twee of meerdere variabelen bevatten, afhankelijk van de complexiteit van de berekening die we willen uitvoeren. Dit hoofdstuk biedt een gedetailleerd overzicht van hoe functies werken in Fortran, hoe we ze kunnen toepassen, en wat er belangrijk is om te begrijpen bij het gebruik van verschillende soorten functies.

Een functie kan bijvoorbeeld gedefinieerd worden voor twee variabelen, zoals f1(x,y) = x^2 + y^2 + 2xy^2 en f2(x,y) = x^2 - y^2. In een Fortran-programma kunnen we deze functies eenvoudig aanroepen door de waarden van de variabelen in te voeren. Het volgende voorbeeld laat zien hoe we de waarden van deze functies kunnen berekenen:

fortran
write(*,*) 'Input x,y' read (*,*) x, y pf1 = f1(x, y + 2) pf2 = f2(x + y, 5) pf3 = f1(4.53, x - y) write(*,*) 'x,y,pf1,pf2,pf3,(pf1+pf2)/pf3'

In dit voorbeeld lezen we de waarden van x en y in en berekenen we de functies f1 en f2 voor verschillende argumenten. We combineren ook de resultaten van de functies en tonen ze op het scherm. De uitvoer kan er als volgt uitzien:

1.2 1.5 43.0900002 -17.7099991 21.426302 1.18452549

Wanneer we werken met functies van meerdere variabelen, moeten we de volgorde van de argumenten correct aanroepen om verwarring te voorkomen. Dit is van toepassing wanneer we bijvoorbeeld met drie variabelen werken. Stel dat we een functie SUMS(x, y, z) hebben die de som van de variabelen berekent, dan kan deze als volgt worden aangeroepen:

fortran
AL = SUMS(A * A, B * B, C * C) BT = SUMS(7.0 * X, 8.0 * Y, -8.0) GM = 4.0 * X / SUMS(X * X, Y * Y, Z * Z)**3

De SUMS-functie wordt in dit geval gebruikt om de berekeningen voor verschillende sets van waarden uit te voeren. De waarde van de functie wordt vervolgens weergegeven in de uitvoer:

css
VALUES OF A,B,C,X,Y,Z
9. 8. 7. 6. 5. 4. VALUES OF AL,BT,GM 13.9283886 8.60232544 0.0355201811

Functies kunnen complexer worden, afhankelijk van de vereiste berekeningen. Wanneer meer dan één statement nodig is om een functie te definiëren, gebruiken we een subprogramma. Een functionele subroutine is een onafhankelijk programma-eenheid die een enkel resultaat terugstuurt naar het hoofdprogramma. Hier is een eenvoudig voorbeeld van een subprogramma om de vierde macht van verschillende variabelen te berekenen:

fortran
function FC(x) FC = x**4 return end

In het hoofdprogramma kan de functie FC meerdere keren worden aangeroepen om de vierde macht van verschillende waarden te berekenen, zoals:

fortran
x = 2
y = 3 z = 4 write(*,*) fc(x), fc(y), fc(z), fc(x + y)

De uitvoer zou eruit zien als:

markdown
16. 81. 256. 625.

Het is belangrijk te begrijpen dat in een functionele subroutine geen uitvoercommando's zoals write mogen worden gebruikt. Dit kan leiden tot runtime-fouten, zoals I/O-recursie, die optreden wanneer I/O-commando's binnen een functie worden uitgevoerd, wat niet is toegestaan. Dit wordt duidelijk in een voorbeeld waarin een schrijfcommando onterecht in de functie wordt geplaatst.

Het gebruik van functies in Fortran is dus niet alleen een manier om berekeningen te structureren, maar vereist ook zorgvuldige aandacht voor de manier waarop de gegevens worden doorgegeven en teruggegeven naar het hoofdprogramma. Het is essentieel om te begrijpen hoe functies worden aangeroepen en welke restricties er zijn bij het gebruik van subprogramma’s. Door deze regels en structuren te volgen, kunnen we efficiënt gebruik maken van de kracht van Fortran voor numerieke berekeningen, wat van groot belang is voor wetenschappelijke en technische toepassingen.

Daarnaast moet de lezer zich realiseren dat, hoewel Fortran nog steeds populair is voor numerieke toepassingen, de taal verschillende beperkingen kent die relevant zijn bij het werken met moderne berekeningen en methoden. Het is essentieel om de efficiëntie van de functies en de mogelijkheid om met grote hoeveelheden gegevens om te gaan goed te begrijpen, evenals de noodzaak om te zorgen voor een foutloze interactie tussen functies en het hoofdprogramma.

Hoe de oplossingen van niet-lineaire vergelijkingen met twee variabelen te vinden: Newton-Raphson en Iteratieve Methode

Het oplossen van niet-lineaire vergelijkingen met twee variabelen is een belangrijk probleem in de numerieke wiskunde, vooral in toepassingen waarbij nauwkeurigheid van cruciaal belang is, zoals in de natuur- en ingenieurswetenschappen. Er zijn verschillende methoden die worden gebruikt om dit soort systemen van vergelijkingen op te lossen, en in dit hoofdstuk bespreken we twee belangrijke technieken: de Newton-Raphson methode en de iteratieve methode.

De Newton-Raphson methode voor twee variabelen wordt vaak gebruikt vanwege zijn snelheid en efficiëntie in het vinden van nauwkeurige oplossingen. Deze methode is gebaseerd op het uitbreiden van de gegeven functies in een eerste orde Taylor-reeks rondom een benaderde oplossing. In een typisch geval moeten de gedeeltelijke afgeleiden van de functies ten opzichte van beide variabelen worden berekend, zodat de correcte iteraties kunnen worden uitgevoerd.

Bijvoorbeeld, voor het systeem:

f(x,y)=4xcos(y)+ysin(x)=0f(x, y) = 4x \cos(y) + y \sin(x) = 0
g(x,y)=x2sin(y)3ycos(x)+2=0g(x, y) = x^2 \sin(y) - 3y \cos(x) + 2 = 0

moeten de volgende afgeleiden worden berekend:

fx,fy,gx,gy\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}, \frac{\partial g}{\partial x}, \frac{\partial g}{\partial y}

De methodologie voor het toepassen van de Newton-Raphson methode is als volgt: we nemen een initiële benadering van de wortels, bijvoorbeeld x0x_0 en y0y_0, en berekenen de waarde van de functies en hun afgeleiden op deze punten. Vervolgens worden de correcties voor xx en yy (aangeduid als hh en kk) berekend door een systeem van lineaire vergelijkingen op te lossen, wat leidt tot nieuwe benaderingen voor de wortels x1x_1 en y1y_1.

Het proces wordt herhaald totdat de veranderingen in de waarden van xx en yy tussen twee opeenvolgende iteraties klein genoeg zijn, waardoor de oplossing als voldoende nauwkeurig wordt beschouwd. Het bovenstaande systeem van lineaire vergelijkingen kan efficiënt worden opgelost met behulp van de regels van Cramer, waarbij de definitie van de determinant DD en de berekeningen van hh en kk worden uitgevoerd om de nieuwe waarden van xx en yy te berekenen.

Een belangrijk kenmerk van de Newton-Raphson methode is dat deze snel convergeert, mits de initiële benaderingen x0x_0 en y0y_0 relatief dicht bij de werkelijke oplossingen liggen. Bij onjuiste initiële waarden kan de methode echter falen om te convergeren of zelfs divergeren.

In de onderstaande code wordt het Newton-Raphson proces geïllustreerd:

cpp
f(x, y) = 4 * x * cos(y) + y * sin(x)
g(x, y) = x * x * sin(y) - 3 * y * cos(x) + 2
...

De code voert iteraties uit om de waarden van xx en yy te verbeteren totdat de opgegeven nauwkeurigheid is bereikt.

Daarnaast kan er een andere oplossing worden verkregen door een iteratieve methode te gebruiken. In dit geval, voor het systeem:

f(x,y)=x+3log10(x)y2=0f(x, y) = x + 3 \log_{10}(x) - y^2 = 0
g(x,y)=2x2xy5x+1=0g(x, y) = 2x^2 - xy - 5x + 1 = 0

wordt de iteratieve formule afgeleid uit de oorspronkelijke vergelijkingen. De iteraties worden uitgevoerd totdat de verschillen tussen opeenvolgende iteraties kleiner worden dan een bepaalde drempelwaarde.

De iteratieve methode is vaak nuttig voor grotere systemen van niet-lineaire vergelijkingen, waarbij directe methoden zoals Newton-Raphson onpraktisch kunnen zijn. Hier zijn de iteratieve formules voor xx en yy gegeven:

y=x+3log10(x)y = \sqrt{x + 3 \log_{10}(x)}
x=x(y+5)12x = \sqrt{\frac{x(y + 5) - 1}{2}}

In dit geval wordt het proces voortgezet totdat beide variabelen geen significante verandering meer vertonen tussen opeenvolgende iteraties. Dit proces wordt gestopt zodra de vereiste nauwkeurigheid is bereikt.

Hoewel de Newton-Raphson methode vaak sneller convergeert, heeft de iteratieve methode het voordeel dat deze eenvoudiger te implementeren is en geen expliciete afgeleiden vereist, wat soms nuttig kan zijn voor complexe systemen. De keuze tussen de twee methoden hangt af van de specifieke eisen van het probleem, zoals de complexiteit van de vergelijkingen en de gewenste nauwkeurigheid.

Een bijkomend aspect dat belangrijk is voor de lezer om te begrijpen, is de aard van de oplossingen van niet-lineaire systemen. Niet-lineaire systemen kunnen meerdere oplossingen hebben, en de gekozen startwaarden kunnen de uitkomst van het iteratieproces aanzienlijk beïnvloeden. Daarom is het belangrijk om te overwegen welke startwaarden het beste zijn voor de convergentie naar de werkelijke oplossing en om te anticiperen op de mogelijkheid van meerdere wortels. In sommige gevallen is het zelfs nodig om verschillende sets van initiële gissingen te proberen om alle mogelijke oplossingen van het systeem te vinden.

Hoe kunnen we eigenwaarden en eigenvectoren van een matrix vinden door gebruik te maken van rotatiematrices?

Het vinden van eigenwaarden en eigenvectoren van een matrix is een fundamentele taak in lineaire algebra, vaak toegepast in verschillende wetenschappelijke en technische velden. Het proces kan een uitdaging zijn, vooral wanneer het gaat om grote matrices of matrices met complexe structuren. In deze context wordt een iteratief proces beschreven dat gebruik maakt van rotatiematrices om de matrix te diagonalizeren en daarmee de eigenwaarden en bijbehorende eigenvectoren te vinden.

Laten we een voorbeeldmatrix AA nemen:

A=(210141014)A = \begin{pmatrix} 2 & 1 & 0 \\ 1 & 4 & 1 \\ 0 & 1 & 4
\end{pmatrix}

Het doel is om de eigenwaarden en eigenvectoren van deze matrix te vinden door een reeks van rotaties toe te passen. Elke rotatie wordt uitgevoerd met een rotatiematrix, die de matrix AA op zo’n manier transformeert dat een van de elementen in de matrix genulleerd wordt, wat uiteindelijk leidt tot een diagonale matrix die de eigenwaarden bevat.

De eerste stap is het kiezen van een rotatiematrix RR die de elementen van de matrix AA transformeert. Na de eerste iteratie, waarbij een rotatiematrix wordt toegepast op AA, ontstaat een gewijzigde matrix B=ARB = A \cdot R. Dit proces wordt herhaald totdat de matrix diagonaal is, wat betekent dat alle off-diagonale elementen (de niet-hoofddiagonale elementen) gelijk aan nul zijn. De resulterende matrix bevat de eigenwaarden op de hoofddiagonaal.

Bij elke iteratie wordt de rotatiematrix zo aangepast dat het effect van de vorige transformaties behouden blijft en de matrix steeds dichter bij de diagonaalvorm komt. De eigenvectoren kunnen vervolgens worden afgelezen uit de opeenvolgende rotatiematrices.

In het beschreven voorbeeld komt na drie iteraties de matrix AA in een volkomen gedifferentieerde vorm, wat betekent dat de eigenwaarden van de matrix zijn gevonden. De waarden zijn:

λ1=1.518805,λ2=5.170086,λ3=3.311107\lambda_1 = 1.518805, \quad \lambda_2 = 5.170086, \quad \lambda_3 = 3.311107

De eigenvectoren worden geëxtraheerd uit de opeenvolgende rotatiematrices die de matrix transformeren. De corresponderende eigenvectoren zijn:

v1=(0.8876500.2331920.397113),v2=(0.4271320.7392390.520657),v3=(0.1721480.6317810.755789)v_1 = \begin{pmatrix} 0.887650 \\ 0.233192 \\ -0.397113 \end{pmatrix}, \quad v_2 = \begin{pmatrix} -0.427132 \\ 0.739239 \\ -0.520657 \end{pmatrix}, \quad v_3 = \begin{pmatrix} 0.172148 \\ 0.631781 \\ 0.755789 \end{pmatrix}

Dit proces kan verder worden aangepast voor verschillende matrixgroottes en formaten, afhankelijk van de specifieke eisen van de toepassing. Het iteratieve proces van rotaties is bijzonder nuttig bij grotere matrices, waar het direct oplossen voor eigenwaarden en eigenvectoren met klassieke methoden vaak inefficiënt is.

Wanneer we deze methode toepassen op matrices van grotere orde, zoals een 4×44 \times 4 of 5×55 \times 5 matrix, wordt het noodzakelijk om de rotatiematrices en hun product zorgvuldig te berekenen en het proces stap voor stap uit te voeren. Elk van deze stappen vereist precisie, omdat kleine fouten zich snel kunnen opstapelen in iteratieve processen.

Het iteratieve karakter van de methode maakt het mogelijk om zelfs in gevallen waar analytische oplossingen moeilijk te verkrijgen zijn, numerieke benaderingen te gebruiken om de benodigde informatie over de matrix te verkrijgen. Dit biedt een krachtig hulpmiddel voor toepassingen in de natuurkunde, engineering en computerwetenschappen, waar het werken met complexe matrices een veelvoorkomend probleem is.

Naast het begrip van de berekening van eigenwaarden en eigenvectoren, is het belangrijk om te beseffen dat het succes van deze methode afhankelijk is van de keuze van de initiële rotatiematrix en de kwaliteit van de numerieke berekeningen. Een slechte keuze van rotatiematrix kan leiden tot langzamere convergentie of zelfs falen in het proces. Ook moet men zich bewust zijn van de mogelijkheid van numerieke instabiliteit bij het werken met grote of slecht geconditioneerde matrices. Het begrijpen van de theoretische achtergrond van lineaire algebra en de specifieke eigenschappen van de matrix is daarom essentieel voor het juiste gebruik van dit algoritme in praktijksituaties.

Hoe de Runge-Kutta Methode Werkt bij Het Oplossen van Tweede Orde Differentiaalvergelijkingen

De Runge-Kutta methode is een krachtige numerieke techniek voor het oplossen van differentiaalvergelijkingen. In dit hoofdstuk wordt de toepassing van de Runge-Kutta methode besproken voor de oplossing van klassieke en fysische problemen, zoals de LC-circuit en de wet van afkoeling, waarbij we stuiten op tweede orde differentiaalvergelijkingen. Deze vergelijkingen worden in de praktijk vaak aangetroffen in situaties waar de verandering van een systeem afhankelijk is van zowel de snelheid als de versnelling.

Laten we de tweede orde differentiaalvergelijking voor een LC-circuit beschouwen. Dit systeem heeft de volgende algemene vorm:

d2qdt2+qLC=0\frac{d^2q}{dt^2} + \frac{q}{LC} = 0

waarbij qq de lading is, LL de inductantie en CC de capaciteit van het circuit. We starten met de beginvoorwaarden: bij t=0t = 0, is q=Q=CVq = Q = CV, de stroom i=0i = 0, en het faseverschil ϕ=0\phi = 0. De analytische oplossing van dit systeem is q=Qcos(ωt+ϕ)q = Q \cos(\omega t + \phi), met ω=1LC\omega = \frac{1}{\sqrt{LC}}. De tijdsperiode TT van het systeem is gelijk aan T=2πωT = \frac{2\pi}{\omega}.

In dit geval kan de Runge-Kutta methode gebruikt worden om de lading qq en de stroom ii op elk tijdstip tt numeriek te berekenen. In de praktijk wordt de Runge-Kutta methode vaak gebruikt om de dynamiek van systemen te simuleren wanneer analytische oplossingen moeilijk te verkrijgen zijn.

Bijvoorbeeld, voor het volgende circuit met V=300VV = 300 \, V, C=25μFC = 25 \, \mu F en L=10mHL = 10 \, mH, kunnen we de volgende parameters afleiden: Q=7.5×103CQ = 7.5 \times 10^{ -3} \, C, ω=2×103rad/s\omega = 2 \times 10^3 \, rad/s, en de frequentie f=318.31Hzf = 318.31 \, Hz, met een periode T=3.1msT = 3.1 \, ms. Dit kan vervolgens worden opgelost met behulp van de Runge-Kutta methode zoals geïllustreerd in het programma.

Door de numerieke oplossing van de differente vergelijking voor de stroom en lading over een reeks tijdstappen te berekenen, verkrijgen we de evolutie van het systeem. De stroom wordt gedreven door het spanningssignaal en vertoont een oscillerend gedrag, dat afhangt van de waarden van de inductantie en capaciteit van het circuit. De numerieke resultaten kunnen worden vergeleken met analytische oplossingen, en we vinden dat de numerieke waarden voor de lading exact overeenkomen met de analytische oplossing, hoewel er bij de stroom een klein verschil kan optreden door de betrokken berekening van zeer kleine hoeveelheden.

Een ander veelvoorkomend probleem waar de Runge-Kutta methode voor kan worden gebruikt, is de wet van afkoeling van Newton, die beschrijft hoe de temperatuur van een object verandert afhankelijk van het temperatuurverschil met de omgeving. De differentiaalvergelijking die deze wet volgt, heeft de vorm:

dTdt=k(TTa)\frac{dT}{dt} = -k (T - T_a)

waarbij TT de temperatuur van het object is, TaT_a de omgevingstemperatuur, en kk de koelconstante. De oplossing van deze vergelijking kan analytisch worden gegeven als:

T=Ta+(T0Ta)ektT = T_a + (T_0 - T_a) e^{ -kt}

Hieruit blijkt dat de temperatuur van het object asymptotisch nadert naar de omgevingstemperatuur naarmate de tijd verstrijkt.

Bijvoorbeeld, stel dat we een kopje thee hebben met een beginnende temperatuur van 100C100^\circ C, en na drie minuten is de temperatuur 50C50^\circ C. We kunnen de koelconstante kk afleiden uit de bekende waarden: k=0.3269min1k = 0.3269 \, \text{min}^{ -1}. Vervolgens kan de temperatuur na elke tijdstap worden berekend door de Runge-Kutta methode toe te passen, waarbij we numeriek de oplossing voor TT vergelijken met de analytische oplossing.

Dit probleem benadrukt hoe we met behulp van numerieke methoden de temperatuur van een object kunnen volgen over de tijd, waarbij de berekeningen zeer nauwkeurig kunnen worden uitgevoerd met de Runge-Kutta methode.

Ten slotte willen we het klassieke geval van beweging van een deeltje bespreken. De tweede orde differentiaalvergelijking die de versnelling aa van een deeltje beschrijft is:

d2xdt2=a\frac{d^2x}{dt^2} = a

waarbij vv de snelheid en xx de positie van het deeltje zijn. De analytische oplossing van de snelheid is v=u+atv = u + at, en voor de positie x=ut+12at2x = ut + \frac{1}{2} a t^2, waarbij uu de initiële snelheid is.

Door deze klassieke vergelijkingen van beweging numeriek op te lossen met de Runge-Kutta methode, kunnen we de snelheid vv en de positie xx van het deeltje op verschillende tijdstippen berekenen. Deze oplossing kan worden vergeleken met de analytische formules voor snelheid en positie om de nauwkeurigheid van de numerieke berekeningen te verifiëren.

De Runge-Kutta methode blijkt een uitstekende manier te zijn om dergelijke systemen op te lossen, vooral wanneer de analytische oplossing moeilijk te verkrijgen of niet beschikbaar is.

Het is belangrijk te begrijpen dat hoewel de numerieke oplossingen in veel gevallen zeer nauwkeurig kunnen zijn, er altijd een kans bestaat op numerieke fouten, vooral bij het werken met kleine tijdstappen. Het kiezen van een geschikte tijdstapgrootte is cruciaal voor de stabiliteit en nauwkeurigheid van de numerieke oplossing. Te grote stappen kunnen leiden tot onnauwkeurige resultaten, terwijl te kleine stappen de rekenkosten verhogen. Het is dus belangrijk om een evenwicht te vinden tussen rekensnelheid en nauwkeurigheid bij het toepassen van de Runge-Kutta methode.