R


Fortran90 Programme Mandelbrotalgorithmus


Beispiel


Basiswissen


Das Programm erzeugt eine Bilddateie mit einem Mandelbrot-Fraktal. Die Zeilen die mit einem Ausfrufezeichen (!) beginnen sind reine Kommentarzeilen.

Quellcode


! Stand: 27. Oktober 2017
! Autor: Gunter Heim

! Was macht das Programm?

! Es wird ein Mandelbrotbild erzeugt.
! Die Bilddatei heißt mandelbrot.pgm
! Sie liegt im selben Verzeichnis in der die ausgeführte Fortran-Datei läuft.

! Wie startet das Programm?

! Den Textinhalt dieser Seite speichern als Datei mandelbrotbild.f90
! Das Programm muss erst kompiliert werden.
! Dazu benötigt man ein Kompilier-Programm (Compiler).
! Ein möglicher Compiler für Linux ist gfortran.
! Unter Ubuntu eingeben: gfortran mandelbrotbild.f90
! Der Compiler erzeugt dann einen neue Datei: a.out
! a.out ist die ausführbare Datei. Aufrufen mit: ./a.out
! a.out erzeugt dann eine Bilddatei: mandelbrot.pgm
! Diese Bilddatei mit einem gängigen Viewer (z. B. Ristretto) ansehen.

! In welchem Format liegt das Bild vor?

! Das Bild wird in einem portable greymap-Format erzeugt.
! Die übliche Dateiendung ist .pgm.
! Das Format wird von den meisten Anzeige-Programmen (z. B. Gimp oder Ristretto-Viewer) erkannt.
! Die Bilddaten werden als Pixelgrafik in menschenlesbarer Form (ASCII) geschrieben.
! Achtung: die Bilddateien können sehr groß (Speichervolumen) werden.

! Nach welchem Algorithmus wird das Bild erzeugt?

! z und c seien komplexe Zahlen in der Gaußschen Zahlenebene.
! z und c werden hier in der kartesischen Form (a+bi) interpretiert.
! c sei eine beliebige komplexe Zahl mit a und b kleiner oder gleich 1.
! z sei immer (0,0).
! Für ein beliebiges c aus der Zahlenebene bildet man dann eine Folge:
! z wird abgebildet auf z*z+c und das wiederum auf z.
! Es werden t Schritte dieser Folge berechnet.
! Es wird dann der Betrag von z berechnet.
! Bleibt |z| unterhalb der Schranke s, wird ein schwarzer Punkt gezeichnet.
! Bleibt |z| nicht unterhalb von s, wird ein weißer Punkt gezeichnet.
! Dieser Algorithmus ist beschrieben in dem Buch "Computerdenken" von ...
! Roger Penrose, siehe das Kapitel zu "Tor Bled Nam".

program mandelbrot

! Variablendeklarationen

integer :: graphsizex ! Bildbreite in Pixeln
integer :: graphsizey ! Bildhöhe in Pixeln
integer :: x ! Aktueller x-Wert in Pixeln
integer :: y ! Aktueller y-Wert in Pixeln
integer :: i ! Zählvariable für Schleife
integer :: t ! Algorithmische Tiefe
logical :: l ! Folge beschränkt true/false
real :: r ! Rechtswert: aktueller x-Wert normiert auf 1
real :: h ! Hochwert: aktueller y-Wert normiert auf 1
real :: s ! Obere Schranke Mandelbrotalgorithmus
real :: a ! Realteil der temporären komplexen Zahl innerhalb des Mandelbrotalgorithmus
real :: b ! Imaginärteil der temporären komplexen Zahl innerhalb des Mandelbrotalgorithmus
real :: c ! Realteil der temporären komplexen Zahl innerhalb des Mandelbrotalgorithmus
real :: d ! Imaginärteil der temporären komplexen Zahl innerhalb des Mandelbrotalgorithmus
real :: xmin ! Linker Rand des Berechnungsraumes
real :: xmax ! Rechter Rand des Berechnungsraumes
real :: ymin ! Unterer Rand des Berechnungsraumes
real :: ymax ! Oberer Rand des Berechnungsraumes
real :: mr ! Steigung der x ⭢ r-Zuordnung
real :: mh ! Steigung der y ⭢ h-Zuordnung

! Vorgegebene Berechnungsparameter

