Arbeiten mit Fortran in 2020: Einsatzgebiete
Fortran – die bewährte Programmiersprache für technische Anwendungen
von DI Dr. Christoph Hofer
Der Name Fortran setzt sich zusammen aus “FORmel TRANslator”und ist eine der ältesten Programmiersprachen. Für viele Softwareentwickler*innen ist sie der Archetyp für eine alte, behäbige, eingeschränkte und schwer zu verstehende Programmiersprache mit der man am besten nichts zu tun haben möchte. Für die alten Versionen von Fortran mag dieses Vorurteil wirklich wahr sein. Fortran hat sich in seiner langen Geschichte aber viel verändert, sodass in seiner “modernen” Variante (wie etwa Fortran 2003) die Sprache einen viel schlechteren Ruf hat als ihr zusteht. Der typische Use-Case für Fortran als Programmiersprache sind rechenintensive numerische Simulationen, wie etwa Wettervorhersagen, Strömungssimulationen, Stabilitätsberechnungen, uvm.
Inhalt
- Aus alt mach neu
- Compiler: Die Qual der Wahl
- Warum wird Fortran heutzutage noch eingesetzt?
- Integration von Fortran/C/Python
- Autor
Aus alt mach neu
Fortran gilt als die erste jemals realisierte höhere Programmiersprache und wurde in den Jahren 1954 – 1957 von IBM entwickelt (FORTRAN I). Der Umfang der Sprache war noch sehr eingeschränkt, zum Beispiel gab es nur Integer (Ganzzahlen) und Reals (Gleitkommazahlen) als Datentypen und noch keine Funktionen. In den folgenden Jahren wurden neue verbesserte und umfangreichere Fortran Versionen entwickelt (FORTRAN II, FORTRAN III, FORTAN 66). Das nächste große Update bekam Fortran im Jahr 1977 (FORTRAN 77). Durch neue Features in der Sprache wurde diese Version sehr populär und damit schnell zu “dem” Fortran. Auch heute noch ist, wenn über Fortran Code gesprochen wird, hauptsächlich FORTRAN 77 Code gemeint, was auch die vielen Vorurteile gegenüber der Sprache erklärt. Seitdem gab es noch einige Updates der Sprache, die sie an moderne Programmierkonzepte und Standards heranführen.
Große Meilensteine in der Entwicklung waren die Updates zu Fortran 90 und Fortran 2003, welche neben der Namensänderung (FORTRAN → Fortran) gängige Konzepte wie unter anderem freie Sourcefile Formate, Module, Operator Overloading, Derived data types, Pointers und objektorientiertes Programmieren zur Programmiersprache hinzufügten. Zusätzlich dazu gab es mit Fortran 95 und Fortran 2008 jeweils ein kleines Update der Sprache. Die aktuellste Version des Fortran Standards ist Fortran 2018, wobei noch kein Compilerhersteller alle Features unterstützt.
Info
Höhere Programmiersprachen und Compiler
Mikroprozessoren werden einer sogenannten Maschinensprache programmiert, also ein Binärcode der vom Mikroprozessor als Folge von Befehlen (Instructions) interpretretiert wird. Da diese Sprachen sehr von der verwendeten Hardware abhängen und das direkte Programmamieren in einer Maschinensprache sehr aufwändig ist, war die Entwicklung von höheren Programmiersprachen und Compilern ein großer Fortschritt. Höhrere Programmiersprachen verwenden mathematische Ausdrücke oder Ausdrücke die an eine natürliche Sprache (meist Englisch) angelehnt sind die mittels einem Compiler (und Linker) in Maschinensprache übersetzt werden. Höhere Programmiersprachen sind unabhäng von der Hardware, die Anpassung an die konkrete Hardware wird vom Compiler übernommen.
Operator Overloading
ist eine Programmiertechnik mit der die Bedeutung von Operatoren (wie etwa +, -, *, …) von den jeweiligen verwendeten Typen abhängt. Beispielsweise liefert 1 + 2 die Zahl 3, aber “Helllo ” + “World” den String “Hello World”.
Derived Data Type
erlauben es dem Benutzer selbst Datentypen aus bestehenden Typen zu definieren. Dies bietet somit die Möglichkeit für die Definition von logisch zusammengehörenden Daten in einem Typ und die Wiederverwednung derer in verschiedenen Teilen des Programms.
Pointer
ist ein Datentyp, der die Speicheradresse einer Variable speichert anstatt die Variable selbst. Pointer verweisen (referenzieren) sozusagen auf eine Speicheradresse, das Extrahieren des dahinterliegenden Wertes wird als Dereferenzierung bezeichnet. Im Unterschied zu Pointern in C/C++ besitzen Fortran Pointer noch weitere Informationen und erlauben auch auf nicht zusammenhangende Speicherbereiche (im Fall von Arrays) zu verweisen.
Objektorientiertes Programmieren
ist eine Programmierstil in dem Daten nicht nur in Derived Data Types gesammelt werden sondern zusammen mit Logik und Funktionalität in soganannten Objekten gekapselt. Jedes Objekt hat definierte Schnittstellen über jene es mit anderen Objekten interagieren kann, z.B. sind oft nicht alle Daten und Funktionen eines Objekts für andere Objekte sichtbar. Ziel ist es Codeduplikationen zu vermeiden um das Fehlerpotential und den Wartungaufwand zu verringern.
Compiler: die Qual der Wahl
Neben dem Umfang der Programmiersprache an sich ist für Programmierer*innen auch ein einfacher und angenehmer Workflow während der Entwicklung wichtig, heißt in welcher Entwicklungsumgebung kann man mit welchem Compiler den geschriebenen Code gut testen und debuggen. Die eingeschränkte Anzahl an verfügbaren Entwicklungsumgebungen verstärkt den Eindruck, dass Fortran heutzutage nicht mehr zu den gängigsten Sprachen gehört.
Um modernes Fortran zu programmieren (Fortran 2003/2008) hat man mehrere Compiler zur Auswahl, sowohl Open Source als auch kommerzielle, unter anderem
- Intel Fortran (ifort, kommerziell)
- NAG Fortran (kommerziell)
- GNU Fortran (gfortran,Open Source)
- Flang (ehemals “f18”, in Entwicklung, Open Source)
Hinsichtlich Entwicklungsumgebungen gibt es speziell für Fortran entwickelte IDEs, wie etwa den NAG Fortran Builder, oder auch Integrationen für bestehende IDEs, wie die Intel Integration für Visual Studio, oder Erweiterungen für Editoren, wie etwa Visual Studio Code. Neben den mitgelieferten Debuggern (gdb, idb,..) sind auch externe kommerzielle Debugger, wie Total View (https://totalview.io/) für Fortran erhältlich.
Warum wird Fortran heutzutage noch eingesetzt?
Legacy Code
Viele Fortran Systeme, die heute noch in Betrieb sind, wurden in den 1980er entwickelt. Zu dieser Zeit war Fortran die Sprache für wissenschaftliches Rechnen und numerische Simulationen. In solchen Programmen steckt sehr viel Wissen und Erfahrung, oftmals von mehreren Generationen von Ingenieur*innen und Wissenschafter*innen. Ein Übertragen in andere “moderne” Programmiersprachen ist oft viel zu aufwendig oder zu teuer und der Mehrwert für die Unternehmen wäre kaum gegeben. Ein Reengineering des Programmcodes in einem modernen Fortran Standard und das aktive Weiterentwickeln in diesem ist oftmals die bessere Alternative.
Fortran ist für technische Anwendungen konzipiert
Wie bereits zu Beginn des Artikels erwähnt sind numerische Simulationen der typische Use-Case für Fortran als Programmiersprache. Diese Bereiche zeichnen sich dadurch aus, dass einerseits effiziente Programmausführung wichtig ist, aber auch die Berechnungen durch mathematische Formeln beschrieben sind. Fortran gibt dem Programmierer die Möglichkeit diese Formeln in lesbarer Weise kompakt im Programmcode zu repräsentieren. Weiters ist die Sprache ausgelegt für effiziente Berechnungen, wodurch hoch performanter Code eher die Regel als die Ausnahme ist.
Fortran ist eine einfache Sprache
Verglichen mit C++ oder Skriptsprachen wie Python hat Fortran ein eher eingeschränktes Feature Set, weshalb für viele heutige Geschäftsanwendungen die Entwicklung sehr mühsam wäre, für technisch/naturwissenschaftliche Anwendungen ist sie aber sehr wohl passend. Das kleinere Feature Set erlaubt es auch, weniger erfahrenen Programmierer*innen gute Software zu entwickeln. Gerade durch die vielen Möglichkeiten von C++20 aber auch wie von Python sind weniger erfahrene Programmierer mit den Möglichkeiten oft überfordert. Falsch angewendet kreieren komplexere Sprachen oftmals mehr Verwirrung als sie zur Lösung des Problems beitragen. In diesem Sinne wurde Fortran für Wissenschafter*innen und Ingenieur*innen, nicht für Informatiker und Softwareentwickler konzipiert.
Integration Fortran/C/Python
Mit Fortran 2003 wurde mit dem Modul iso_c_binding neue Möglichkeit zur einfacheren Interaktion zwischen Fortran und C Code geschaffen. Dieses Modul inkludiert:
- Arten von primitiven Datentypen (Integer, Reals, …), die den entsprechenden C-Datentypen entsprechen (int, double, ..)
- Funktionen zum Arbeiten mit C-Pointern, wie die Konvertierung von C zu Fortran Pointer oder Auslesen der Speicheradresse einer Fortran Variable.
- Konstanten für nicht anzeigbare C-Zeichen, wie das Zeilenumbruchzeichen (\n) oder das horizontale Tab (\t).
Nicht alle Datentypen aus Fortran kann man mittels dem iso_c_binding in den C-Code übertragen und vice-versa. Beispielsweise existiert in Fortran kein Äquivalent einer C-Union oder in C gibt es kein direktes Äquivalent des Fortran ALLOCATABLE Attribut für Arrays, das eine dynamische Allokation des Speichers erlaubt, der automatisch wieder freigegeben wird, falls der Array out-of-scope geht. Weiters hat C/C++ keine Unterstützung für Array-slices, also eine strukturierte Teilmenge eines Arrays, daher müssen bei der Übergabe dieser Kopien angelegt werden.
In einigen Projekten der RISC Software GmbH war die Vorgabe Python Interfaces für Fortran Code zu schreiben. Dazu hat sich das Programm SWIG (http://www.swig.org/) bewährt, das Code für Python/C Interfaces generiert. Um ein Python/Fortran Interface zu erzeugen, wird zuerst die Fortran/C Schnittstelle geschrieben, um mittels SWIG dann die Python/C Schnittstelle zu erzeugen. SWIG ist in seiner Anwendung sehr flexibel und lässt sogar numpy-Arrays als Argumente der Python Funktionen zu, was zu einerseits effizienten und anderseits gut lesbaren Python führt. Durch die Einbindung in das CMake Buildsystem funktioniert dieser Zugang plattformunabhängig und bietet einen einfachen und effizienten Workflow in der Entwicklung.
Kontakt
Autor
DI Dr. Christoph Hofer
Professional Software Engineer Unit Industrial Software Applications