s=2 ! liefert gute Bilder, aber auch Werte wie 1 oder 5 gehen
t=50 ! liefert gute Bilder, aber auch Werte ab 4 liefern schon gute Bilder
graphsizex=400 ! Breite des Ausgabebildes im pmg-Format
graphsizey=400 ! Höhe des Ausgabebildes im pmg-Format

! Parameter werden eingelesen

write (*,*) "xmin xmax ymin ymax"
read (*,*) xmin, xmax, ymin, ymax

! Gute Ergebnisse geben zum Beispiel die folgenden Werte:
! xmin = -2
! xmax = 1
! ymin =-1.5
! ymax = 1.5
! Besten Dank dafür an Remo Siegenthaler

! Jetzt wird die Ausgabe-Bilddatei erzeugt bzw. geöffnet.
open (UNIT=1,FILE="mandelbrot.pgm",FORM="Formatted",STATUS="Replace",ACTION="Write")
100 Format (A) ! Kopfzeilen der Bilddatei als bloßer Text
150 Format (I4) ! Pixelbreite und Höhe des Bildes
200 Format (I2) ! Pixelgrauwert als Integer und zwei Zeichen breit
write (UNIT=1,FMT=100) "P2" ! Erste Kopfzeile der pgm-Datei: ASCII-Kodierung
write (UNIT=1,FMT=150) graphsizex ! Pixelbreite des Bildes
write (UNIT=1,FMT=150) graphsizey ! Pixelhöhe des Bildes
write (UNIT=1,FMT=100) "1" ! Hellste Graustufe (entspricht Farbe weiß)

! Wie funktioniert die Berechnung?

! Das Programm berechnet zeilenweise von oben nach unten und von
! links nach rechts, ob ein Pixel im Bild schwarz oder weiß wird.
! Die Pixelkoordinaten sind natürliche Zahlen im Bereich 1 bis graphsize.
! Jedem Pixel wird zur Berechnung ein reeller Wert des Berechnungsrechteckes zugeordnet.
! Das Berechnungsrechteck geht von links nach rechts von xmin bis xmax und es geht
! von unten nach oben von ymin bis ymax. Die Schrittweite sind reelle Zahlen.

! Durch diese Zuordnung entsteht aus den Pixelkoordinaten gedanklich eine komplexe Zahl c.
! Die komplexe Zahl c liegt immer innerhalb des Berechnungsrechteckes.
! Die komplexe Zahl c hat die Form (r+hi), mit r als Real- und h als Imaginäranteil.

! Auf diese komplexe Zahl c wird dann ein einfacher Mandelbrotalgorithmus angewandet.

do y=graphsizey,1,-1
do x=1,graphsizex,1

! z in der Form (x,y) ist jetzt eine komplexe Zahl in der Gaußschen Zahlenebene.
! Es wird jetzt überprüft, ob z nach t Mandelbrottransformationen beschränkt bleibt.
! Es gilt die Mandelbrotfolge z ⭢ z²+c, mit z=(0,0) und c=normierten Bildkoordinaten.
! Als Beschränkungkriterium gilt: Der Betrag von z muss kleiner als s bleiben.

mr=(xmax-xmin)/(graphsizex-1)
mh=(ymax-ymin)/(graphsizey-1)
r=mr*x+(xmin-mr)
h=mh*y+(ymin-mh)

a=0.0
b=0.0

do i=1,t,1 ! Anzahl Schritte gleich Berechnungstiefe t

c=a*a-b*b+r
d=2*a*b+h
a=c
b=d

if (a>10000) exit
if (b>10000) exit

end do

! Jetzt wird geprüft, ob der Betrag des letzten berechneten Elementes der Folge die obere Schranke s überschreitet.
! Ein Überschreiten der oberen Schranke würde als unbeschränkte Folgenentwicklung interpretiert.
! Falls ja, wird das Logik-Flag l auf .true. gesetzt, ansonsten bleibt es auf .false.

l=.false.
if (sqrt(a*a+b*b) < s ) l=.true.

! Jetzt wird das Ergebnis in die Bilddatei geschrieben:
if (l .eqv. .true.) write (UNIT=1,FMT=200,ADVANCE='no') 0
if (l .eqv. .false.) write (UNIT=1,FMT=200,ADVANCE='no') 1

end do
end do

close (UNIT=1) ! Schließen der Bilddatei

end program mandelbrot