Entwicklung eines effizienten Verfahrens zur Simulation kompressibler Strömungen in 3D auf Parallelrechnern Bernhard Schupp Institut für Angewandte Mathematik Universität Freiburg Dissertation vorgelegt bei der Mathematischen Fakultät Universität Freiburg Betreuer: Prof. Dr. D. Kröner 1999 2 1. Gutachter: Prof. Dr. Dietmar Kröner 2. Gutachter: Prof. Dr.-Ing. Hans Burkhardt Dekan: Prof. Dr. Wolfgang Soergel Tag der mündlichen Prüfung: 20. Dezember 1999 3 Inhaltsverzeichnis Einleitung 5 1 Simulation kompressibler Strömungen 13 1.1 Die Euler-Gleichungen der Gasdynamik . . . . . . . . . . . . . . 13 1.2 Numerisches Verfahren . . . . . . . . . . . . . . . . . . . . . . . 17 1.3 Gesamtalgorithmus . . . . . . . . . . . . . . . . . . . . . . . . . 24 2 Parallelrechner 27 2.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.2 Ausführungsmodelle . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.3 Programmiermodell . . . . . . . . . . . . . . . . . . . . . . . . . 35 2.4 Leistungsmessung . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3 Basisentwurf 43 3.1 Objektorientierte Programmentwicklung . . . . . . . . . . . . . . 44 3.2 Datenstrukturen und Basisalgorithmen . . . . . . . . . . . . . . . 49 3.3 Gliederung der Klassen und Schnittstellen . . . . . . . . . . . . . 62 3.4 Numerisches Verfahren . . . . . . . . . . . . . . . . . . . . . . . 64 3.5 Lokale Gitterweitenanpassung . . . . . . . . . . . . . . . . . . . 70 4 Das parallele Simulationsprogramm 4.1 Ansatz zur Parallelisierung 77 . . . . . . . . . . . . . . . . . . . . . 77 4.2 Aufteilung des Gitters . . . . . . . . . . . . . . . . . . . . . . . . 80 4.3 Numerisches Verfahren . . . . . . . . . . . . . . . . . . . . . . . 82 4.4 Identifikation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 4.5 Lokale Gitterweitenanpassung . . . . . . . . . . . . . . . . . . . 95 4.6 Dynamische Lastverteilung . . . . . . . . . . . . . . . . . . . . . 98 4 INHALTSVERZEICHNIS 5 Dokumentation zur Implementierung 109 5.1 Adaptives Gitter . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 5.2 Sicherung und Wiederherstellung . . . . . . . . . . . . . . . . . . 116 5.3 Numerisches Verfahren . . . . . . . . . . . . . . . . . . . . . . . 118 5.4 Identifikation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 5.5 Datenaustausch im parallelen Verfahren . . . . . . . . . . . . . . 122 5.6 Dynamische Lastverteilung . . . . . . . . . . . . . . . . . . . . . 124 5.7 Iterationspaket . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 5.8 Schnittstelle zum Message Passing System . . . . . . . . . . . . 129 5.9 Ausführbare Programme . . . . . . . . . . . . . . . . . . . . . . . 131 6 Testbeispiele, Messungen und Bewertung 135 6.1 Hinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 6.2 Dynamische Lastverteilung . . . . . . . . . . . . . . . . . . . . . 143 6.3 Beschleunigung und Skalierung . . . . . . . . . . . . . . . . . . . 150 6.4 Bewertung der Ergebnisse . . . . . . . . . . . . . . . . . . . . . 157 A Abbildungen 161 B CD-ROM Datenträger 167 C Index der Quelldateien 171 Literaturverzeichnis 172 5 Einleitung Motivation Die rechnergestützte Simulation physikalischer Vorgänge der Kontinuumsmechanik hat in den letzten Jahren zunehmend an Bedeutung gewonnen. Wohlbekannte Anwendungen sind für die Strukturmechanik die Vorhersage von Verformung und Bruch von Werkstücken z.B. im Fahrzeugbau oder in der Baustatik, für die Strömungsmechanik die Bestimmung von Druck-, Temperatur- und Geschwindigkeitsprofilen beispielsweise in der Meteorologie, im Flugzeugbau und bei der Auslegung von Wärmekraftmaschinen. Die Gründe dafür lassen sich mit der Feststellung zusammenfassen, daß die Simulation, falls sie mit den derzeitigen Möglichkeiten durchführbar und unter dem Gesichtspunkt der jeweils vorgenommenen Vereinfachungen noch aussagekräftig genug ist, eine kostengünstige Alternative zu experimentell gewonnenen Vorhersagen darstellt. Bei genauer Betrachtung erweisen sich die beiden Rahmenbedingungen als miteinander gekoppelt, denn signifikante realitätsnahe Berechnungen erfordern hohe Rechnerleistungen, gemessen in der Anzahl der auszuführenden arithmetischen Basisoperationen und rücken daher durch die stetige Weiterentwicklung der Mikroprozessoren und Rechnersysteme immer mehr in greifbare Nähe. Daneben haben aber auch entscheidende Verbesserungen in den zugrunde liegenden mathematischen Methoden und in den zugehörigen Algorithmen dafür gesorgt, die vorhandenen Möglichkeiten zielgerichtet und effizient einzusetzen. Ziele und Rahmen Mit der vorliegenden Arbeit sollen zwei wesentliche Methoden, die zur Beschleunigung numerischer Strömungsberechnungen auf unstrukturierten Gittern herangezogen werden können, miteinander kombiniert werden: 6 Adaptivität, hier speziell die lokale und zeitabhängige Anpassung der Gitterweite nach Maßgabe eines Verfeinerungskriteriums. Der offensichtliche Gewinn einer adaptiven Gitterstrategie liegt in der Möglichkeit, die begrenzte Anzahl verfügbarer Freiheitsgrade dort einzusetzen, wo sie den besten Nutzen entwickeln. Parallelisierung, zunächst als Begriff für die Option, eine numerische Simulation auch auf einem Parallelrechner durchführen zu können, transparent gegenüber den besonderen Eigenschaften und Einschränkungen derartiger Rechnersysteme (vgl. Kap. 2). Ziel Ziel ist die Entwicklung einer Simulationssoftware, die in der Lage ist, die Leistungsmöglichkeiten der heutigen Parallelrechnergeneration für eine gegebene Klasse von Aufgabenstellungen der mathematischen Strömungssimulation zu erschließen. Es wird sich herausstellen, daß als Grundlage dafür eine Strategie zur verteilten Datenhaltung benötigt wird, damit die Freiheitsgrade des numerischen Verfahrens mit dem darunterliegenden Gitter aufgeteilt und völlig getrennt sowohl verwaltet als auch bearbeitet werden können. Für Teilaufgaben, die Datenzugriffe über die Grenzen dieser Aufteilung hinweg erfordern, werden die betreffenden Daten auf geeignete Art identifiziert und herangeführt. Darüber hinaus muß auch vorgesehen werden, die Aufteilung der Freiheitsgrade zur Laufzeit verändern zu können, weil die lokale Gitterweitenanpassung (Adaptivität) Freiheitsgrade unterschiedlich stark in die Teilprobleme einfügen oder aus ihnen entfernen wird. Dies führt auf die Frage, wie eine effiziente dynamische Lastverteilung realisiert werden kann, über welche Eigenschaften das verteilte Gitter dazu verfügen muß, und wie sich die vorgestellten Ideen bereits im Entwurf der geometrischen Gitterdatenstrukturen und Basisalgorithmen so geschickt vorbereiten lassen, daß ein einheitliches Konzept entsteht. Damit sind die im Bereich des Programmentwurfs liegenden Aspekte der Zielrichtung dieser Arbeit zunächst kurz umrissen. Auf der anderen Seite, also dort wo nach Leistungsfähigkeit von numerischen Verfahren, Algorithmen und Programmentwürfen gefragt wird, sollten aber auch befriedigende Antworten gegeben werden können. Betrachtet man dazu die Simulation der zeitabhängigen kompressiblen Durchströmung einer dreidimensionalen Geometrie selbst als als eine aktuelle, praxisrelevante Fragestellung der Strömungssimulation oder eventuell als ein Teilverfahren in einer komplexeren Berechnung: Beidesmal sind alle für die Bewertung des parallelen adaptiven Algorithmus entscheidenden Gesichtspunkte enthalten; ebenso wird sich zeigen, daß die im letzten Kapitel vorgestellten Testprobleme sogar schärfere Anforderungen an das entwickelte Verfahren definieren als viele Aufgabenstellungen auf der Grundlage aufwendigerer Modelle. 7 Rahmen Das für die Simulation einer zeitabhängigen kompressiblen Überschallströmung ausgewählte numerische Verfahren ist ein explizites Finite Volumen Verfahren erster Ordnung auf einem unstrukturierten nichtkonformen Hexaedernetz. Die Freiheitsgrade des numerischen Verfahrens sind an die Elemente gebunden, der Aufwand des Verfahrens besteht im wesentlichen aus der Berechnung der numerischen Flüsse auf den Element-Element-Grenzflächen. Der Daten- bzw. Methodeninhalt des in der Programmiersprache C++ realisierten parallelen Simulationsprogramms geht über den vom verwendeten numerischen Verfahren benötigten Umfang nicht hinaus, um einen linearen und übersichtlichen Aufbau der Implementierung zu unterstützen. Im Gegensatz dazu berücksichtigt der Entwurf die Ausdehnung des numerischen Verfahrens auf höhere Approximationsordnung, viskose Zusatzterme oder implizite Diskretisierungsschemata bei der Auslegung der Datenstrukturen und Basisalgorithmen. Damit ist die Gitterverwaltung des parallelen Simulationsprogramms auch eine ideale Grundlage für die Integration aufwendigerer Lösungsverfahren für realitätsnahe Problemstellungen. Die Reichweite des entwickelten Datenmodells für die geometrischen Zusammenhänge im Gitter geht sogar noch über diese Möglichkeiten und die verwendeten Hexaederelemente hinaus: Eine Erweiterung des Programms auf ein vergleichbares Tetraedernetz ist im Umfang des beiliegenden Quellcodes enthalten und vermittelt bei Bedarf einen Eindruck von der Flexibilität des Entwurfs. Selbst ein weiterer Ausbau auf eine hybride Gitterstruktur mit verschiedenen Elementtypen erfordert keine tiefgreifenden Änderungen im Programmentwurf, weshalb an den entscheidenden Stellen in der Dokumentation auf die entsprechenden (fundamentalen) Konzepte im Lösungsansatz eingegangen wird. Umfang Die vorliegende Arbeit enthält an erster Stelle eine umfassende Darstellung des numerischen Verfahrens zur Simulation kompressibler zeitabhängiger Strömungen und dessen Analyse im Hinblick auf die verteilte Datenhaltung. Daran anschließend wird ein objektorientierter Programmentwurf, der alle vorliegenden Anforderungen erfüllt, vorgestellt. Daneben wird besonderer Wert darauf gelegt, möglichst viele Entwurfsmuster und eventuell sogar Standardentwurfsmuster zu identifizieren, um dadurch eine knappe und verständliche Dokumentation des Entwurfs zu unterstützen. Weiterhin soll der Bezug zur Implementierung, die in C++, einer mittlerweile verbreiteten und verfügbaren Programmiersprache mit Unterstützung für objektorientierte Konzepte vorliegt, hergestellt werden, wodurch die sich anschlie- 8 ßende Dokumentation des Programmcodes auf jene Eigenschaften beschränkt werden kann, die nicht bereits aus dem Entwurf hervorgehen. Abschließend ist zu testen, wie gut das entwickelte Programm den vorab aufgestellten und formulierten Vorgaben und Erwartungen entspricht. Zu diesem Zweck sind im letzten Kapitel Testbeispiele, Zeitmessungen und Aufwandsbetrachtungen zusammengestellt. Der Quellcode des Simulationsprogramms gehört mit zum Umfang der Arbeit, zunächst mindestens als ein Beleg, der die gewonnenen Ergebnisse reproduzierbar und jederzeit nachprüfbar macht. Deshalb ist es notwendig, den Quellcode des Simulationsprogramms in exakt der Version, die zu den dargestellten Ergebnissen geführt hat, als festen Bestandteil der Arbeit anzusehen, zumindest überblicksartig zu dokumentieren und mit dem zugrunde liegenden Programmentwurf in Verbindung zu bringen. Durch den Umfang der Quelldateien ist es nicht möglich, sie in Form eines Klartextausdrucks in diesem Dokument unterzubringen. Insofern bietet sich ein CD-ROM Datenträger, auf dem die Dateien abgelegt sind, als praktikable Lösung an. Inhaltliche Einordnung Allgemein ist das bearbeitete Thema der Programmentwicklung zur Nutzung von Höchstleistungsrechnerarchitekturen für Aufgabenstellungen der numerischen Mathematik, insbesondere der numerischen Strömungssimulation, zuzuordnen. Die Forschung in diesem Bereich ist bemüht, Konzepte zu entwickeln, die explizit die zugrunde liegende mathematische Problemstellung berücksichtigen, bzw. diese sogar von der algorithmischen Seite nutzen können. Hier wiederum lassen sich zwei hauptsächliche Richtungen unterscheiden: Einerseits findet man die Entwicklung von Verfahren, die hinsichtlich ihrer Daten stark strukturiert sind und dadurch eine äußerst effiziente Nutzung der Rechenanlagen zulassen. Auf der anderen Seite erkennt man die Algorithmen für unstrukturierte Problemstellungen, deren Klasse im Bereich der Lösungsverfahren für partielle Differentialgleichungen hauptsächlich die adaptiven numerischen Verfahren auf unstrukturierten oder hybriden Gittern umfaßt. Der Vorteil dieser Verfahren liegt in ihrer Flexibilität im Hinblick auf realistische Problemstellungen [42], wodurch auch die aufwendige Ausdehnung auf eine parallele Verarbeitungsstrategie gerechtfertigt wird. Das im Rahmen dieser Arbeit entwickelte Simulationsprogramm profitiert hinsichtlich seines Entwurfs, also der Strukturierung und Auslegung der Daten und Algorithmen, an einigen Stellen von den Erfahrungen aus früheren Untersuchungen und Vorschlägen zu verwandten Themen und Fragestellungen. 9 Von besonderem Interesse sind dabei sicherlich die Parallelisierung eines rekursiven Verfeinerungsalgorithmus auf Dreiecksgittern für Transputer [22], die Betrachtungen zu einem adaptiven Mehrgitterverfahren mit dynamischem Lastausgleich [5] für stationäre Probleme in Verbindung mit dem dazu entworfenen abstrakten verteilten Datenmodell [6] sowie die Untersuchungen zur Effizienz paralleler Simulationsverfahren für die kompressiblen Navier-Stokes Gleichungen auf unstrukturierten Dreicksnetzen mit verschiedenen Methoden zur Gitterzerlegung [36]. Ergebnisse Die vorliegenden Ergebnisse sind keinesfalls als ein Vorschlag für die Zusammenführung von bereits bestehenden Techniken und Konzepten aus anderen Untersuchungen zu einem Endprodukt mit hoher Integrationsdichte anzusehen, denn das Gesamtverfahren eines parallelen adaptiven numerischen Algorithmus mit dynamischer Lastverteilung ist aufwendig, kondensiert aber letztlich die Anforderungen aus realistischen Aufgabenstellungen an einen verteilten Datenentwurf sogar noch massiv. Es stellt damit den nicht weiter reduzierbaren Kern einer verteilt-parallelen Verarbeitungsstrategie dar, denn ein adaptives paralleles Verfahren kann, wie auch abschließend nachgewiesen wird, ohne dynamische Lastverteilung nicht effizient auf zeitabhängige Probleme angewandt werden. Entlang des reduzierten Problems zeigt die vorliegende Arbeit erstmals verschiedene neue Ansätze für den Programmentwurf auf: Eine geradlinige und durchgängige Analyse und Modellierung unter dem Paradigma der Objektorientierung führt auf einen strukturierten und durchsichtigen Programmentwurf mit klaren und einsichtigen Klassendefinitionen (vgl. Kap. 3.3). Neu identifizierte Entwurfsmuster und die sinnvolle Übernahme von Standardentwurfsmustern [12] eröffnen eine gegenüber traditionellen Ansätzen abweichende Sicht auf das mathematische Verfahren und die geometrischen Zusammenhänge des Gitters (vgl. Kap. 3.2, 3.4). Bereits in der Klassenhierarchie des Basisentwurfs ist die Option zu einer Ausdehnung des numerischen Verfahrens auf eine höhere Approximationsordnung [42] oder auf Discontinous-Galerkin Verfahren [8] enthalten. Geeignete Abstraktionen in der Schnittstellenauslegung ermöglichen es, das Programm auf anisotrope Verfeinerungsregeln [3] oder Tetraederelemente und hybride Gitter erweitern zu können (vgl. Anh. B). Geschickt entworfene Algorithmen für die parallele Gitterweitenanpassung und die Identifikation vermeiden Datenüberhang und Redundanz 10 im verteilten Simulationsprogramm und schaffen die Grundlage für ein Gesamtverfahren, das auch für stark instationäre Probleme effizient eingesetzt werden kann (vgl. Kap. 4.4, 4.5). Weiterhin liegen mit den Messungen am Simulationsprogramm für die konkrete realistische Problemstellung Einsichten vor, die dazu führen sollten, daß manche Vorbehalte gegenüber objektorientierten Ansätzen in der Programmentwicklung für mathematisch-ingenieurswissenschaftliche Anwendungen neu bewertet werden: Die Messungen zur dynamischen Lastverteilung zeigen, daß der zusätzliche Aufwand zur Partitionierung und Umverteilung des Gitters auch für stark instationäre Strömungen mit wechselnder Topologie der Verfeinerungszone nur ca. ein Prozent des gesamten Berechnungsaufwands ausmacht (vgl. Kap. 6.2). Der Vergleich des adaptiven parallelen Gesamtverfahrens mit Rechnungen auf einem global verfeinerten Gitter ergeben eine mehr als halbierte Ausführungszeit der Simulation durch die lokale Gitterweitenanpassung mit dynamischer Lastverteilung (vgl. Kap. 6.3.1). Die Untersuchungen zur Skalierbarkeit des Simulationsprogramms zeigen, daß das parallele Simulationsprogramm gerade für hochaufgelöste Berechnungen mit mehreren Millionen Freiheitsgraden sehr geeignet ist (vgl. Kap. 6.3.4). Die umfangreichsten Testrechnungen auf 120 Prozessoren führen eindrucksvoll vor, wie die verteilte Gitterverwaltung mit einem Gitter aus ca. 20 Millionen einzelnen Objekten effizient umgeht und weisen damit die Eignung des objektorientierten Entwurfs, der vorgeschlagenen Datenstrukturen und der verwendeten Programmiersprache für realistische Problemgrößen nach (vgl. Kap. 6.3.3). Somit darf an dieser Stelle schon vorweggenommen werden, daß mit dem vorliegenden Entwurf das Problem einer verteilt-parallelen Ausführung der numerischen Simulation nicht nur strukturell unter vielen Aspekten bearbeitet worden ist, sondern daß die aufgezeigten Ansätze auch zu einer effizienten Implementierung weiterentwickelt werden können. Danksagungen Ohne die Unterstützung der nachfolgend aufgeführten Personen oder Einrichtungen wären die Ziele dieser Arbeit nicht oder zumindest nicht im erwarteten Umfang erreicht worden. Ich danke daher 11 dem Betreuer Herrn Prof. Kröner für die Vergabe des Themas und den Vorschlag, das Vorhaben aufgrund seiner fachübergreifenden Definition dem Graduiertenkolleg Nichtlineare Differentialgleichungen: Modellierung, Theorie, Numerik und Visualisierung zuzuordnen, dem Zweitgutachter Herrn Prof. Burkhardt von der Fakultät für Informatik an der Universität Freiburg, der Deutschen Forschungsgemeinschaft (DFG) für die finanzielle Unterstützung des Promotionsvorhabens durch ein dreijähriges Stipendium im Rahmen des Graduiertenkollegs Nichtlineare Differentialgleichungen: Modellierung, Theorie, Numerik und Visualisierung, den Betreibern der Parallelrechner am Rechenzentrum der Universität Karlsruhe, am Institut für Wissenschaftliches Rechnen (IWR) in Heidelberg und am Paderborn Center for Parallel Computing (PCPC) in Paderborn für den zuverlässigen, berechenbaren und forschungsorientierten Betrieb der jeweiligen Hochleistungsrechner, verschiedenen, im Text erwähnten wissenschaftlichen Einrichtungen bzw. Forschergruppen für die unkomplizierte und transparente Art, wie die dort entwickelte Software zur Einsicht und Verwendung zugänglich gemacht wird, und nicht zuletzt den Kollegen Andreas Dedner und Matthias Wesenberg für die Diskussionen und Anregungen zum vorliegenden Dokument, dem Kollegen Ralph Schwörer für die Unterstützung bei der Visualisierung der Ergebnisse, Herrn Ulrich Hiddemann für verschiedene Hinweise zur Verwendung der Unified Modeling Language [7] in der Dokumentation und meiner Schwester Sibylle Schupp für die Unterstützung bei der Drucklegung des Dokuments. 12 13 Kapitel 1 Simulation kompressibler reibungsfreier Strömungen in 3D 1.1 Die Euler-Gleichungen der Gasdynamik Die Euler-Gleichungen der Gasdynamik sind ein mathematisches Modell für das zeitliche Verhalten kompressibler reibungsfreier Strömungen. Unter bestimmten Annahmen kann beispielsweise die Strömung trockener Luft mit diesen Gleichungen beschrieben werden. Aber auch für ausgefeiltere Modelle, die weitere Effekte wie Reibung, Strahlung oder chemische Reaktion enthalten, sind die Euler-Gleichungen und die zugehörigen numerischen Verfahren fundamentale Bausteine. Die Euler-Gleichungen sind ein System von Erhaltungsgleichungen, das aus der Annahme folgt, es gebe eine (vektorielle) physikalische Größe, deren zeitliche Entwicklung innerhalb eines beliebigen Volumens sich durch Bilanzen auf dessen Rand ausdrücken läßt. Dieser Zusammenhang soll zunächst kurz skizziert werden, unter anderem auch deshalb, weil das verwendete Finite Volumen Verfahren aus nahezu identischen Überlegungen heraus motiviert werden kann. Notation und verwendete Bezeichnungen In den weiteren Abschnitten dieses Kapitels werden die folgenden Notationen und Bezeichnungen verwendet: Der Ortsvektor bezüglich eines raumfesten Koordinatensystems. Vektoren sind durch fettgedruckte Buchstaben bezeichnet. 14 KAPITEL 1. SIMULATION KOMPRESSIBLER STRÖMUNGEN Die euklidische Norm auf dem normierten Vektorraum (NVR) 8 #9 ;: 8 #9 !#" !%$&'& )( für T * +'-,/,.0d.h. 213,/4513,/67 . Der Divergenzoperator in ist . mit Die linearen Abbildungen bzw. die Gruppe der invertierbaren lieines NVR . nearen Abbildungen <=9?>@9 Weiterhin sei A ein Gebiet, und BDC*A kompaktes Testvolumen innerhalb von A . 9 ein hinreichend glatt berandetes Bilanzengleichungen EF'GEH JI )K 'LKM N I OPRQSTE5U ,0VWO Die in einer Bilanzengleichung auftretenden Größen sind eine räumliche Dichund die entsprechende Stromdichte . Weiteverteilung terhin wird angenommen, daß für die Gesamtmasse in einem beliebigen, festgehaltenen Testvolumen sich die zeitliche Änderung alleinig aus der Situation auf dessen Berandung, genauer aus der Bilanz der einund ausströmenden Massen ergibt: X S , V EY[Z X]\ KS _ ^` MU a (1.1) K ^`b /U a b Hier steht auf der rechten Seite das Oberflächenintegral über die durch ein Flächenelement ausströmende Masse mit der äußeren Einheitsnormalen . Werden die Stromdichte und der Rand des Testvolumens als hinreichend glatt vorausgesetzt, darf der allgemeine Hauptsatz angewendet werden, und es folgt die lokale bzw. differentielle Form (Erhaltungsform) der Bilanzengleichung (1.1): (1.2) ^` U/a K dK fe ,MVEc1 ? Letztlich ist es vom verwendeten Modell abhängig, in welcher Beziehung Dichte und Stromdichte zueinander stehen. Für die Bewegung einer räumlichen Massenverteilung setzt man , wobei das Geschwindigkeitsprofil des skalaren Transports ist [23]. KghE/i ijhik JI Die Euler-Gleichungen der Gasdynamik folgen unter der Voraussetzung, daß Masse, linearer Impuls und die Energie bestimmten, physikalisch begründeten Bilanzengleichungen genügen, wenn die beschriebene Vorgehensweise sinngemäß auf den Vektor dieser Größen angewendet wird. Erhaltungsgleichung für die Massendichte El'LEm NI Die Dichte und die Massenstromdichte genügen einer Erhaltungsgleichung der Form: E/i Le , V En1 o EMi des betrachteten Gases (1.3) 1.1. DIE EULER-GLEICHUNGEN DER GASDYNAMIK 15 Erhaltungsgleichungen für die Impulsdichte EMi Die drei Komponenten der Dichte des linearen Impulses erfüllen zusammen mit der Impulsstromdichte homogene Bilanzengleichungen, solange eine Impulsänderung durch Volumenkräfte wie Gravitation oder elektromagnetische Kräfte ausgeschlossen wird. Die Impulsgleichungen in Komponentenschreibweise lauten: +1 u 13,/4]EMqrpqm 1s,/6/EMqvq e (1.4) (1.5) q 13, 4 EMq 1)u 1s, 6 EMq q e (1.6) q 13, 4 EMq q 13, 6 #E0q 1+u e Die Impulsgleichungen (1.4)-(1.6) können mit dem zu i dualen Vektor i w auf ,MVpEMqr s 1 ,/.tEMq , V EMq s 1 , . EMq , V EMq s 1 , . EMq die kürzere tensorielle Schreibweise reduziert werden: ,0VHE/i 1 ? #E5iyx=i{z 1F|tu -e (1.7) Hinweis: Der Ausdruck E5i+xoi w wird als in der Kontinuumsmechanik als Impulsstromdichtetensor, der Term für den Druck |tu als Spannungstensor be- zeichnet. Aus der Symmetrie des Spannungstensors folgt die Erhaltung des Drehimpulses bzw. umgekehrt die Invarianz der Impulsgleichungen unter Rotation des zugrunde liegenden räumlichen Koordinatensystems. } Erhaltungsgleichung für die Energiedichte ~~/ NI Die Energiedichte genügt ebenfalls einer skalaren Erhaltungsgleinoch ein Quellterm auftritt, chung, wobei zusätzlich zur Energiestromdichte der vom Druck abhängt. Dieser beschreibt die durch das einströmende Volumen am Testvolumen aufgebrachte Volumenarbeit: ~ i J u1s~ i fe ,MV~k1 ? (1.8) Zustandsgleichung für ideale Gase Das System der Gleichungen (1.3),(1.7) und (1.8) wird erst durch die thermodynamische Zustandsgleichung des Gases geschlossen [16]. Im vorliegenden Fall, also für ein ideales Gas, gilt dann mit der spezifischen Gaskonstanten und der (absoluten) Temperatur : uy d E < < und uyo Z 5 ~Z E i r Die Konstante ist von der Temperatur unabhängig und hat für trockene Luft einen Wert von . Die lokale Schallgeschwindigkeit ergibt sich daraus zu . =3 J o E u 16 KAPITEL 1. SIMULATION KOMPRESSIBLER STRÖMUNGEN Eigenschaften der Euler-Gleichungen Konservative Variablen: Die Euler-Gleichungen können auch als System in Erhaltungsform geschrieben werden, es lassen sich also eine verallgemeinerte und ein Tensor der verallgemeinerten Stromdichvektorielle Dichte te mit angeben, so daß mit diesen Größen die Gleichungen (1.3), (1.7) und (1.8) in die folgende Form überführt werden können: (1.9) Lk JI F N I 5 NI N r > 8 ,MV/{1 * -e Der Vektor 'EmNEMq N EMq JE0q ;~ T wird Erhaltungsvektor genannt, die Kom- ponenten bezeichnet man als konservative Variable. Das System (1.9) stellt die Euler-Gleichungen in konservativen Variablen dar. Primitive Variablen: Eine weitere Darstellung der Euler-Gleichungen findet man nach einer Transformation auf die primitiven Variablen, also auf die physikalischen Basisgrößen Massendichte , Geschwindigkeit und Druck . Das Differentialgleichungssystem liegt dann nicht in Erhaltungsform vor. Man erhält T: mit E F?#EtJqrNqHNq u (1.9) T i ,0VWy1 ! ,/. £M¤Le ! $¡)¢ wobei auf die explizite Darstellung der recht komplizierten Matrizen tet wird [23, 41]. u (1.10) verzich¢ ! Klassifikation: Die Euler-Gleichungen sind ein hyperbolisches System partieller Differentialgleichungen 1. Ordnung. Dies kann anhand der Darstellung in primitiven Variablen (1.10) leicht nachvollzogen werden [16]: Für jeden Vektor hat das charakteristische Polynom ¥ ¦ ¥ ¥ ¥ 0§;¨ LUM~7Iª© ! ¥ ! Z ¨ | « (1.11) !%$ ¢ ¥ ¥ ¥ fünf reelle Nullstellen ¨t¬ " ¬ $¡p&'&'& . Aus der Hyperbolizität folgt wieder- um, daß es für die Euler-Gleichungen sogenannte charakteristische Flächen gibt, auf denen die Information durch die Differentialgleichungen transportiert wird. Ohne auf Details einzugehen, ist zumindest für die Euler-Gleichungen der Gasdynamik leicht einzusehen, daß für einen sich mit der lokalen Strömungsgeschwindigkeit bewegenden Beobachter das Einflußgebiet der Daten an seinem Ort der Rückwärtsschallkegel ist. Umgekehrt erreicht einen feststehenden Beobachter in einer Überschallströmung nur Information die aus Orten innerhalb eines räumlichen Kegels mit Öffnung in Richtung der Anströmung kommt. i Die im nächsten Abschnitt beschrieben Upwind Finite Volumen Verfahren sind genau in diesem Sinne zu verstehen: Auch das numerische Verfahren enthält explizit in seiner Konstruktion eine Strategie, das Einflußgebiet der Lösung zu berücksichtigen [23]. 1.2. NUMERISCHES VERFAHREN 17 1.2 Numerisches Verfahren Dieser Abschnitt stellt das gesamte numerische Verfahren vor, und zwar gegliedert in die Motivation des verwendeten Finite Volumen Verfahrens, dessen genaue Beschreibung und die Aspekte, die durch die adaptive Strategie, hier speziell durch die Möglichkeit zur lokalen Anpassung der Zelldurchmesser, hinzukommen. 1.2.1 Motivation: Finite Volumen Verfahren Aus der Divergenzform der Bilanzengleichungen (1.2) läßt sich die Idee für ein numerisches Verfahren ableiten. Dazu seien zunächst eine räumliche Aufteilung des Trägergebiets für die Lösungsfunktion in kleine Volumenelemente (Zellen) offen mit und und zellenweise konstante Approximationen für die Anfangswerte auf allen Kontrollvolumen gegeben. B!#" ! $¡&'&'& ­®C[Ad B! ¯! B°!5?A Bt!r±)B/²YG³]µ´m¶n¹ · ¸ b S £ ITºe Bt! Dann kann für ein beliebiges Volumen , dessen Rand keinen Teil der Gebietsberandung enthält, eine Näherungslösung zur Zeit folgendermaßen berechnet werden: Gleichung (1.9) wird über das Zeitintervall integriert und anschließend der Hauptsatz der Integralrechnung angewandt, was auf den folgenden Ausdruck führt: X !J»I »I ¼ e½;»IW¾ X3¿ V X À S £ ,/Ák N U X ¿ V X \ 7^ ` Z À S £ N U/aTU X\ b S £ »°I Äà b S £ #e Z b »B ! I b S £ Je 7^ ` U/a S £ 5 ;»I Z5 Je (1.12) Mit Gleichung (1.12) liegt allerdings noch keine vernünftige Definition für eine Näherungslösung vor, weil der Wert von auf dem Rand des Zellvolumens ausgewertet wird, wo die Approximation der Lösungsfunktion infolge ihrer zellenweise konstanten Definition nicht eindeutig sein muß. # Å^ Um dieses Problem zu beheben, setzt man in die Gleichung (1.12) an die Stelle von eine numerische Flußfunktion ein, die neben dem Wert auf der Zelle auch den Wert auf der Nachbarzelle über die lokale Fläche berücksichtigt [16, 23]. v² Æ{!²0#!JJv² ¡! ¸ ^ ^ `2b /U a b Hinweis: Die skalierte äußere Normale ist in der Definition der numerischen Flußfunktion enthalten, was durch die Indizes deutlich gemacht wird. Die Flußfunktion ist daher im Gegensatz zu eine vektorwertige Funktion. Æ !² } 18 KAPITEL 1. SIMULATION KOMPRESSIBLER STRÖMUNGEN 1.2.2 Numerische Flußfunktion Æ{!² kann das heuristische Schema zur Mit einer numerischen Flußfunktion Berechnung einer numerischen Approximation der Lösungsfunktion zum Zeitpunkt aus den (Anfangs-) Daten zum Zeitpunkt (1.12) in eine Form überführt werden, die explizit berücksichtigt, daß die Approximation der Daten auf Grenzflächen zwischen zwei Volumen nicht stetig sein muß. Wird das Integral über die Volumen-Volumen-Grenzflächen durch eine 1-Punkt Integrationsformel approximiert, erhält man ein explizites Finite Volumen Verfahren in niedrigster Ordnung [16, 23]: I51¹»I I !J#Ir1Ç»I ' !NI Z b °» B! I b È Î Î Æ{!²0#!;I ;r²/I N £ÉpÊ Ë0È ÌM£É7Í £/Ë0Ð ÑÏÌÍ É ' Ò! Z b »I b Ô Æ{!'²/# Ò! J ²Ò bzw. ¡!ÒÓ B ! £É (1.13) Die Konstruktion der numerischen Flußfunktion wird anschließend für ein konkretes Verfahren motiviert, hier sollen noch die allgemeinen Bedingungen, die an eine numerische Flußfunktion zu stellen sind, aufgezählt werden: Æ '! ² ; Æ{!²0#5J Æ !'² ; ZsÆ !'² ÖmJÖ p×HØÙHÚ#Û Ü ´y;Öt; JÖ ßrà á und ZÕÆ ²J! # J (1.14) ^ (1.15) # !² ( ½Ý )ZÖ ;ÙHÚ 1 ZÞÖ JÙrÚ (1.16) Ýlâfãå!è äæ ç]é äã Bt! Bedingung (1.14) sichert die Erhaltungseigenschaft des Verfahrens, (1.15) muß aus Konsistenzgründen erfüllt sein. Aus verschieden Beweisen zur Konvergenz von Finite Volumen Verfahren für skalare hyperbolische partielle Differentialgleichungen [25] wird die Voraussetzung (1.16) sinngemäß für Systeme übernommen. 1.2.3 Flußfunktion von Steger und Warming Das parallele Simulationsprogramm verwendet die Flußfunktion von Steger und Warming [34], welche als numerisch robust gilt und effiziente Implementierungen zuläßt. Das Verfahren gehört zur Klasse der Flux Vector Splitting Verfahren, die auf einer Zerlegung des Erhaltungsvektors basieren. Eine einfache Betrachtung läßt zumindest die Absicht, die der Konstruktion des Verfahrens zugrunde liegt, vermuten. Ein lineares System hyperbolischer Differentialgleichungen in einer Raumdimension für eine allgemeine vektorwertige Funktion ê +( =ë ¼ e½J<¾W 2¬ : 8 2 ¬ ¢ , V ê?1 êìLe ¢ (1.17) 1.2. NUMERISCHES VERFAHREN í 19 kann in ungekoppelte Gleichungen für die Elementarwellen (die rechten Eigenvektoren von ) zerlegt werden, was auf ungekoppelte lineare skalare hyperbolische Differentialgleichungen führt [16]: ¢ ,0Vï î !vZð!,/.fï î !¡feT2ð!f· eY2¶? í (1.18) In diesem Fall kann leicht eingesehen werden, daß jede der Gleichungen die ) Information mit fortschreitender Zeit entlang der x-Achse in positiver ( oder negativer ( ) Richtung transportiert. Demnach sollte das numerische Verfahren zur Bestimmung des neuen Funktionswerts an einer Stelle auf die benachbarten Werte auf der richtigen“ Seite zugreifen. ” Da ein Finite Volumen Verfahren in mehreren Raumdimensionen durch die Normalenrichtung der betrachteten Element-Element-Grenzfläche bereits eine Raumrichtung auszeichnet, kann die bisherige Überlegung nach einer Transformation des Koordinatensystems auch auf lineare skalare Gleichungen in mehreren Raumdimensionen angewendet werden. ¤ñDe óòfe ^` Mit den Euler-Gleichungen liegt jedoch ein nichtlineares System vor, wodurch noch erhebliche Unterschiede zur vorgestellten Situation begründet werden. Betrachtet man auch hier den eindimensionalen skalaren Fall , V ï Z, . ï eYP )( ï w [e ï ï ôÁJI ïw und setzt als strikt konvex voraus, dann gibt es höchstens einen Wert von mit und das Schema von Enquist und Osher [9] ist eine Diskretisierung mit Upwind Charakter. Mit den Funktionen Ó ï - ãTäæ ï w ï N ï '- ã é%õ ï w ï N (1.19) definiert das Schema von Enquist und Osher die numerische Flußfunktion als ö ï N ÷ fHÓ ï 1Ç ÷ (1.20) Die Flußfunktion (1.20) greift in Abhängigkeit des Vorzeichens von auf das linke oder rechte Argument zu (Upwind Eigenschaft). Eine vergleichbare Voraussetzung an darf auch für die Euler-Gleichungen gemacht werden [16]. ê )( -ë ¼ e½N<ª¾ ¬ t )( ø¬ ,MVÁêùZÞ,/.c Mê T ,0VêZÞú{ ê ,M.ê 2¬ e e Dehnt man die Betrachtungen auf ein nichtlineares System in einer Raumdimensionen aus (1.21) (1.22) wird eine zum skalaren Fall ähnliche Situation nur auftreten, falls die Eigenwerte der Jacobimatrix in Abhängigkeit von immer einheitlich positives oder negatives Vorzeichen haben. Die Eigenwerte für die Jacobimatrix der Euler-Gleichungen sind hingegen , und , die Situation mit verschiedenen Vorzeichen ist also zu berücksichtigen [23]. ¨ !J#ê ú{ ê q ¨ ?ql1 ¨ ? ¨t oqZs 20 KAPITEL 1. SIMULATION KOMPRESSIBLER STRÖMUNGEN Hinweis: An dieser Stelle sind die Unterschiede zwischen den verschiedenen numerischen Flußfunktionen zu erkennen: Im Überschallbereich haben alle das erforderliche Upwind Verhalten, wohingegen im Unterschallbereich nach verschiedenen Vorschriften diskretisiert wird. } Ó Zu (1.19) analoge Funktionen , für die Euler-Gleichungen erhält man, wenn die Homogenität erster Ordnung der Funktion genutzt wird, die im Fall idealer Gase gilt ( bezeichnet den Erhaltungsvektor mit einer Geschwindigkeitskomponente) ê Mê 0#ûrê LûcMê Daraus folgt für eine Darstellung, die einer Linearisierung und Zerlegung nach Eigenvektoren besser zugänglich ist: Mê ¢ #ê ê Die Flußfunktion von Steger und Warming [34] definiert eine Aufspaltung von mit der geforderten Upwind Eigenschaft durch: 0#ê ü ê)J fý Ó ê ê?13ý ø (1.23) wobei die Matrizen ê und Ó ê durch Auswahl der positiven und ne¢ gativen Eigenwerte ¢ aus der Jacobimatrix ú{ nach einer diagonalisierenden Transformation der Variablen mit den Matrizen aus den linken und rechten Eigenvektoren von entstehen: úy Ó #ê þ # ê äÿ ãåäæ ¨ !N;e ½ þ ¢ #ê þ #ê ]ç é ä ÿ ã ¨ !;;e ½ þ ç]é %é õ ¢ # ê #ê bzw. Die Erweiterung des Verfahrens (1.23) auf mehrere Raumdimensionen geschieht mit dem Argument, daß entlang der Normalen auf einer Volumen-Volumen-Grenzfläche nur eine Ableitungsrichtung existiert. Die Gleichung kann somit in ein räumliches Koordinatensystem transformiert werden, bezüglich dessen die Ableitungen und verschwinden. ,M4 ê ,/6 ê ê ¢ Ó ê ¢ #ê Auf die expliziten Darstellungen der Matrizen , in 1D in Abhängigkeit vom Vektor der Erhaltungsgrößen sowie der entsprechenden Matrizen und in 3D, die zusätzlich von der Normalenrichtung der betrachteten Fläche abhängen, wird verzichtet [23]. ¢ Ó ê) ^ ê)^ ^ ¢ Steuerung der Zeitschrittweite: Wendet man die Formulierung für ein Upwind Finite Volumen Verfahren als explizite numerische Vorschrift (1.12) an, stammen alle Größen, die in die Berechnung der numerischen Flußfunktion eingehen, aus dem letzten bereits berechneten Zeitschritt und das numerische Verfahren transportiert eine Information in einem Zeitschritt nur von einer Zelle (Kontrollvolumen) zu einer ihrer Nachbarzellen. »I Die Zeitschrittweite ist daher so klein zu wählen, daß die maximale Ausbreitung einer Elementarwelle (1.18) während der Zeitschrittweite nicht größer »I 1.2. NUMERISCHES VERFAHREN 21 B ! Ô \ b _^kb b » I b Ü »I ãåS ä£ æ b B ! b ãåÉ äæ S £ i 1s ² ist als der Durchmesser des Volumens . Dies ist eine anschauliche Erklärung für die CFL-Bedingung an die Zeitschrittweite im expliziten Verfahren [23]: Ü (1.24) ² bezeichnet darin eine Außenfläche des Volumens B ! und ^ die skalierte Normale an diese Fläche. Die Werte für die Geschwindigkeit i und die Schallgeschwindigkeit sRô¡NI R#ikô¡NI J werden aus den Daten des bereits CFL berechneten Zeitschritts ermittelt. 1.2.4 Randbedingungen Randbedingungen sind festzulegen, falls das Trägergebiet der Strömung nur eine endliche Ausdehnung aufweisen soll und die Strömung deshalb in Wechselwirkung mit dessen Berandung zu betrachten ist. Für Überschallströmungen kann man einige realistische Randbedingungen angeben, die überdies im numerischen Verfahren sehr einfach zu realisieren sind. Die zur Bewertung des verteilt-parallelen Simulationsprogramms durchgeführte Strömungsberechnung macht von vier Randbedingungen Gebrauch [23]: Einströmrand: Am Einströmrand dürfen alle fünf Werte des Erhaltungsvektors vorgegeben werden, solange die Strömungsgeschwindigkeit dort größer als die Schallgeschwindigkeit ist. Allgemein dürfen für ein hyperbolisches System mit Gleichungen Größen auf dem Rand vorgeschrieben werden, wenn die Anzahl der negativen Eigenwerte von (1.23) ist. O ú{ í O-Zlí Ausströmrand: Hier dürfen keine Werte vorgeschrieben werden, solange die Strömung Überschallcharakter hat. Es ist leicht nachzuvollziehen, daß eine konstante Fortsetzung der Werte auf den Zellen vor dem Rand in das Gebiet dahinter für das Upwind Verfahren genau das gewünschte Ergebnis liefert: Ø & Û É £ Æ{!²M#!JJv² {Æ !'²0¡!JJ! #! _ ^ '! ² / ^ j e Sliprandbedingung: (No-flux boundary condition) An der festen Wand wird gefordert, die Strömungsgeschwindigkeit hat nur eine tangentiale Komponente. Falls die Werte als über den Rand hinweg konstant fortgesetzt angesehen werden, vereinfacht sich der numerische Fluß zu (Bezugspunkt ist das Volumen , ist das aus der Fortsetzung entstandene virtuelle Volumen): B! B² Ø & Û É £ Æ ! ² # ! ; ² Æ '! ² ! J ! # ! ^ !² [Z2u°e½ ;e T Der einströmende Impuls EMi ist das Produkt aus dem lokalen Druck u und der skalierten Flächennormalen ^ !² . 22 KAPITEL 1. SIMULATION KOMPRESSIBLER STRÖMUNGEN Symmetrierand: Falls die Geometrie des Berechnungsgebiets durch Spiegelung einer Teilgeometrie an einer Fläche erhalten werden kann, besteht die Möglichkeit, die Berechnung nur auf dieser Teilgeometrie durchzuführen und den künstlichen Rand durch die Symmetrierandbedingung EM!¡LE²ø ~ !Á-~ð²2 v!H1Fm² ^ ` -e ^` die Normale an die Symmetriefläche bezeichdarzustellen, worin net. 1.2.5 Adaptives Verfahren In einem adaptiven numerischen Verfahren sollen zur Beeinflussung des Diskretisierungsfehlers während der Berechnung nach Maßgabe eines entsprechend entworfenen Kriteriums Freiheitsgrade in das Gitter eingefügt bzw. aus ihm entfernt werden. Das kann grundsätzlich auf zwei verschiedene Arten geschehen: h h-Verfeinerung Die Anzahl der Kontrollvolumen wird verändert, indem bestimmte Kontrollvolumen geteilt bzw. zusammengefaßt werden. Diese Art wird auch h-Verfeinerung genannt, weil sie die Gitterweite verändert, die üblicherweise mit bezeichnet ist. Ý p p-Verfeinerung Für ausgewählte Kontrollvolumen wird die Approximationsordnung der numerischen Lösungsfunktion erhöht bzw. erniedrigt. Diese Technik kann als p-Verfeinerung bezeichnet werden, falls die numerische Lösung durch Polynome vom Grad dargestellt wird. Die Gitterweite wird nicht verändert. u Die erste Art der Verfeinerung ist vom numerischen Verfahren unabhängig und betrifft nur das Gitter. Im Fall der p-Verfeinerung hingegen muß das numerische Verfahren dafür ausgelegt sein, mit den unterschiedlichen Approximationsordnungen umzugehen. Deshalb kann für das Finite Volumen Verfahren bei festgelegter Approximationsordnung nur eine h-Verfeinerungstechnik angewendet werden. Alle weiteren Überlegungen dieses Abschnitts gehen davon aus, daß ein Algorithmus vorliegt, der ein beliebiges Volumen im Gitter auf Anforderung in kleinere Einheiten aufteilt und dabei eine Nebenbedingung der Form Ü b ÝB ! b Ü ( Ý ' ã !ù (1.25) é%õ ç]é äã B! mit festgelegten Konstanten , ( einhält bzw. umgekehrt kleine Volumen zu einem größeren unter Beachtung dieser Bedingung zusammenfaßt. Diese Nebenbedingung an die Verfeinerungsregel ist eine Voraussetzung zum Theorem von Lax Wendroff für Systeme von Erhaltungsgleichungen [23]. 1.2. NUMERISCHES VERFAHREN 23 Verfeinerungskriterium Für skalare Gleichungen ist bereits eine theoretisch fundierte Technik zur aposteriori Schätzung des räumlichen und zeitlichen Diskretisierungsfehlers vorgestellt worden [24]. Die Ergebnisse lassen sich allerdings nicht ohne weiteres auf die nichtlinearen Euler-Gleichungen in mehreren Raumdimensionen erweitern, sodaß man dort noch auf heuristische Kriterien zur Steuerung der Gitterweitenanpassung angewiesen ist. Zur Untersuchung der Leistungsfähigkeit des parallelen Simulationsprogramms wird ein Testproblem benötigt, für das eine flächenartige Verfeinerungszone entsteht, die sich zeitlich in ihrer Größe, Topologie und Lage ändert. Weil diese Anforderung nur qualitativer Natur ist, kann auch ein einfaches Verfeinerungskriterium schon brauchbare Ergebnisse liefern: In den Testrechnungen zu einer Überschallströmung in einem einfachen Windkanal (vgl. Kap. 6.1.2) sollen lediglich die Stoßwellen der Dichte (Schocks) vom Verfeinerungskriterium erkannt und bewertet werden. Dazu genügt es, auf allen Volumen-Volumen-Grenzflächen den Wert von !'² !²c b E Î £ ZÞE Î É b (1.26) zu bestimmen und daraus ein einfaches Kriterium zur Steuerung der Gitterweitenanpassung zu konstruieren, das auf eine räumliche Gleichverteilung der lokalen Größen abzielt [22]: !'² ! ²cCg,rB! !²nò w ´rB ¬ " ¬ $¡p&'&'& ´ ¬ ²óC,HB ¬ ¬ ²óñg B! verfeinere vergröbere alle B ¬ " ¬ $¡p&'&'& (1.27) Das Kriterium ist dabei in folgendem Sinne zu verstehen: Das Gitter muß am Ort der Zellen und verfeinert werden, sobald der Wert von auf der gemeinsamen Fläche ist. Umgekehrt darf vergröbert werden, falls für alle Zellen , die zu einer gröberen zusammenzufassen sind, der Wert von auf allen Außenflächen ist. B! B¬ B]² !'² Cg,rB ¬ !'²ò !² ñg Zusätzlich wird eine maximale Verfeinerungstiefe vorgegeben, die vorschreibt, wie oft der Durchmesser eines Kontrollvolumens höchstens halbiert werden darf. Diese Beschränkung ist unbedingt nötigt, weil das Verfeinerungskriterium (1.27) kein Sättigungsverhalten zeigt, falls eine unstetige Funktion approximiert wird. Die Vergröberung endet auf dem Niveau der Grobgitterzellen. Hinweis: Das vorgeschlagene Kriterium zur Steuerung der Verfeinerung liefert allerdings nur dann brauchbare Ergebnisse, wenn die Konstanten , in einer dem Problem angepaßten Form festgelegt werden. Aufwendigere Strategien beruhen beispielsweise auf der Bewertung des diskreten Gradienten der numerischen Lösung [24, 42]. 24 KAPITEL 1. SIMULATION KOMPRESSIBLER STRÖMUNGEN Interpolation - Restriktion Weil die Freiheitsgrade des numerischen Verfahrens die konservativen Variablen auf den Zellen des Gitters sind, ist unmittelbar klar, wie nach der Teilung infolge lokaler Gitterweitenanpassung die Interpolation der eines Volumens Daten auf die entstehenden Volumen auszusehen hat: B! Bt!É Î £ É - Î £ ´]¸°* % óBt!¡¯Á² B°!ÉÞ;Bt!%É2±Bt!ó-³¸· í (1.28) Alle Werte auf den Teilvolumen werden auf den konstanten Wert der Ausgangszelle gesetzt. Dies ist vernünftig, weil die Ausgangszelle keine bessere Approximation der Lösung liefert, als sie durch die identischen Werte auf den feinen Zellen nach der Verfeinerung vorliegt. B !É Umgekehrt faßt die Vergröberung des Gitters einige ausgewählte Zellen zu einer größeren Zelle zusammen. Aufgrund der Erhaltungseigenschaft (1.9) müssen die in diesem Volumen vor und nach der Vergröberung die enthaltene Masse, Energie und der Impuls unverändert bleiben: Bt! Î £ b tB ! b Î £ É b Bt!É b ² (1.29) 1.3 Gesamtalgorithmus Der nachfolgend in wenigen übersichtlichen Schritten formulierte Algorithmus zum numerischen Verfahren zeigt, wie durch eine wiederholte Ausführung der Zeitschrittschleife das Gitter mit seinen assoziierten Daten für die diskrete Darstellung der Erhaltungsgrößen von einem Anfangszustand zur diskreten Zeit mit einer Verfeinerungssituation und den elementweise gespeicherten in einen Endzustand zur diskreten Zeit mit VerfeineErhaltungsgrößen rungssituation und Daten überführt wird. IÒ ÒÓ ¬ Ò! !ÒÓ ¬ Ò I ÒÓ ¬ Insofern kann schon auf dem Niveau des gesamten Gitters mit seinen Daten für die aktuelle diskrete Zeit und den elementweise definierten Werten der numerischen Approximation gewissermaßen eine objektorientierte Sicht eingenommen werden. Das Gitter selbst tritt darüber hinaus als Behälter (für Elemente und Flächen) in Erscheinung und sorgt dafür, daß bestimmte Aufgaben nacheinander auf allen Elementen bzw. Flächen ausgeführt werden (Iteration, vgl. Kap. 3.2.1, 5.7). B! !'² Im Kapitel zum Basisentwurf des Gitters wird detailliert darauf eingegangen, wie die Daten und die zugehörigen Funktionen derart hierarchisch gegliedert werden können, daß jede Aufgabe bereits dort bearbeitet wird, wo die dazu benötigten Informationen zur Verfügung stehen und dadurch viele schwach 1.3. GESAMTALGORITHMUS 25 gekoppelte Einheiten entstehen, damit das Gesamtproblem einer Parallelverarbeitung zugänglich gemacht werden kann (vgl. Kap. 2). Algorithmus 1.1: Start t end < t start + ∆t Anfangszustand: Die numerische Approximation !"# der Lösungsfunktion besteht für das Intervall true $ Stop "&% ')( *+",% '-*+.0/123/340*+"6578% '9*:"<;>=?*:"A@CB Die Zeitschrittweite =?* " ist nach der CFL-Bedingung $ " (1.24) aus den Daten ! "# zu bestimmen. Falls *+D "FEHG bricht der Algorithmus hier ab. I È £É Ê M £ L É LK JÍ J KHL M L ON Verfeinerungskriterium: Auf allen Flächen P # Q des Gitters ist das Verfeinerungskriterium R # Q (1.26) auszuwerten, gegebenenfalls sind die anliegenden Elemente zu verfeinern bzw. es darf vergröbert werden: ➞ È £É¡Ê S £/Ë £ m£É p£ É Sm É Ë É m£É p£ É I S ATVU XWZY :[Y \ S N U XZW Y :[ Y \ Numerische Flüsse: Auf allen Flächen P # Q des Gitters wird die numerische Flußfunktion ausgewertet. Dazu wird auf Daten aus den anliegenden Elementen zugegriffen (lesend). Der berechnete Wert wird auf den anliegenden Elementen gespeichert (schreibend): ➞ I Î £tÊ £ Ë £ Σ £ £/Ë Ë p£ Y] T_^ `Y ] b N L adc L S S `eX[ WZY 0\ adc adc Änderung des Verfeinerungszustands. Versteckte (innere) Zustandsänderung. Aufdatieren der Lösungsfunktion: Auf allen Elementen des Gitters wird der im vorigen Schritt berechnete Wert f # herangezogen, um den neuen Wert der numerischen Approximation (1.13) der Lösung zu bilden. Die neue diskrete Zeit wird zu * "657 '-* " ;g=h* " festgelegt. ➞ Änderung der numerischen Lösungsfunktion. Zeitschrittschleife: Der Zustand des Gitters und der Daten wird zum Anfangszustand für die Berechnung des nächsten Zeitschritts, die Abarbeitung wird an der Stelle des ersten Abschnitts fortgesetzt. Endzustand Stop ➞ Anfangszustand Endzustand: Der Algorithmus bricht ab, sobald die verlangte numerische Approximation der Lösung auf einem angepaßten Gitter für einen Zeitpunkt *:D berechnet ist. "E?G ( * "Ai7 4:* " @ 26 KAPITEL 1. SIMULATION KOMPRESSIBLER STRÖMUNGEN 27 Kapitel 2 Parallelrechner Zunächst sollte es ausreichen, einen Parallelrechner anzusehen, als bestehend aus einer Menge von Prozessoren, die in der Lage sind, ein Programm für eine Anwendung kooperativ zu bearbeiten. Dahinter verbirgt sich die Absicht, durch den zeitgleichen parallelen Einsatz von mehreren aktiven Bauelementen (Prozessoren) entscheidende zeitliche Gewinne zu erzielen. Allerdings darf man die Beschreibung eines Parallelrechners im ersten Absatz nicht dahingehend abändern, daß in der Formulierung ein Programm durch jedes Programm ersetzt wird (sonst wäre die Situation aus der Sicht der Anwendungsentwicklung auch ohne besonderen Reiz). Es gibt also Einschränkungen für die Klasse der zulässigen Programme und die Aufgabe der Programmentwicklung besteht grob gesprochen darin, zu einem festgelegten Problem ein geeignetes Programm“ zu konstruieren. ” Ist bei den seriellen Algorithmen die Entwicklung noch eher schwach von der Technologie getrieben, weil sowohl der Rechner als auch der auf ihm ausgeführte Algorithmus als eine kausale Abfolge dem intuitiven Verständnis sehr gut zugänglich sind, sieht die Situation bei der Programmierung und Algorithmenentwicklung für Parallelrechner völlig anders aus: Hier dominiert die zur Verfügung stehende Technik das Geschehen sowohl in der Theorie wie bei den Ausführungsmodellen als auch bei Programmiersprachen, Programmiermodellen und Standards für die Praxis. Deshalb sollte der Zugang nicht zu abstrakt formuliert werden, schließlich kann kein Programmentwurf die teilweise starken Einschränkungen, die der reale Einsatz eines entsprechenden Simulationsprogramms bereit hält, einfach ignorieren. Realer Einsatz erzwingt eben auch Entscheidungen zugunsten der Effizienz, also zugunsten eines an den Ressourcen orientierten Programmentwurfs. Andererseits sollte klar sein, daß gerade die Möglichkeit zur Parallelverarbeitung die Programmausführung großzügig mit Prozessorleistung und Hauptspeicherkapazität ausstattet, wovon, wann immer der Algorithmenentwurf davon profitiert, Gebrauch gemacht werden sollte. 28 KAPITEL 2. PARALLELRECHNER 2.1 Einsatz von Parallelrechnern 2.1.1 Parallelrechnersysteme Ein kurzer Blick auf die zur Zeit verfügbaren Parallelrechnersysteme und deren entscheidende Merkmale kann hilfreich sein zu verstehen, mit welchen Anforderungen und Rahmenbedingungen die Programmentwicklung für Parallelrechner umgehen muß. Die Taxonomie der gebräuchlichen Parallelrechnerarchitekturen (vgl. Abb. 2.1) gliedert die verschiedenen Systeme in Multicomputer und Multiprozessoren [37]. Das übergeordnete Merkmal ist hier der für eine Anwendung sichtbare Adreßbereich: Multiprozessoren besitzen einen homogenen globalen Adreßbereich, Multicomputer hingegen sind nicht in der Lage, Daten die verschiedenen Prozessoreinheiten zugeordnet sind, über diese Grenzen hinweg zu identifizieren. Dies entsprach den technischen Möglichkeiten zu Anfang der Entwicklung: Einerseits konnte man anstelle von nur einem auch mehrere Prozessoren an einen Hauptspeicher anschließen, andererseits war es in Computernetzen üblich, daß nur Daten in einheitlichem Format zwischen den beteiligten Rechnern ausgetauscht werden konnten. Erst an zweiter Stelle erfolgt eine Klassifikation nach der Verbindungskomponente, die exklusiv wie ein Bus, oder verteilt, wie ein Netz beschaffen sein kann. Mittlerweile verwenden viele Hersteller auch Kombinationen. Busartige Systeme sind oftmals günstig, falls wenige Prozessoren in einem verteilten Rechnersystem zusammenhängen sollen, weil dann leistungsfähige Technologien eingesetzt werden können. Parallele und verteilte Computer Multiprozessoren (gemeinsamer Adressbereich) Multicomputer (privater Speicher) Bus Verbindungsorientiert Bus Verbindungsorientie rt CRAY T90 SGI Origin 2000, HP Convex Exemplar Cluster aus Arbeitsplatzrechner n in einem LAN IBM SP , CRAY T3E, Parsytec CC Abbildung 2.1: Einfache Taxonomie der Parallelrechnersysteme [37]. 2.1. MOTIVATION 29 Möchte man hingegen sehr viele (im Moment mehr als 20) Prozessoren betreiben, wird man netzartige Verbindungen bevorzugen. Verbindungsnetze sind weniger leistungsfähig, können aber größere räumliche Entfernungen überbrücken und lassen grundsätzlich eine skalierbare Architektur zu. Definition: Eine Parallelrechnerarchitektur, also das Schema der Verbindungen zwischen den einzelnen Prozessoren, wird skalierbar genannt, falls für zwei beliebige Prozessoren des Parallelrechners die Zeit, die für den Austausch eines Datums erforderlich ist, weder von der Anzahl der Prozessoren im Parallelrechner, noch von einem gleichzeitigen Datenaustausch zwischen anderen Prozessoren abhängt. Hinweis: Das verteilte Simulationsprogramm (vgl. Kap. 4) basiert auf dem Message Passing Programmiermodell (vgl. Kap. 2.3.1) und ist damit in erster Linie für verbindungsorientierte Multicomputer wie z.B. die IBM RS 6000 SP (rechts unten in der Abbildung) ausgelegt. } 2.1.2 Motivation Eine parallele Verarbeitungsstrategie wird für ein bestimmtes numerisches Verfahren in erster Linie entwickelt, um die hohe Rechenleistung der Parallelrechnersysteme nutzen zu können. Eine differenziertere Aufstellung nach drei Zielrichtungen sieht so aus: 1. Für eine festgelegte Problemgröße soll möglichst schnell ein Ergebnis der Berechnung vorliegen, um z.B. effizient Parameterstudien durchführen zu können: Die Programmausführung wird durch die Parallelverarbeitung beschleunigt. 2. Die Aufgabenstellung soll um einen bestimmten Faktor vergrößert werden, ohne die Laufzeit nachhaltig zu verlängern: Die Problemgröße und die Leistung des verwendeten Rechnersystem werden gleichmäßig, also skaliert erhöht. 3. Die gewünschte Problemgröße benötigt Ressourcen, die von Einprozessorsystemen aus konstruktiven Gründen nicht bereitgestellt werden können. Beispielsweise ist der von einen Prozeß adressierbare Hauptspeicher durch die Länge der verwendeten Adressen begrenzt: Manche durch die Technologie vorgegebenen Grenzen von Einprozessorsystemen wenden sich auf Parallelrechner nicht an. Die ersten zwei Zielvorgaben für ein Parallelisierungsvorhaben, nämlich Beschleunigung und Skalierbarkeit werden im Abschnitt über die Leistungsmessung für parallele Verfahren zu strikten Meßvorschriften ausgebaut, anhand derer die Qualität eines parallelen Programms gemessen werden kann. 30 KAPITEL 2. PARALLELRECHNER 2.1.3 Parallelverarbeitungsstrategie Definition: Unter Parallelisierung eines Algorithmus soll hier seine Implementierung mit dem Ziel einer effizienten Parallelverarbeitung verstanden werden. Diese Definition ist so gestaltet, daß der zur Lösung eines bestimmten Problems ausgewählte Algorithmus durch die Parallelisierung nicht verändert werden soll, die Anpassungen für eine parallele Verarbeitung beziehen sich alleine auf den Programmentwurf bzw. dessen Umsetzung (Implementierung). Dadurch lassen sich die Ziele aus dem vorangegangenen Abschnitt von der Frage nach dem optimalen numerischen Verfahren, das dem Algorithmus zugrunde liegt, trennen. Der vorgeschlagene Ansatz geht also vereinfachend davon aus, daß an erster Stelle das günstigste numerische Verfahren für eine bestimmte Problemstellung auszuwählen ist, und dann erst eine Strukturierung für die Parallelverarbeitung vorgenommen wird. Jede Strategie zur Parallelisierung wird sich bemühen, im vorliegenden Algorithmus möglichst viele voneinander unabhängige Einheiten zu identifizieren, die den Ausgangspunkt für die Parallelverarbeitung bilden. Diese Einheiten können sowohl im Bereich der Instruktionen des Programms gefunden werden (Programmparallelität) oder als an Daten gebundene Operationen, was einem objektorientierten Ansatz, der Operationen mit Daten verbindet, entgegenkommt (vgl. Kap. 3.1). Im zweiten Fall spricht man von einem datenparallelen Ansatz [15]: Definition: Datenparallelität liegt vor, wenn auf jedes Element einer Menge von Daten jeweils die selbe Operation unabhängig angewendet werden muß. Läßt sich eine solche Datenmenge angeben, ist die Verteilung des Aufwands der Operationen implizit durch die Verteilung der Daten realisierbar. Im datenparallelen Ansatz besteht die Aufgabe darin, jene unabhängigen Operationen zu finden, die gleichmäßig auf den gesamten Datensatz angewendet werden sollen. In der Praxis darf man allerdings nicht erwarten, daß z.B. das gesamte numerische Verfahren eine solche Eigenschaft aufweist, vielmehr besteht die Unabhängigkeit in der Regel nur für kleine Teilalgorithmen des Gesamtverfahrens. Konkret bedeutet dies, daß nach jeder unabhängigen parallelen Abarbeitung eines Teilalgorithmus die Abhängigkeiten, die durch das Gesamtverfahren zwischen den Daten vorgegeben sind, restauriert werden müssen. Hier liegt der Schlüssel zu den Kriterien, nach denen die Aufteilung der Daten vorgenommen werden muß. 2.1. MOTIVATION 31 Methodik zur Parallelisierung: Die Parallelisierung eines Problems läßt sich methodisch in vier Schritte zerlegen (vgl. Abb. 2.2) [10], wobei sich die angegebenen Beispielsituationen auf einen datenparallelen Ansatz beziehen: 1 Partitionierung: Das Problem soll in viele möglichst unabhängige Teilprobleme zerlegt werden. Eine große Anzahl von Teilproblemen läßt eine feingranulare Aufteilung des Aufwands und dadurch auch den Einsatz einer großen Anzahl von Prozessoren zu. Beispiel: Die elementweise Berechnung der lokalen Steifigkeitsmatrizen in einem Finite Elemente Verfahren oder die flächenweise Berechnung der numerischen Flüsse in einem Finite Volumen Verfahren können als atomare d.h. nicht mehr weiter zu zerlegende Teilprobleme angesehen werden. 2 Kommunikation: Die Zusammenhänge zwischen diesen Teilproblemen müssen herausgefunden werden. Dazu ist zu untersuchen, welche Teilprobleme auf welche Art miteinander gekoppelt (verbunden) sind. Teilprobleme Problem Partitionierung Kommunikations− struktur Agglomeration Prozessorzuweisung Abbildung 2.2: Vierstufiges Vorgehen zur Parallelisierung durch Partitionierung des Problems, Analyse der Kommunikationsstruktur, Agglomeration und Prozessorzuweisung. 32 KAPITEL 2. PARALLELRECHNER Beispiel: Für ein numerisches Verfahren zeigt in der Regel bereits die mathematische Struktur der Diskretisierung die Zusammenhänge zwischen den Daten: Häufig findet man Zugriffe entlang der geometrischen Relationen Element-Knoten, Element-Nachbarelement, Fläche-Element usw. 3 Agglomeration: Die Teilprobleme sollen zu größeren Einheiten zusammengefaßt werden, innerhalb derer möglichst viele der im zweiten Schritt identifizierten Zusammenhänge bereits enthalten sind. Agglomeration bietet sich an, wenn das Problem entsprechende Strukturen aufweist. Die Anzahl der zu bildenden Einheiten ist von der Anzahl der einzusetzenden Prozessoren (Prozesse) unabhängig. Beispiel: Verfeinerungsstrukturen oder algebraische Strukturen des numerischen Verfahrens wie z.B. in Multilevel- oder Mehrgitterverfahren [5] definieren Zusammenhänge, die auch eine Basis für die Agglomeration darstellen (vgl. Kap. 4.1.1). 4 Prozessorzuweisung: Die jetzt wesentlich kleinere Anzahl von Agglomerationseinheiten wird auf die Anzahl der verfügbaren Prozessoren abgebildet. Hierzu ist vorausgesetzt, daß erheblich mehr dieser Einheiten gebildet wurden, als letztlich Prozessoren eingesetzt werden sollen. Beispiel: Betrachtet man die im Zuge der Agglomeration gebildeten Einheiten als Knoten eines Graphen mit einem ihrem Operationsinhalt entsprechenden Gewicht und deren Zusammenhänge untereinander als gewichtete Kanten dieses Graphen dann kann das Problem der Prozessorzuweisung (engl.: mapping) als allgemeines Partitionierungsproblem für einen ungerichteten Graphen angesehen werden (vg. Kap. 4.6.1). 2.2 Ausführungsmodelle Um theoretische Vorhersagen zur Ausführungszeit einer parallelen Anwendung begründen zu können, muß ein Modell festgelegt werden, mit dem das reale System Parallelrechner beschrieben wird. 2.2.1 Von Neumann Modell Das anerkannte Modell für einen Rechner mit einem Prozessor und einer Verbindung zu seinem völlig homogenen Hauptspeicher ist das Von Neumann Modell (vgl. Abb. 2.3) [18]. Definition: Das Von Neumann Modell nimmt an, daß der Prozessor jedes Datum und jede Anweisung aus dem Hauptspeicher lädt, wozu jedesmal eine konstante Zeit kjlFm notwendig ist. Die nachfolgende Ausführung der Anwei3n sung benötigt ihrerseits eine Zeit , die nur von der Art der Anweisung < < `. ` 2.2. AUSFÜHRUNGSMODELLE 33 < WV ` abhängt. Das Schreiben der Ergebnisse in den Hauptspeicher soll ebenfalls eine konstante Zeit po jq erfordern. Weil die Zeiten zum Laden bzw. Schreiben der Daten und für die Ausführung einer Anweisung nicht von der Vorgeschichte abhängen, läßt sich die Gesamtlaufzeit für manche numerische Algorithmen mit diesem Modell leicht vorhersagen: Dazu sind alle Lade-, Schreib- und arithmetischen Operationen des numerischen Verfahrens für eine festgelegte Problemgröße aufzusummieren. 2.2.2 PRAM Modell Die logische Ausdehnung des Von Neumann Modells auf die parallele Programmausführung stellt das PRAM Modell dar (vgl. Abb. 2.3) [18]. Definition: Das PRAM (Parallel RAM) Modell geht von mehreren Prozessoren, die einen gemeinsamen Hauptspeicher teilen, aus und sieht jedes Teilsystem Prozessor-Hauptspeicher als Von Neumann Architektur an. Hinzu kommt die Annahme, daß alle Operationen, also auch jene, die den gemeinsam genutzten Speicher berühren, von allen Prozessoren gleichzeitig und ohne gegenseitige zeitliche Beeinflussung ausgeführt werden können. Das PRAM Modell vermittelt bereits eine entscheidende Ausdehnung des Einblicks in die Programmausführung auf Parallelrechnern, denn die Programmausführung verläuft im Unterschied zur sequentiellen Situation abwechselnd in zwei Phasen: - Der betrachtete Prozessor bearbeitet gerade den ihm zugeordneten Instruktionsstrom. - Der betrachtete Prozessor wartet algorithmenbedingt die Ausführung eines Instruktionsstromes auf einem anderen Prozessor ab. Demgegenüber befindet sich ein Von Neumann Rechner immer in der ersten Phase. Die Programmausführung auf einem Mehrprozessorsystem weist in der Prozessor Hauptspeicher Prozessor Prozessor Prozessor Hauptspeicher Abbildung 2.3: Von Neumann Modell (links) und davon abgeleitetes PRAM Modell eines Multiprozessors (rechts) für die theoretische Betrachtung der Laufzeit einer Programmausführung (Anwendung). 34 KAPITEL 2. PARALLELRECHNER Analyse unter den Annahmen des PRAM Modells eine nichttriviale Laufzeitstruktur auf, die aus einer abwechselnden Folge dieser zwei Phasen besteht. Bemerkung: Für einige einfache Algorithmen mit einer festgelegten Aufteilung der zu bearbeitenden Teilprobleme kann die Laufzeitstruktur durch theoretische Überlegungen ermittelt werden, aus der wiederum die Programmlaufzeit mit dem PRAM Modell bestimmt werden kann. Ein solcher Algorithmus ist z.B. die systolische Multiplikation zweier Matrizen (block-multiply-roll scheme) [28]. } 2.2.3 Bulk Synchronous Parallel Modell Bedingt durch die großzügigen Annahmen im PRAM Modell für einen Multiprozessor hängt die Beschleunigung (2.1) allein vom Algorithmus und der gleichmäßigen Aufteilung der Operationen ab. Die Praxis sieht aber oft anders aus: Verbindungsnetzwerke oder gemeinsamer Speicher bedingen in der Regel einen gegenseitigen Ausschluß und damit zusätzliche Kommunikationsund Wartezeiten, die nicht aus der statischen Analyse des Algorithmus, der Datenaufteilung und dem PRAM Modell vorhergesagt werden können. Deshalb wurden weitere Modelle entwickelt, die mit zusätzlichen Parametern ausgestattet sind. Bemerkung: Auf der Seite der Programmentwicklung wurden die eingeschränkten Möglichkeiten der Rechnersysteme ebenfalls zur Kenntnis genommen, was u.a. zu Strategien wie dem Latency-Hiding“ geführt hat. Gemeinsam ” ist solchen Techniken, die Reihenfolge der logischen Programmausführung an einigen Stellen zur Laufzeit zu bestimmen, weil erst dann die Option mit der kleinsten Wartezeit erkannt wird. Die Programmausführung wird dadurch allerdings nichtdeterministisch, was eine theoretische Betrachtung nahezu unmöglich macht. } Das Bulk Synchronous Parallel (BSP) Model [39] verfolgt einen Mittelweg zwischen Theorie und Praxis, wobei die Forderungen an parallele Algorithmen, die sich durch das BSP Modell beschreiben lassen, so gewählt sind, daß sie noch effiziente Implementierungen zulassen. Das BSP Modell unterteilt einen Parallelrechner in drei funktionale Einheiten: 1. Eine Anzahl an Komponenten, von denen jede Berechnungen oder externe Speicheranforderungen bearbeiten kann. 2. Ein Router, d.h. ein Verbindungsnetzwerk, das Nachrichten (vgl. Kap. 2.3.1) zwischen Paaren von Komponenten transportiert. 3. Ein globaler Mechanismus zur Synchronisation mehrerer oder aller Komponenten in festgelegten Zeitabschnitten. Die Programmausführung läuft damit in Supersteps, also strukturiert in größere Blöcke, ab. Entscheidend 2.3. PROGRAMMIERMODELL 35 ist, daß die Zeitspanne, die für einen Schritt aufgewendet wird, immer gleich bleibt. Falls eine Komponente des Rechners die Ausführung des Blocks nicht innerhalb des Supersteps abschließen kann, wird ein weiterer Schritt für diesen Anweisungsblock eingeschoben. Nach dem Ablauf der Synchronisation sind alle Nachrichten und alle Zugriffe auf den Speicher einer externen Komponente konsistent übertragen. Bemerkenswert ist, daß versucht wird statisch festzulegen, welche Teile der Programmausführung parallel stattfinden sollen. Hier liegt das Bindeglied zur Agglomeration aus der Methodik zur Parallelisierung (vgl. Kap. 2.1.3), wenn von einem programmparallelen Ansatz [15] ausgegangen wird. Alle Algorithmen sind so zu strukturieren, daß die Ausführung jedes Blocks in der Zeit eines Supersteps abgeschlossen werden kann. Dem liegt die Idee zugrunde, durch die Emulation mehrerer virtueller Prozessoren auf einer physikalischen Komponente des BSP Rechners eine Lastverteilung auf dem Niveau der Ausführungsblöcke durchzuführen. Die wesentliche Konsequenz, die aus der Untersuchung des BSP Modells für die Entwicklung des parallelen Simulationsprogramms gezogen wird, ist die strikt synchrone Auslegung aller parallelen Teilalgorithmen. Eine Gliederung nach Anweisungsblöcken findet nicht statt, vielmehr sind die Zeiträume zwischen Synchronisierungspunkten unterschiedlich lang. Eine gleichmäßig verteilte Ausführungszeit über alle Komponenten hinweg muß durch die explizit im Algorithmus vorgesehene dynamische Lastverteilung erfolgen (vgl. Kap. 4.6). 2.3 Programmiermodell Bei der Untersuchung einiger etablierter Modelle zur Programmierung von Parallelrechnern wird man feststellen, daß die meisten davon sich stark am Machbaren und damit an der verfügbaren Rechnertechnologie orientieren. Dies ist einigermaßen natürlich, denn der Anwender eines Parallelrechners möchte bei der Entwicklung seiner Programme zunächst sicherstellen, daß die teuer bezahlte Leistung auch absolut effizient eingesetzt wird. Die Betrachtung beschränkt sich hier auf das Message Passing Programmiermodell, das in unterster Schicht des parallelen Simulationsprogramms dazu beiträgt, in grundlegenden Funktionen von der betreffenden Rechnerarchitektur abstrahieren zu können (vgl. Kap. 5.8). Die technologischen Wurzeln des Message Passing Programmiermodells liegen im Bereich der Programmentwicklung für Multicomputer, weshalb es in seiner Definition besonders auf die technologischen Grenzen dieser Systeme eingeht. 36 KAPITEL 2. PARALLELRECHNER 2.3.1 Das Message Passing Programmiermodell Das Message Passing Programmiermodell sieht den Austausch von Daten zwischen zwei oder mehreren völlig autonomen Prozessen als Kernaufgabe an. Auf die Möglichkeit Daten aus den Adreßbereichen der verschiedenen Prozesse identifizieren zu können, wird bereits im Ansatz verzichtet. An die Stelle der Identifikation von statischen Speicherorten auf Prozeßniveau tritt die Identifikation von Nachrichten, also der mobilen Daten: Praktisch alle Ansätze stellen sicher, daß Nachrichten unverfälscht zwischen identifizierten Prozessen in deterministischer Reihenfolge ausgetauscht werden können. Definition: Unter Nachricht wird im Message Passing Programmiermodell eine Menge von Daten verstanden, die von einem Prozeß der verteilten Anwendung einem anderen zugänglich gemacht wird, wobei ein Einverständnis über Bedeutung und Inhalt (Typ) auf der Basis eines eindeutigen Namens für die Nachricht erreicht wird. Das Message Passing System, das gegenüber dem Anwender die im Message Passing Programmiermodell festgelegte Funktionalität als technische Lösung realisiert, hat keine Kenntnis davon, wie die Nachrichten mit den Daten und Prozeduren der Anwendung zusammenhängen, diese Information ist erst auf dem Niveau der Anwendung durch Identifikation der Prozesse und Namenskonventionen für die Nachrichten angelegt. Damit lassen sich die notwendigen Funktionen einer entsprechenden Programmiersprache oder Bibliothek zusammenfassen (vgl. Abb. 2.4): Prozess Anwendung Identifikation Anwendung Nachricht anfragen ? Nachricht abgeben 4 8 Message Passing Bibliothek Nachricht erhalten Message Passing Bibliothek Nachricht ausliefer n Nachricht codieren Eingegangene Nachri chten Nachricht decodieren Abbildung 2.4: Schematischer Nachrichtenaustausch im Message Passing Programmiermodell: Über die Prozeßgrenze hinweg findet die Identifikation des Adressaten und der Austausch der Nachricht statt. 2.3. PROGRAMMIERMODELL 37 Funktionsumfang eines Message Passing Systems 4 Die Möglichkeit unter allen beteiligten Prozessen einzelne Prozesse oder Prozeßgruppen identifizieren zu können. Mögliche Erweiterungen sind logische Verbindungen in einer Prozeßtopologie (Baum, Ring, Torus, Würfel usw.). Funktionen zum Versenden und Empfangen von Nachrichten zu bzw. von identifizierten Prozessen, eventuell gegliedert nach synchronem (blockierendem) und asynchronem (nicht blockierendem) Nachrichtenaustausch. Falls die Darstellung der Daten (z.B. Gleitkommazahl) nicht einheitlich ist, wird durch das Message Passing System eine Konversion (Codierung) vorgenommen. Hat man sich mit dem Message Passing Modell bereits auf einen Standard im Entwurf für verteilte parallele Programme geeinigt, dann liegt es nahe, auch die Gliederung der Funktionalität in Prozeduren und deren Aufrufsyntax für die gängigen Programmiersprachen zu vereinheitlichen. Dies ist mit der Verabschiedung des Message Passing Interface Standards MPI geschehen, der im Jahr 1993 als Entwurf vorgestellt worden war. Der MPI Standard Der Message Passing Interface Standard MPI [26] ist derzeit der wichtigste Vertreter eines Standards für Implementierungen des Message Passing Modells. Das im Rahmen dieser Arbeit entwickelte parallele Simulationsprogramm greift nur auf einen kleinen Ausschnitt aus dem standardisierten Funktionsumfang einer MPI-konformen Kommunikationsbibliothek zurück: r r Funktionen zur Identifikation der Prozesse, von denen die jeweiligen Teilgitter bearbeitet werden. r Punkt zu Punkt Kommunikation mit codierten oder binären Daten. r Globale (engl.: all to all) Kommunikationsvorgänge zur Verteilung von einzelnen Werten oder Vektoren mit verschiedenen Datentypen. Globale (kollektive) Operationen zur Bildung von Summe, Maximum oder Minimum einer Gleitkomma- oder Integerzahl. Bemerkung: Message Passing ist keine Strategie zur Parallelisierung, auch wenn manche Formulierungen dies suggerieren. Message Passing ist eine Strategie, von den Verbindungen innerhalb eines Parallelrechners Gebrauch zu machen, und schränkt die Auswahl des Vorgehens zur Parallelisierung ofts mals tatsächlich auf einen datenparallelen verteilten Ansatz [15] ein. 38 KAPITEL 2. PARALLELRECHNER 2.4 Leistungsmessung Als Motivation für die parallele Verarbeitung einer Anwendung werden Gründe genannt, die sich mehrheitlich auf die wesentlich höhere erreichbare Rechenleistung beziehen. Die aus der Parallelisierung resultierenden Leistungsgewinne müssen daher gemessen und bewertet werden. Ausführungszeit Definition: Als Ausführungszeit t eines Programmlaufs (Anwendung) auf einem bestimmten Rechnersystem wird die kürzeste erreichbare Zeitspanne, gemessen in der Realzeit (engl.: wall-clock time), zwischen dem Start und dem regulären Beenden der Anwendung definiert. Diese Definition läßt sich sinngemäß auch auf die Ausführungszeit eines Teilprogramms ausdehnen. Sie schließt die gleichzeitige Abarbeitung verschiedener Anwendungen auf einem Rechner aus, weil nur ein exklusiver Betrieb die kürzeste Verweilzeit realisieren kann. Beschleunigung Definition: Als Beschleunigung udvxw+w (engl.: Speedup) der Programmausführung durch die Parallelverarbeitung wird das Verhältnis der Ausführungszeiten tzy{| , tzy~}A| des parallelen Verfahrens auf identischen Rechnersystemen mit verschiedenen Prozessorzahlen {} definiert: u vxw+w y{}A| tzy}A| t,y{| {} (2.1) Häufig wird als Bezugswert die Ausführungszeit auf einem Rechner mit einem Prozessor tzy}6| gewählt: udvxw+wy{| tzy36| tzy{| { (2.2) Ein Beschleunigungswert u vxw+w y{}A| bzw. u vxw+w y{|`>{ heißt superlinear. Diese Definition der Beschleunigung läßt offen, in welcher Beziehung die Programme zueinander stehen, die auf den { bzw. } Prozessoren eingesetzt werden, insbesondere falls } ist. Für die Praxis ist jedoch die Forderung, es solle grundsätzlich gegen die absolut optimale sequentielle Implementierung getestet werden (2.6), wenig geeignet, denn sie dehnt die beabsichtigte Bewertung des Entwurfs für das verteilte Programm auf die Wahl der numerischen Verfahren, der Algorithmen und der Programmiersprache aus. Es erscheint vernünftig und zulässig, ein Programm, das für eine variable Anzahl von Prozessoren entworfen wurde, gleichermaßen auf { und } Prozessoren zu messen, selbst wenn } ist (vgl. Kap. 6.3.1, Tab. 6.2). 2.4. LEISTUNGSMESSUNG 39 Effizienz Definition: Direkt von der Beschleunigung abgeleitet ist die Effizienz der Parallelisierung, die als Verhältnis von realer und theoretisch möglicher Beschleunigung gegeben ist: 36 uvxw+wy{}A| Z {A} (2.3) Die Grundlage für diese Definition ist das Theorem zur Begrenzung der Beschleunigung (2.6). Skalierung Definition: Sei t <yC| die Zeit die für das Problem auf einem Rechner mit Prozessoren benötigt wird, dann ist das -skalierte Problem H¡ zu dadurch bestimmt, daß auf einem idealisierten Einprozessorsystem (Von Neumann Architektur) für die gemessenen Ausführungszeiten t¢_£ ¤<y|¥¦ ¡~t ¤<y| gilt. Dann wird für alle 8~{§©¨ als Skalierung (Skalierfähigkeit, Skalierbarkeit, engl.: scalability) ª w+vX«3y8{| des parallelen Verfahrens auf { Prozessoren das Verhältnis ª w+vX« yC8{|Z t y{| t ¬£ yC­¡3{| A{® (2.4) bezeichnet. Für {¯ hat man den von { unabhängigen Ausdruck: ª w+vX« yC|<Z t<y| t ¬£ yC| (2.5) Falls der für das betrachtete Verfahren erreichbare Speedup durch das Verhält nis der Prozessorzahlen begrenzt ist, d.h. es gilt u vxw+w y¡{{|h°±¬ £ ² , dann folgt für die Skalierung ª w+vX« y8{|h° . Diese Schranke für die Beschleunigung ist nicht willkürlich gewählt: Erwartungsgemäß sollte das Verhältnis der Prozessorzahlen der maximal erreichbare Speedup sein, wie das nachfolgende Theorem feststellt. Begrenzung der Beschleunigung Theorem: Unter der Voraussetzung, daß als Referenzwert tzy36| die Laufzeit eines in jeder Hinsicht absolut optimalen sequentiellen Programms für die festgelegte Problemstellung in (2.2) eingesetzt wird, ist die durch eine parallele Verarbeitung erreichbare Beschleunigung durch u vFw+w y{|°-{ begrenzt [28]. (2.6) 40 KAPITEL 2. PARALLELRECHNER Beweis: Es wird ein superlinearer Speedup uvFw+wy{|³´{ angenommen. Dann läßt sich ein sequentieller Algorithmus durch logisches Nacheinanderausführen der parallelen Teilprogramme konstruieren [28], der im Widerspruch zur Voraussetzung schneller als die Referenzimplementierung ist. µ Im praktischen Versuch werden unter Umständen Beschleunigungswerte beobachtet, die größer als das Verhältnis der Prozessorzahlen sind, was aber kein Gegenbeispiel zur obigen Behauptung darstellt, sondern mit technischen Eigenschaften der verwendeten Rechnerarchitekturen begründet werden kann: Moderne Einprozessorsysteme, aus denen manche Parallelrechner zusammengesetzt sind, bearbeiten Probleme mit kleinerem Datenumfang durch die Hierarchie ihrer Speicherkomponenten schneller – und sind damit keine echten Realisierungen des Von Neumann Modells, das dem Theorem implizit zugrunde liegt (vgl. Kap. 2.2.1). 2.4.1 Berücksichtigung der dynamischen Lastverteilung Eine dynamische Lastverteilung wird in einem parallelen Programmentwurf vorgesehen, falls davon auszugehen ist, daß die Belastung der einzelnen Prozessoren während der Programmausführung den anfangs eingestellten optimalen Zustand verläßt. Hierbei stellt sich allerdings die Frage, welche Beschleunigung bei einer vorgegebenen Schranke für die Ungleichverteilung der Prozessorbelastung überhaupt theoretisch erreichbar ist. Intuitiv ist klar, daß es wohl keinen Sinn macht, einerseits nach optimalem Speedup zu fragen, wenn andererseits aus Gründen, die in der Problemstellung zu suchen sind, in einer Anwendung sehr großzügige Schranken für die dynamische Lastverteilung gewählt werden. Da sich die Definition der Effizienz eines parallelen Verfahrens (2.3) auf die erreichbare Beschleunigung und damit auf das Theorem (2.6) bezieht, liegt es nahe, die Aussage des Theorems auf die Situation mit ungleich verteiltem Aufwand zu erweitern. Theorem: Gelte für die Ausführungszeit t p¶ y36| der { Teilprobleme ·C¸ ·¹º¸Z»Z»Z»Z¸ einer parallelen Anwendung auf einem idealisierten Einprozessorsystem mit einer Konstanten ¼½§½¾¿{dÀ : ÁH Ì8Í §-ÿFk{Ä Åt ¶ y36|bƼÈtÇ §-ÿFk{Ä Ç Åt ËAy36|9ÎÐÒ Ï Ñ ¼ t t Ç { É Ê ¹º tpËAy3| dann ist die erreichbare Beschleunigung der parallelen Ausführung auf { Prozessoren durch { (2.7) uvxw+wy{|¯Æ udÇ vxw+wy{| ¼ begrenzt. 2.4. LEISTUNGSMESSUNG 41 Beweis: Für die parallele Bearbeitung wird ein PRAM Parallelrechner vorausgesetzt: Die Gesamtausführungszeit t ist das Maximum aller Summen aus der v « Bearbeitungszeit t · X ¦t p¶ und der algorithmenbedingten Wartezeit t · ·ÔÓ« für  jeden Prozessor . Für die gemessene Beschleunigung udvxw+wy{| erhält man mit den Argumenten aus dem Beweis zu Theorem (2.6) uvxw+wy{|Z tzy| tzy{| v « ·k¹º t · X Õ v « ·Ó« ÖØ×AÙ t · X Û t · ·¹º»Z» Ü &Ú (2.8) denn die algorithmenbedingten Wartezeiten treten bei einer sequentiellen Abarbeitung des Algorithmus nicht auf. Vernachlässigt man weiterhin die lokalen algorithmenbedingten Wartezeiten, erhält man die (formale) Abschätzung u vxw+w y{|° v « ·k¹º t · X v « ·k¹ºX»Z» t · X Õ Ù ÖØ×Ý (2.9) aus der wiederum die Behauptung folgt. Die Abschätzung (2.9) ist genau dann scharf, wenn der Algorithmus optimal parallel ausführbar ist (engl.: embarassingly parallel). µ Steuerung der Lastverteilung Definition: Im Rahmen dieser Untersuchung wird als Steuerung der dynamischen Lastverteilung ein Kriterium bezeichnet, das den Vorgang der Neuberechnung einer Gitteraufteilung und der Umverteilung des Gitters auslöst, wobei davon ausgegangen wird, daß die Aufteilung selbst vom Kriterium unabhängig ist und jeweils den bestmöglichen Zustand annimmt. Die Ungleichung (2.9) zeigt vor diesem Hintergrund, wie die Steuerung der Lastverteilung auszusehen hat, d.h. wann eine neue Verteilung des Gitters stattfinden soll: Das Kriterium ist die maximale Abweichung des lokalen Aufwands vom Mittelwert; mit anderen Worten: Die längste Bearbeitungsdauer dominiert das Geschehen und legt den erreichbaren Speedup fest: Wird beispielsweise eine maximale Abweichung der Laufzeit von v « t · X °)Þàßá { É Ê ¹º v « t Ê X âã ®Þät Ç v X « Á å¿k {VÞ­§9¾k{OÀ (2.10) vorgegeben und eingehalten, ergibt sich daraus für die theoretisch erreichbare Beschleunigung udÇ vxw+wy{| { Þ Îkæ ° »ç »è Ñ u vFw+w kÎ æ é ° Ñ { Ç (2.11) Für die Beschleunigung, die in der realen Ausführung des Programms gemessen wird, gilt uvFw+wêÆ udÇ vxw+wë§ì¾ í {dÀ . Die Anwendung dieser Ergebnisse auf eine konkrete Situation ist allerdings schwierig, denn solange die genaue Verteilung des Aufwands nicht exakt bekannt, sondern nur durch eine Schranke (2.10) abgeschätzt ist, kann auch kein Zielwert für die Beschleunigung in die Berechnung der Effizienz des Verfahrens (2.3) eingesetzt werden. 42 KAPITEL 2. PARALLELRECHNER Hinweis: Obwohl die Begrenzung der maximalen Abweichung (2.10) an der richtigen Stelle angreift und außerdem eine untere Grenze von ÖØ×ÝÙ yîOF<ïy~Þðïä| y{Øïñ6||t Ç v X « v « °ñt · Á å { impliziert, kann von der Steuerung der dynamischen Lastverteilung im parallelen Simulationsprogramm auch die Abweichung der kürzesten Ausführungszeit vom Mittelwert kontrolliert werden: Es sind somit zwei Konstanten ò«óô +õ und +õ festzulegen, mit der Eigenschaft, daß die dynamische Lastverteilung geòxö nau dann eine neue neue Aufteilung des Gitters berechnet und durchführt, wenn eine der Ungleichungen ÖØ×ÝÙ v « v « yò«óô +õ F<ïy~Þðïä|py{Øï|3|÷t Ç X °ät · X Æòxö verletzt ist (vgl. Kap. 4.6.1, 5.6.1). X Á 3õ t Ç v X « { (2.12) s 43 Kapitel 3 Objektorientierter Basisentwurf für das Simulationsprogramm Nachfolgend werden die zentralen Ideen des Programmentwurfs für ein verteiltes paralleles adaptives Gitter vorgestellt. Die Darstellung orientiert sich der Form nach an dem, was in der objektorientierten Analyse und Programmentwicklung in neuerer Zeit entwickelt wurde [7]. Dadurch wird erreicht, daß die Strukturen und Algorithmen, die letztendlich in der Implementierung ein- und umgesetzt sind, auch ohne Zugriff auf den Quellcode verständlich und auf ähnliche Probleme anwendbar sind. Die Dokumentation des Programmentwurfs und der Implementierung erhält dadurch außerdem eine günstige Gliederung: r r Alle grundlegenden Strukturen des Entwurfs, Konzepte und Algorithmen werden in diesem Kapitel besprochen. r Die Erweiterungen, die es ermöglichen, das Programm auf verteilt parallelen Rechnerarchitekturen auszuführen, sind im nächsten Kapitel dargestellt (vgl. Kap. 4). Die Konzeption der Implementierung, ihre Strukturierung und und Realisierung mit den Mitteln der Programmiersprache C++ finden sich in einem weiteren Kapitel (vgl. Kap. 5). Hinweis: Es wird davon abgesehen, in der Dokumentation direkt mit den Klassen-, Methodennamen usw. aus dem Vokabular des Quellcodes umzugehen. Einerseits sind sehr viele dieser Namen aus verkürzten englischen Begriffen zusammengesetzt, andererseits stellen sich die Namen, die während der Entwicklung eines Programms festgelegt wurden, am Ende oft als nicht 44 KAPITEL 3. BASISENTWURF unbedingt glücklichste Wahl heraus. Die in den folgenden Kapiteln gewählten Namen sind deshalb der Forderung nach Präzision und Klarheit folgend nachträglich ausgesuchte in der Regel deutschsprachige Begriffe oder Begriffskombinationen. s 3.1 Objektorientierte Programmentwicklung Objektorientierte Ansätze in der Analyse und Programmentwicklung [4] haben gerade in den letzten Jahren eine schwunghafte Verbreitung erfahren. Programmiersprachen, die auf objektorientierten Konzepten aufsetzen, sind schon recht lange bekannt; was im wesentlichen neu hinzukommt, ist die Erkenntnis, wie durch die Anwendung dieses Paradigmas komplexe Aufgaben strukturiert und die zugehörigen Programme in einen übersichtlicheren Zustand gebracht werden können. Objektorientierte Entwürfe eignen sich für die Auslegung grafischer Benutzeroberflächen ebenso, wie zur Modellierung von Geschäftsprozessen und Produktionsabläufen. Allem gemeinsam ist, daß eine objektorientierte Sicht nur schwach von den realen Strukturen abstrahieren muß. Sie eignet sich deshalb besonders gut zur Beschreibung von Gegenständen der realen Welt (statisches Modell) und deren Zusammenwirken (dynamisches Modell) [4]. Die Anwendung objektorientierter Analysestrategien auf numerische Verfahren drängt sich nicht sofort auf, es könnte sogar vermutet werden, daß eine funktionale Beschreibung den abstrakten mathematischen Inhalten besser gerecht wird. Beachtet man jedoch, daß in modernen numerischen Verfahren, wie beispielsweise den Finite Elemente oder Finite Volumen Verfahren, die Verwaltung des Gitters, also der Aufteilung des Berechnungsgebiets in passende Kontrollvolumen, immer wichtiger für die Leistungsfähigkeit aber auch immer komplexer wird, deutet sich der Zugang über eine objektorientierte Modellierung an: Das Gitter wird als eine Sammlung vieler gleichartiger oder ähnlicher Objekte (Elemente, Flächen, Kanten und Knoten) angesehen, die miteinander in bestimmten Beziehungen stehen und im Zusammenwirken Anforderungen von ” außen“ erfüllen. Die nachfolgend dargestellte Modellierung des geometrischen Gitters und der mathematischen Strukturen des numerischen Verfahrens für das verteilte Simulationsprogramm ist nicht grundsätzlich als Folge einer vollständigen und strikten objektorientierten Analyse entstanden, sondern oftmals auch als vernünftige Lösung, zu der es durchaus noch Alternativen geben kann. Insofern werden in diesem Abschnitt nur die tatsächlich verwendeten grafischen Notationen der Dokumentation des Entwurfs vorgestellt, auf die Erörterung von Vorgehensschemata, Use Cases usw. wird verzichtet. Die grafischen Darstellungen lehnen sich an jene der Unified Modeling Language (UML) [7, 11] an, verwenden aber nicht deren gesamten Umfang an Bildelementen. 3.1. OBJEKTORIENTIERTE PROGRAMMENTWICKLUNG 45 3.1.1 Darstellung der Klassenbeziehungen Die statischen Informationen des Entwurfs sind die Beziehungen zwischen den verschiedenen Klassen bzw. deren Instanzen (Exemplaren, Objekten), die bereits vor der Ausführung des Programms bekannt sind. Diese Strukturen werden in Form von Klassendiagrammen beschrieben. Der folgende Abschnitt stellt die verwendeten Symbole und Notationen vor. Klassendiagramme Jede Klasse wird im Klassendiagramm (vgl. Abb. 3.1-3.3) mindestens durch ein Rechteck mit dem fettgedruckten Klassennamen dargestellt. Soweit nötig sind die Attribute (Instanzenvariablen) der Klasse in einem weiteren Feld darunter mit ihrem jeweiligen Typ eingetragen. In diesem Feld sind gegebenenfalls auch die Klassenvariablen (Attribute der Metaklassse), die statischen Attribute in C++ dargestellt: Sie sind zur Unterscheidung unterstrichen. Deutlich wichtiger für das Verständnis der Klassendiagramme sind die innerhalb einer Klasse definierten Methoden (Operationen), die in einem Rechteck an unterster Stelle eingetragen sind. Jede Operation wird durch ihren Namen mit sich anschließendem Klammerpaar, das die Argumente enthält, bezeichnet. Der Typ des Rückgabewerts folgt nach einem Doppelpunkt: Operation (Argument : Typ des Arguments, ...) : Typ des Rückgabewerts. Auf die Angabe von Zugriffsmöglichkeiten wird sowohl bei den Attributen als auch bei den Operationen verzichtet. Der Klassenname ist kursiv geschrieben, falls eine abstrakte Klasse vorliegt, von der keine Instanzen erzeugt werden können. In diesem Fall ist mindestens eine Operation abstrakt, die ebenfalls kursiv geschrieben wird. Falls alle definierten Operationen abstrakt sind und die Klasse keine Attribute ausweist, handelt es sich um eine Schnittstellenklasse, genauer um die Definition einer polymorphen Schnittstelle. Andererseits können auch nicht-abstrakte Klassen eine Schnittstelle beschreiben, z.B. für den Typparameter einer parametrisierbaren Klasse, weshalb sol- KlassenName Instanzenvariable : Typ Klassenvariable : Typ Instanzenoperation (Argument : Typ) : Typ Klassenoperation (Argument : Typ) : Typ Abbildung 3.1: Darstellung einer Klasse im Klassendiagramm. Oben ist fettgedruckt der Klassenname eingetragen, darunter folgen die Attribute bzw. unterstrichen die Klassenvariablen. An unterster Stelle sind die Methoden bzw. unterstrichen die Methoden der Metaklasse angegeben [11]. 46 KAPITEL 3. BASISENTWURF che Klassen oberhalb des Namens durch die Angabe des Stereotyps interface kenntlich gemacht sind. Die Hilfsmittelklasse wird gekennzeichnet durch das Stereotyp utility und dient der Zusammenfassung gemeinsam benutzter Konstanten als Klassenvariablen. Eine weitere Notationsergänzung benötigt die parametrisierbare Klasse (Schablone, Templateklasse): Oben rechts sind in einem Rechteck mit unterbrochener Umrißlinie der oder die Typparameter eingetragen. Die Ausprägung einer Schablone mit einem bestimmten Typ (Spezialisierung) wird durch einen unterbrochenen Pfeil mit leerer Spitze, der auf die parametrisierbare Klasse zeigt, kenntlich gemacht (vgl. Abb. 3.2). Vererbungsrelationen: Vererbungsrelationen [4] zwischen Klassen werden durch eine Linie, mit einem leeren Dreieck an der Spitze dargestellt (vgl. Abb. 3.3). Das Dreieck zeigt auf die Basisklasse (Oberklasse) die üblicherweise auch in der Zeichnung oberhalb der von ihr abgeleiteten Klasse (Unterklasse) angeordnet ist. Zusätzliche Notizen und Erklärungen, die sich auf die Implementierung einzelner Methoden beziehen, werden in einem Feld mit Eselsohr“ untergebracht. ” Liegt mehrfache Vererbung vor, führen mehrere Linien zu Basisklassen. Mehrfache Vererbung kann problematisch sein, falls die unmittelbaren Basisklassen wiederum eine gemeinsame Basisklasse beerben: Deren Attribute und Operationen sind dann nicht mehr eindeutig. Die Programmiersprache C++ [29] läßt dies zwar zu, der Abwärtsbezug auf die Basisklasse muß dann aber bei jedem Zugriff eindeutig qualifiziert werden. Die Implementierung macht von dieser Möglichkeit keinen Gebrauch. Falls hingegen eine Schnittstelle indirekt mehrfach beerbt wird, kann mit C++ diese Schnittstelle als virtuelle Basisklasse angelegt werden. Der Abwärtsbezug auf die Schnittstelle ist dann wieder eindeutig. << utility >> Hilfsmittelklasse Attribute << interface >> SchnittstellenKlasse Typparameter TemplateKlasse less(x : KlasseB) : bool Methoden TemplateKlasse < Int > Abbildung 3.2: Klassendiagramm: Spezielle Klassen erhalten eine Kennzeichnung oberhalb des Klassennamens. Hilfsmittelklasse (links) und Schnittstellenklasse (Mitte). Rechts die Darstellung einer parametrisierbaren Klasse (Templateklasse, Schablone) [11]. 3.1. OBJEKTORIENTIERTE PROGRAMMENTWICKLUNG 47 Beziehungen zwischen den Objekten: Weiterhin sind in das Klassendiagramm die Beziehungen zwischen den Instanzen der dargestellten Klassen (den Objekten) eingetragen. Durch die Mittel der Programmiersprache C++ [11] (Zeiger und Referenzen) entstehen gerichtete Beziehungen mit nur einer Möglichkeit zur Navigation zwischen den Instanzen. Deshalb sind Hin- und Rückrichtung immer getrennt dargestellt. 1 1..N Assoziation: Die Pfeilrichtung gibt die Navigationsrichtung, also die Richtung des möglichen Zugriffs an. An der Spitze und am Ende des Pfeils können Kardinalit äten angegeben werden. 1..N Aggregation: Stärkere Verbindung, denn das Aggregat übernimmt besondere Aufgaben gegenüber den aggregierten Objekten. Auf der Seite des Aggregats befindet sich die Raute. Die Navigationsrichtung zeigt natürlicherweise in die Richtung der Komponenten. 1..N Komposition: Eine Sonderform der Aggregation, die zum Ausdruck bringen soll, daß die aggregierten Objekte feste Bestandteile des Aggregats sind. Die ausgefüllte Raute wird auf der Seite der Komposition eingezeichnet, dort ist die Kardinalit ät implizit eins. 3.1.2 Darstellung der Interaktionsmuster Als dynamische Struktur bezeichnet man die Interaktionen zwischen den Objekten zur Laufzeit und meint damit die Information, welche Methodenaufrufe zwischen welchen Objekten wann ausgetauscht werden. Aus den Klassendiagrammen läßt sich diese Information nicht entnehmen, dort ist nur erkennbar, daß die betreffende Klasse eine Methode für einen bestimmten Vorgang anbietet. Es fehlt hingegen jede zeitliche Gliederung. Betrachtet man im Klassendia- AbstrakteKlasse AbstrakteOperation () ImplementierungA Operation () Instanzenvariable ImplementierungB Notiz, z.B. Pseudocode: for ( ; ; ) { ø a−>op () } Abbildung 3.3: Klassendiagramm: Einfache Vererbung und abstrakte Basisklasse, die Notiz enthält Pseudocode, der die konkrete Operation erklärt [11]. 48 KAPITEL 3. BASISENTWURF gramm Assoziationen auf polymorphe Basisklassen, bleibt sogar verborgen, welche Implementierung aus welcher Klasse die Aufgabe letztlich übernimmt. Einige Operationen auf dem gesamten Gitter setzen sich aus komplizierten Ketten von Methodenaufrufen auf verschiedenen Objekten zusammen, so z.B. der Verfeinerungs- und Vergröberungsvorgang oder die Methodenauflösung im numerischen Verfahren (vgl. Kap. 3.4, 3.5): Dort ist die Struktur des Zusammenwirkens der einzelnen Methodenaufrufe in Form eines Sequenzdiagramms erklärt. Sequenzdiagramme Im Sequenzdiagramm (vgl. Abb. 3.4) nimmt die Ausführungszeit der Anwendung von oben nach unten zu, das Diagramm ist in dieser Richtung zu lesen. Die Kopfzeile enthält ein Rechteck mit dem Klassennamen für jedes Objekt, das zu Beginn der betrachteten Interaktion bereits besteht. Die gestrichelte Lebenslinie des Objekts führt von dort aus bis zum Ende des Diagramms oder bis zu der Stelle, an der das Objekt infolge der Interaktion gelöscht wird. Die Lebenslinie neu erzeugter Objekte beginnt an der Stelle ihrer Instantiierung. Das Diagramm gibt die wechselseitige Beeinflussung von Instanzen wieder, weshalb Methodenaufrufe, die auf die eigene Lebenslinie führen, echt rekursiv sind: Sie betreffen das anfordernde Objekt selbst. ObjektA ObjektA new () ObjektB Operation () ObjektB Laufzeit Operation () ... Operation1 () Antwort Operation2 () delete () ... ... Objektlebenslinie Abbildung 3.4: Einfache Sequenzdiagramme: Konstruktion, Methodenaufruf und Löschung von ObjektB ausgelöst durch ObjektA (links). Direkt-rekursive und indirekt-rekursive Methodenaufrufe zwischen den Objekten (rechts) [11]. 3.2. DATENSTRUKTUREN UND BASISALGORITHMEN 49 3.2 Datenstrukturen und Basisalgorithmen Die Datenstruktur, die in einem numerischen Verfahren zur Lösung partieller Differentialgleichungen zur Modellierung des unstrukturierten geometrischen Gitters entworfen wird, nimmt insbesondere für die Erweiterung des numerischen Verfahrens auf verteilt-parallele Ausführung eine Schlüsselrolle ein. Deshalb soll in den folgenden Abschnitten überlegt werden, wie eine derartige Datenstruktur auszusehen hat, die sich an den geometrischen Relationen und dem verwendeten numerischen Verfahren orientiert. Hinweis: Da Finite Volumen Verfahren (vgl. Kap. 1.2.1) nahezu keine Einschränkungen an die Geometrie der zu verwendenden Kontrollvolumen bedingen, sind einige Definitionen für allgemeine Polyederelemente formuliert. Jede Numerierung von Objekten, Assoziationen usw. beginnt bei î und läuft bis ?ï¯ wenn die Gesamtzahl der vergebenen Nummern ist. s 3.2.1 Übersicht Der Strukturplan (vgl. Abb. 3.5) vermittelt einen ersten Überblick, wie das parallele Simulationsprogramm durch Vererbung, Ersatz und Delegation [12] aus ei- Behälter Test Iteration Test Iteration Zustand: Sicherung / Wiederherst. Konstruktion Konstruktion Gitterweitenanpassung Vererbung Grobgitter (leer) BuilderIF Factory ersetzt da Zu s gri G ff ro au bg f itt er Gitter (leer) Zeitschritt Daten: Sicherung / Wiederherst. ersetzt Test Iteration Konstruktion Grobgitter (Eulergleichungen) Factory Gitter z.B. Eulerlöser, Parallel (leer), Eulerlöser − Parallel Grobgitter (leer) usw. Abbildung 3.5: Strukturplan der Behälterklassen für das Grobgitter und der übergeordneten Klassen mit Methoden zu Iteration, Test, lokaler Gitterweitenanpassung und Sicherung bzw. Wiederherstellung. 50 KAPITEL 3. BASISENTWURF nem sequentiellen (Mono-) Gitterentwurf mit leeren Elementen, Flächen, Kanten und Knoten, also einer Datenstruktur, die über die geometrische Information keine weiteren Daten oder Methoden beinhaltet, aufgebaut ist. Zentral und von einheitlicher Gestalt ist das Iterationskonzept, welches die Verbindung von Durchläufen über die Grobgitterobjekte und deren aus der lokalen Gitterweitenanpassung resultierenden Verfeinerungsbäumen ermöglicht (vgl. Kap. 3.2.5, 5.7). Auf diese Art können alle Methoden des Gitters bzw. des vom Gitter verwalteten Grobgitterbehälters, die lediglich auf die Iterationsschnittstellen der Elemente, Flächen, Kanten oder Knoten zugreifen, bereits an unterster Stelle realisiert werden. Dazu gehören die Methoden zur lokalen Gitterweitenanpassung, zum Integritätstest und zur Sicherung bzw. Wiederherstellung der Verfeinerungsstruktur. 3.2.2 Darstellung der geometrischen Zusammenhänge Das numerische Verfahren benötigt zwei Zugriffe, die längs der geometrischen Relationen verlaufen: Volumenintegrale auf Elementen und Oberflächenintegrale auf den Element-Element-Grenzflächen verwenden die Koordinaten der anliegenden Knoten. 2. 0. 3. 3. 3. 2. 1. 1. 2. 2. 0. 0. 0. 1. 1. 1. ù(x,y,z) Abbildung 3.6: Zusammenhang zwischen den Hexaedern, Vierecksflächen, Kanten und Knoten des Gitters. Der Zugriff auf die Koordinaten des Knotens erfolgt indirekt über die anliegende Fläche und eine Kante (rot). Die offenen Pfeile geben die globale Ausrichtung von Kanten und Flächen an. 3.2. DATENSTRUKTUREN UND BASISALGORITHMEN 51 Trotzdem werden mit Blick auf die anstehenden Erweiterungen hin zu einer parallelen Gitterverwaltung alle geometrischen Zusammenhänge über die verschiedenen Dimensionen hinweg explizit vorgesehen: Das Gitter setzt sich somit zusammen aus Knoten, Kanten, Flächen und Elementen, womit gleichzeitig eine Klassifikation der Iterationsschnittstellen nach der Dimension der Gitterobjekte vorgeschlagen wird (vgl. Abb. 3.6). Deren Spezialisierung (Verfeinerung) [4] nach dem konkreten Typ eines Elements bzw. einer Fläche geschieht im Anschluß daran durch die Geometriesockelklassen (vgl. Kap. 3.3, Abb. 3.16): Die Klasse der Elemente zerfällt dann in Hexaeder, Tetraeder usw., die der Klasse der Flächen in Polygone verschiedener Polygonlänge. Durch die Navigation von einem Hexaeder zu einer Vierecksfläche bleibt das Niveau der Spezialisierung erhalten. Navigation zur niedrigeren Dimension Die Relation zwischen zwei geometrischen Gitterobjekten ú und û der Form ûêüäýú wird als Assoziation (vgl. Kap. 3.1.1) zwischen ú und û angelegt. Navigationsrichtung in dieser Assoziation ist immer die Richtung von der höheren zur nächstniedrigeren Dimension, also von ú nach û . Allgemein zerfällt der Zugriff vom Element auf einen anliegenden Knoten in die Navigationskette (vgl. Abb. 3.6) Element ➝ Fläche ➝ Kante ➝ Knoten. Diese Richtung der Navigation ist gewissermaßen natürlich: Der Zugriff auf ein niederdimensionales Objekt, das Teil der Berandung ist, verfügt über die volle geometrische Information zu diesem Objekt. Beispielsweise ist ausgehend vom Hexaeder klar, daß alle Flächen der Berandung Vierecksflächen sein müssen, die Umkehrung hingegen muß nicht richtig sein, denn eine Vierecksfläche kann auch zu einer Pyramide oder einem Prisma gehören. Orientierung Weil Kanten und Flächen jetzt als eigenständige Gebilde angesehen werden, sind sie auch absolut im Raum orientiert, worin ein ganz entscheidender Unterschied besteht zu einer unvollständigen Datenhaltung, bestehend aus Elementen und Knoten: Dort sind Kanten und Flächen implizit durch den verwendeten Prototyp des Elements orientiert [32]. Daraus ergeben sich Freiheitsgrade, die anscheinend zunächst willkürlich festgelegt werden können, denn die Ausrichtung einer Kante oder einer Fläche kann beim Aufbau des Gitters beliebig gewählt werden. Die Kante zwischen zwei Knoten þÝÿ und þ º kann von þÝÿ nach þ º zeigen oder umgekehrt, die Fläche 52 KAPITEL 3. BASISENTWURF der Knotenfolge þ ÿ k þA¬ º kann auf Arten in das Gitter eingesetzt werden (alle zyklischen Permutationen der Mengen ÃîOFk¯ïñÄ und ïïñ¿FkîdÄ ). Damit nun ausgehend vom Element die absolute Orientierung einer Außenfläche gegenüber derjenigen des Elementprototypen aufgelöst werden kann, muß die Verdrehung (engl. twist) für jede assoziierte Fläche abgespeichert werden. Dazu wird ein ganzzahliger Wert §)Ã_ï<8FkîOFkï®AÄ verwendet. Der Zugriff auf den Knoten mit der Nummer im Elementprototyp wird dann als Zugriff auf den Knoten der Fläche realisiert, wobei nach folgender Formel ( bezeichnet die Polygonlänge) zu berechnen ist: y y Û Û <ï Û | | z ñî ñî (3.1) Allerdings ist der Zugriff auf den Knoten der Fläche, der hier vorausgesetzt wird, auch nicht echt“ : Dahinter verbirgt sich noch eine Navigation über eine ” der an der Fläche anliegenden Kanten. Die Situation ist hier ähnlich der bereits geschilderten, aber erheblich einfacher: Es gibt nur zwei Möglichkeiten, eine Kante zwischen zwei Knoten auszurichten, die als Orientierung §gÃîOFÄ zu jeder Assoziation Fläche ➝ Kante abgespeichert wird. Dazu kommt noch die Konvention, als Kante mit der Nummer  ausgehend von der Fläche die Kante zwischen den Knoten mit den lokalen   Nummern und y Û | zu bezeichnen. Die Skizze zeigt die atomare Situation beim Zugriff auf den Knoten mit der lokalen Nummer î der rechten Elementfläche (vgl. Abb. 3.6): Der entsprechende Knoten hat in der Numerierung der Fläche die Nummer , er kann als Knoten der Kante erreicht werden. Globale Ausrichtung Als globale Ausrichtung einer Kante oder Fläche im Gitter wird deren Lage bezüglich der anliegenden Knoten bezeichnet. Falls die Knoten über eindeutige globale Nummern verfügen, kann zunächst die folgende Definition angewendet werden, um die globale Ausrichtung zu beschreiben. Â Í Â Í Definition: Sei eine Kante zwischen den Knoten . Dann wird mit y | Í Â Â Í Â Í oder y | identifiziert. Für die Ausrichtung findet man die Fälle bzw. (aufwärts/abwärts). Die Situation ist für Flächen ähnlich: Die Lage einer Fläche kann im einfachsten Fall durch den Vektor der anliegenden Knotennummern in der Reihenfolge der lokalen Numerierung beschrieben werden. An dieser Stelle wird nun festgelegt, wie mit dem zusätzlichen Freiheitsgrad, der durch die freie Wahlmöglichkeit der globalen Ausrichtung der Flächen und Kanten entstanden ist und dort bisher offenbar nicht benötigt wird, beim Aufbau des Grobgitters umzugehen ist. Anstelle einer beliebigen (zufälligen) globalen 3.2. DATENSTRUKTUREN UND BASISALGORITHMEN 53 Ausrichtung, die z.B. von der Reihenfolge der Konstruktion abhängt, wird gefordert, daß: - Alle Knoten des Grobgitters a-priori numeriert sind oder in der Reihenfolge ihrer Konstruktion numeriert werden. - Für alle Kanten des Grobgitters der îd lokale Knoten die kleinere globale Nummer trägt. - Für alle Flächen (mit anliegenden Knoten) des Grobgitters der lokale îd Knoten an der kleinsten globalen Nummer anliegt und die globale Nummer des ¿ Knotens kleiner als die des ,ïñ¿ Knotens ist. Die Ausrichtungskonvention für die Flächen ist leichter zu verstehen, wenn beachtet wird, daß jede Fläche bildlich gesprochen zuerst mit ihrem îO lokalen Polygonpunkt am Knoten mit der kleinsten globalen Nummer fixiert wird. Dann wird je nach Situation der Umlaufsinn der Fläche festgelegt, also ob sie vom Betrachter aus links- oder rechtsdrehend numeriert ist. 3.2.3 Das geometrische Nachbarschaftskonzept Die Strukturen, die im vorigen Abschnitt zur Modellierung der geometrischen Zusammenhänge vorgeschlagen werden, sind ihrer Konstruktion nach nicht in der Lage, die Navigation von einer Element-Element-Grenzfläche zurück auf die anliegenden Elemente zu vermitteln (Nachbarschaft). Das Finite Volumen Verfahren (1.13) benötigt definitionsgemäß zur Berechnung der numerischen Flüsse auf allen Flächen · Ê des Gitters die auf den Elementrand fortgesetzten Werte der Erhaltungsgrößen · aus dem Element (Kontrollvolumen) · . Der Entwurf wird deshalb um das geometrische Nachbarschaftskonzept ergänzt, das den folgenden Voraussetzungen genügen wird: r r Innerhalb des Grobgitters wird eine konforme Nachbarschaft vorausgesetzt: Jede Außenfläche eines Grobgitterelements fällt mit genau einer Außenfläche eines Nachbarelements zusammen. Nach einer lokalen Verfeinerung darf eine nichtkonforme Nachbarschaft der folgenden Art entstehen: Die Außenfläche eines Elements fällt mit genau einer Fläche zusammen, die durch ein- oder mehrmalige Verfeinerung aus derjenigen Außenfläche des groben Elements entstanden ist, zu dem eine konforme Nachbarschaft bestand (vgl. Abb. 3.11) Darstellung der konformen Nachbarschaft Die Darstellung des Nachbarschaftskonzepts in Form der entsprechenden Klassen soll am Beispiel der konformen Nachbarschaft zwischen Hexaeder- 54 KAPITEL 3. BASISENTWURF element und Pyramide über die gemeinsame Vierecksfläche motiviert werden (vgl. Abb. 3.7): Die Navigation von einem Element über die anliegende Fläche zum Nachbarelement muß unabhängig von dessen konkretem geometrischen Typ ablaufen. Von den bisher eingeführten Klassen könnte als Ziel für eine Assoziation bestenfalls die Iterationsschnittstelle des Elements eingesetzt werden, d.h. beim Zugriff auf den Nachbarn geht über die Kenntnis, daß es sich um ein Element handelt, sämtliche Information verloren. Dadurch wird die Navigationsmöglichkeit aber praktisch wertlos. Beachtet man hier, daß die beste Aussage, die über den Nachbarn gemacht werden kann, besagt, er verfüge über mindestens eine Vierecksfläche (im Beispiel), dann wird klar, wie durch eine passende Schnittstelle die beschrieben Probleme beseitigt werden (vgl. Abb. 3.7): Die Geometriesockelklassen des Elements und des Randelements beerben eine Schnittstelle (im Beispiel den 4-PolygonVerbinder), die spezifiziert, welche Operationen ausgehend von der anliegenden Fläche angefordert werden können, und zwar gegliedert nach dem konkreten geometrischen Typ der Fläche. Durch die Aufnahme dieser Schnittstelle wird (im Beispiel) vom geometrischen Typ Hexaeder, Pyramide der Fläche 4-Polygon gegenüber die Eigenschaft zugesichert, über mindestens eine Vierecksfläche zu verfügen. Der Hintergrund für diese Strukturierung der Schnittstellen ist direkt im eingesetzten numerischen Verfahren zu erkennen: Hier wird die Restriktion der (polynomialen) Approximation der Daten innerhalb des Elements auf eine entsprechende lokale Darstellung auf der Randfläche verlangt (vgl. Kap. 3.4.1). 2 4−PolygonVerbinder Hexaeder 0,1,2 0,1,2 6 Pyramide 1 4−Polygon 1 Abbildung 3.7: Konforme Nachbarschaftsbeziehung zwischen Element, Vierecksfläche und Pyramide (unten) und deren Darstellung im Entwurf. Die Navigation vom Element zum Nachbarelement verläuft über die anliegende Fläche zur Schnittstelle der 4-Polygonnachbarschaft (rot). 3.2. DATENSTRUKTUREN UND BASISALGORITHMEN 55 Aber auch unter grundlegenden Aspekten ist die vorgeschlagene Art der Nachbarschaftsbeziehung eine absolut angemessene Lösung, denn sie vermittelt durch die Typinformation, die mit der Assoziation auf die beschriebene Schnittstelle verbunden ist, die maximal verfügbare geometrische Information zu der realen Situation im Gitter. Hinweis: Der Navigationspfad der geometrischen Nachbarschaftsbeziehung vermittelt zwar den Zugriff von der Fläche auf das anliegende Element unter angenehmen abstrakten Spezifikationen, allerdings bleibt offen, wie das Element feststellen kann, von welcher Außenfläche ein Methodenaufruf erfolgt. Eine einfache Möglichkeit besteht darin, mit dem Methodenaufruf an die Schnittstelle auch gleichzeitig die lokale Flächennummer im Element als Parameter zu übergeben (vgl. Abb. 3.8), die dazu in der Datenstruktur der an dieser Seite anliegenden Fläche abgespeichert sein muß. Daraus folgen zwei Nachteile: Einerseits werden die Signaturen aller Schnittstellenmethoden zur Nachbarschaft um ein Argument aufgebläht, andererseits sichert eine konsistente Datenstruktur noch keine korrekten Aufrufe, falls die Konstruktion nicht richtig verstanden wird. Ein aufwendiger Weg, der das Problem vollständig umgeht, ist im nächsten Klassendiagramm (vgl. Abb. 3.9) dargestellt: Das Hexaederelement enthält Instanzen von sechs Klassen, die für jede Position die Schnittstelle implementieren. Die Instanzen dieser sechs Klassen bilden zusammen mit dem Hexaeder eine Komposition (vgl. Kap. 3.1.1), wobei der Zugriff auf das Hexaederelement für jede Methode der Komponenten gewährleistet sein muß. Dazu ist jede Schnittstellenmethode für jede Position einzeln zu implementieren. Der entscheidende Vorteil liegt aber darin, daß die Positionsangabe schon im Navigationspfad (also in der Referenz) enthalten ist. 2 4−PolygonVerbinder Operation (Fläche : Int) Hexaeder 1,2 Operation (Fläche : Int) 6 4−Polygon 1 switch ( Position ) { case OBEN : ... case UNTEN: . . ø break ; } FlächeLinks : int FlächeRechts : int Abbildung 3.8: Einfachste Lösung zur Vermittlung der Position der von einem Methodenaufruf betroffenen Fläche des Hexaederelements: Die lokale Flächennummer wird bei jedem Methodenaufruf als zusätzlicher Parameter angegeben. 56 KAPITEL 3. BASISENTWURF Eine andere Lösung verwendet für jede Position eine Instanz, wobei alle von der selben Klasse sind (vgl. Abb. 3.10). Die Positionskodierung findet durch ein Attribut statt, hier durch die lokale Flächennummer. Die Schnittstellenmethoden müssen in diesem Fall nur einmal realisiert werden, die Auswahl des passenden Algorithmus folgt dann dem Wert des vorgefundenen Attributs. s Erweiterung auf die nichtkonforme Nachbarschaft Das numerische Verfahren verwendet in der niedrigsten Ordnung elementweise konstanten Approximationen für die Erhaltungsgrößen und erfordert somit keine komplizierte, vom geometrischen Typ der Fläche abhängige Darstellung der Daten auf dem Elementrand (vgl. Kap. 3.4.1). 2 4−PolygonVerbinder Operation () 1 Rechts Links Unten Oben Vorne Hinten Operation () 1 hexaeder−>Operation (LINKS) ; 1 Hexaeder 1 Operation (Position : Int) 6 1,2 4−Polygon 1 Abbildung 3.9: Kodierung der lokalen Flächenposition im Element durch eigene Klassen, die von der Schnittstelle zur 4-Polygonnachbarschaft abgeleitet sind (aufwendige und sichere Lösung). 2 4−PolygonVerbinder 6 Flächenverbinder Position : enum 6 1 Hexaeder 1 6 4 4−Polygon 1 Abbildung 3.10: Vereinfachte Lösung: Es wird nur eine einzige Spezialisierung der Schnittstelle zur 4-Polygonnachbarschaft benötigt. Die Information zu welcher Position die jeweilige Instanz gehört, wird in einem Attribut abgelegt. 3.2. DATENSTRUKTUREN UND BASISALGORITHMEN 57 Für diesen Spezialfall kann das konforme Nachbarschaftskonzept sehr einfach auf die zulässigen nichtkonformen Situationen erweitert werden: Die Assoziation führt direkt von der feinen Fläche zum 4-Polygonverbinder des groben Nachbarelements (vgl. Abb. 3.11) und enthält keine differenzierte Darstellung der Einbettung der feinen Fläche in die grobe des Nachbarn. Der Nachteil dieses Vorgehens besteht darin, daß die vorgestellte Art offensichtlich nur in einem Gitter mit Flächen von einheitlichem geometrischen Typ eingesetzt werden kann. Der Grund ist der direkte Zugriffspfad von der feinen Vierecksfläche zurück auf das grobe anliegende Element: Falls ein Hexaeder in Elemente mit Dreiecksflächen zerfällt (z.B. in Prismen), findet diese Assoziation keine geeignete Schnittstelle mehr vor - der Hexaeder beerbt (vernünftigerweise) keine Schnittstelle für eine 3-Polygonnachbarschaft. Weiterhin fehlt in diesem Fall auch im homogenen Hexaedernetz die für numerische Verfahren höherer Ordnung notwendige Information, wie die Daten aus dem groben Element auf die anliegende feine Fläche fortzusetzen sind. Als Lösung empfiehlt sich hier, die Assoziation von der Fläche auf ein Proxyobjekt [12] (als Fläche mit angehängter Kugel dargestellt) zu führen, das die passende Schnittstelle für die Nachbarschaft implementiert und mit der nötigen Information ausgestattet ist, wie die Fläche des feinen Elements in die Vierecksfläche des groben eingebettet ist. Damit kann gleichzeitig eine Interpolation der Daten im numerischen Verfahren verbunden werden. 3.2.4 Behandlung der Gebietsränder Definition: Eine Fläche des Gitters liegt auf dem Gebietsrand, falls sie von genau einem Element über den Navigationspfad des geometrischen Zusammenhangs (vgl. Kap. 3.2.2) erreicht wird. Eine Kante oder ein Knoten liegt auf dem Gebietsrand, wenn mindestens ein Navigationspfad ausgehend von einer Fläche auf dem Gebietsrand dort endet. 2 3 1 0 Abbildung 3.11: Nichtkonforme Nachbarschaft nach der lokalen Verfeinerung des linken Elements mit direkter Navigation zum Nachbarelement (links) oder dem Zugriff unter Vermittlung eines Proxyobjekts (rechts). 58 KAPITEL 3. BASISENTWURF Am Gebietsrand sollte die Situation aus bisheriger Sicht unproblematisch sein, trotzdem lohnt sich ein genauer Vergleich der zur Verfügung stehenden Alternativen: r r Die Eigenschaft auf dem Rand zu liegen“ könnte direkt in die Klasse für ” die betreffenden Knoten, Kanten und Flächen eingebaut werden (polymorphes Verhalten). Für das Element ergibt sich keine Veränderung, es befindet sich definitionsgemäß immer im Innern des Gebiets. Bei diesem Vorgehen ist eine Kenntnis der Gebietsränder schon beim Aufbau des Grobgitters nötig, damit die richtigen“ Flächen eingebaut werden. ” Am Rand wird auf jede Fläche des Gitters ein Randelement aufgeklebt (vgl. Abb. 3.12). Die auf dem Rand liegenden Knoten, Kanten und Flächen sind mit denen im Innern des Gitters vom Typ identisch. Jetzt muß aber ein abweichendes Verhalten der randständigen Flächen im numerischen Verfahren oder während der lokalen Gitterweitenanpassung durch eine Vermittlung des anliegenden Randelements und eine angepaßte Methodenauflösung erreicht werden (vgl. Kap. 3.4.4). Die erste Möglichkeit erscheint zunächst einfacher, aber aus Gründen, die mit der Erweiterung des Basisentwurfs auf ein verteiltes Gitter zusammenhängen, wird die zweite realisiert: Die dynamische Umverteilung des Gitters im verteilten parallelen Programm wird an beliebigen nichtvorhersagbaren Stellen im Gitter künstliche Randflächen erzeugen oder auch schließen, was mit dem ersten Ansatz offenbar nicht beherrscht werden kann. 2 4−PolygonVerbinder Hexaeder 1,2 0,1 6 4−PolygonRand 1 4−Polygon 1 Abbildung 3.12: Konforme Nachbarschaftsbeziehung zwischen Element, Vierecksfläche und Vierecksrandelement. 3.2. DATENSTRUKTUREN UND BASISALGORITHMEN 59 3.2.5 Verfeinerungsregeln und hierarchische Anordnung Die Hierarchie entsteht in einem Gitter durch die lokale Gitterweitenanpassung und ist neben den geometrischen Zusammenhängen die zweite wichtige Struktur. Obwohl das numerische Verfahren keine hierarchische Datenhaltung erfordert, wird auch für die Abbildung der Hierarchie eine sorgfältige Modellierung vorgenommen: Der Abschnitt zur verteilten Datenhaltung zeigt im nachfolgenden Kapitel, welcher Gewinn aus einer günstig angelegten hierarchischen Strukturierung gezogen werden kann (vgl. Kap. 4.1.1, 4.4.5, 4.5.2). Mit Verweis auf die Bedürfnisse der parallelen Gitterverwaltung wird die folgende Struktur der hierarchischen Navigationswege für das Gitter hier ohne weitere Begründungen festgelegt (vgl. Abb. 3.13). Jedes in der Folge einer Verfeinerung neu entstandene Objekt soll dabei am Ort seiner Entstehung verwaltet werden, der Navigationspfad soll entlang der Generationen verlaufen: r r Aus den Knoten des Gitters entstehen keine neuen Gitterobjekte. r Die Teilung einer Kante liefert neue Kanten und Knoten, diese sind ausgehend von der Bezugskante angeordnet. Die entstehenden Knoten müssen auf der Bezugskante liegen. r Verfeinerung einer Fläche führt zu neuen Flächen, Kanten und Knoten, die relativ zur Bezugsfläche aufgefunden werden können. Der neu entstehende Knoten liegt in der Bezugsfläche. Durch die Teilung eines Elements werden neue Elemente, Flächen, Kanten und Knoten erzeugt, die vom Bezugselement aus erreichbar sind. Der entstehende Knoten liegt innerhalb des Bezugselements. Abbildung 3.13: Hierarchische Anordnung der Objekte des Gitters am Ort ihrer Entstehung: Das Hexaederelement (außen) wird zum Knoten in der Elementhierarchie und verwaltet die enthaltenen zwölf Flächen, sechs Kanten und den zentralen Knoten. Analoge Situation an der Vierecksfläche und an der Kante. 60 KAPITEL 3. BASISENTWURF Die Navigationsmöglichkeiten innerhalb der hierarchischen Struktur sind in der Skizze ausgehend von einem Hexaederelement mit einer isotropen Verfeinerungsstufe dargestellt (vgl. Abb. 3.14). Die Navigationsrichtung verläuft in der Zeichnung im Baum von unten nach oben. Gestrichelte Linien sind eingetragen, falls sich das Muster bei mehrfacher Verfeinerung wiederholt. Durch diese Art der Datenhaltung wird die Iteration der Knoten, Kanten und Flächen, die Blätter in der entsprechenden Hierarchie sind, deutlich komplizierter, denn es gibt keine Behälter [1, 27], die exklusiv diese Objekte verwalten. Dem wird in der Implementierung durch ein geeignetes Paket mit Bausteinen für Iterationsklassen begegnet (vgl. Kap. 5.7). 3.2.6 Grobgitteraufbau Die kooperative Struktur des verteilt parallelen Programms weist dem Modul zum Aufbau des Grobgitters eine besondere Bedeutung zu (vgl. Kap. 4.1.2): Dieses Modul wird an mehreren Stellen des Basisentwurfs als auch von der verteilten Gitterverwaltung verwendet und führt sowohl den Aufbau des Grobgitters nach einem in einer Datei gespeicherten Zustand durch, als auch die Ergänzung und den komponentenweisen Umbau des Grobgitters im Verlauf der dynamischen Lastverteilung. Elemente Flächen Kanten Knoten Abbildung 3.14: Hierarchische Datenhaltung für die verschiedenen Teilbäume, die durch Verfeinerung eines Hexaederelements entstanden sind. Die Navigationsrichtung verläuft von unten nach oben. 3.2. DATENSTRUKTUREN UND BASISALGORITHMEN 61 Entwurfsmuster Wann immer das Grobgitter verändert werden muß, spielen im wesentlichen drei fundamentale Bausteine zusammen, wobei das Entwurfsmuster das Standardmuster einer abstrakten Objektfabrik mit dem des Erbauers, virtuellen Konstruktors [12] verbindet (vgl. Abb. 3.15). r Das konkrete Gitter instantiiert einen Grobgitterbehälter [2] und vorübergehend einen geeigneten Erbauer für das zu erstellende Gitter (Director [12]). r Der Erbauer des Grobgitters setzt das Grobgitter aus Knoten, Kanten, Flächen, Elementen und Randelementen sukzessive zusammen. Die konkreten Typen der in das Grobgitter eingebauten Objekte sind dem Erbauer nicht bekannt, er delegiert die Instantiierung an den Grobgitterbehälter (Objektfabrik). r Das konkrete Grobgitter tritt gegenüber dem Erbauer als Schnittstelle zur Konstruktion der geometrischen Gitterobjekte auf und ist darüber hinaus ein konkreter Behälter, der die Bestandteile des Grobgitters verwaltet. Gitter (Interface) Konkretes Gitter (Director) Instantiierung 1 mg : Konkretes Grobgitter & Analoge Situation für Ränder, Flächen, Kanten und Knoten Instantiierung Erbauer (Builder) Map < Hexaeder * > a Map < 4−Polygon * > b Map < Kante * > c Map < Knoten * > d 1 1 1...N Grobgitter (Project) 0...N HexaederGeometriesockel (Part) f : (FlächeGeometriesockel *)[6] hexaederErzeugen () 4−PolygonErzeugen () kanteErzeugen () knotenErzeugen () Behälter < Hexaeder * > a Behälter < 4−Polygon * > b Behälter < Kante * > c Behälter < Knoten * > d Konkretes Hexaederelement Instantiierung 1 Konkretes Grobgitter (Factory) hexaederErzeugen () 4−PolygonErzeugen () kanteErzeugen () knotenErzeugen () Abbildung 3.15: Das Zusammenwirken der verschiedenen Instanzen beim Aufbau des Grobgitters entspricht dem Standardentwurfsmuster Builder Pattern [12]. 62 KAPITEL 3. BASISENTWURF Hinweis: Die Behälter unterscheiden nach dem geometrischen Typ der enthaltenen Objekte, d.h. die Typinformation bleibt auf dem Niveau der Geometriesockelklassen erhalten. Die gegenüber dem Gitter angebotene Funktionalität der Iteration über die Iterationsschnittstellen (ohne geometrische Information) wird durch eine zusammengesetzte Iteration über die verschiedenen geomes trischen Ausprägungen erreicht. 3.3 Gliederung der Klassen und Schnittstellen Aus der Zusammenführung aller Konzepte, denen das Gitter in Bezug auf Geometrie, Nachbarschaft und Hierarchie genügt, folgt eine Gliederung der entworfenen Klassen und Schnittstellen (vgl. Abb. 3.16): 3.3.1 Iterationsschnittstellen Die Übersicht enthält links die Schnittstellen für die Iteration, geordnet nach der Dimension der dahinter verborgenen geometrischen Gitterobjekte. Die Iterationsschnittstellen dürfen daher nicht nach konkretem geometrischen Typ unterscheiden, und die enthaltenen abstrakten Methodendeklarationen spezifizieren Operationen, die für alle Elemente sinngemäß gleichartig sind. Die Randelemente besitzen eine eigene Iterationsschnittstelle und können deshalb nicht zusammen mit Flächen oder Elementen iteriert werden. Dies ist durchaus sinnvoll, denn die Randelemente sind als eigenständige Gitterbestandteile anzusehen, die sich unter Verfeinerungsoperationen wie Flächen, unter Nachbarschaftszugriffen aber eher wie Elemente verhalten. Der Satz der Iterationsschnittstellen ist vollständig. 3.3.2 Geometriesockelklassen Die Geometriesockelklassen der Elemente (hier Hexaeder) und der Randelemente (hier 4-PolygonRand) spezialisieren die allgemeinen Iterationsschnittstellen sowie die Schnittstelle für die Nachbarschaftsrelation und sind die Basisklasse für weitere Ableitungen mit Implementierungen eines numerischen Verfahrens, weil dieses in der Regel stark vom Typ der unterliegenden Elemente abhängig ist. Beispielsweise sind zur Volumenberechnung für Hexaeder und Tetraeder unterschiedliche Formeln zu implementieren. Die Geometriesockelklassen sind die Stelle des statischen Entwurfs, an der sich die Zugehörigkeit eines Elements zu einem bestimmten geometrischen Typ manifestiert. Deshalb sind hier auch alle Methoden untergebracht, die eine Navigation entlang der geometrischen Zusammenhänge und der Nachbarschaftsbeziehungen vermitteln (vgl. Kap. 5.1.1, Abb. 5.1-5.4). 3.3. GLIEDERUNG DER KLASSEN UND SCHNITTSTELLEN 63 Ferner kann für die Elemente hier die Verfeinerungsanforderung stattfinden. Die Schnittstelle zur Nachbarschaft (hier 4-PolygonVerbinder) beerbt keine Iterationsschnittstelle und wird daher nur im Zuge der Navigation in der Nachbarschaft erreicht. Die Geometriesockelklassen bilden einen vollständigen Satz, solange keine weiteren Elementtypen in das Konzept eingefügt werden müssen. 3.3.3 Implementierungsschicht Ganz rechts in der Tabelle sind die für das numerische Verfahren vorgesehenen konkreten Implementierungsklassen eingetragen (vgl. Abb. 3.16). Auf den Knoten und Kanten benötigt das numerische Verfahren keine Operationen die über den Umfang der Funktionalität aus den Geometriesockelklassen hinausgehen, daher werden deren leere“ Standardimplementierungen, die mit ” dem Funktionsinhalt der Geometriesockelklassen übereinstimmen, verwendet. Die Implementierungen der Randelemente bestimmen das Verhalten der Außenflächen des Gitters im numerischen Verfahren. Neue Implementierungsklassen müssen erstellt werden, sobald ein abgeändertes numerisches Verfahren in das Gitter eingebaut werden soll. Iteration Knoten Fläche Element Rand Nachbarschaftskonzept Navigation Kante 4-PolygonFl äche Hexaeder Vierecksfl äche mit Berechnung der num. Flüsse Hexader mit Verwalt ung des Erhaltungsvekto rs 4-PolygonVerbinder 4-PolygonRand Geometriesockelklassen Verschiedene Rand− behandlungen Implementierungen Vererbung / Spezial isierung Abbildung 3.16: Die Klassen- und Schnittstellenhierarchie der Gitterobjekte für das Simulationsprogramm in der Übersicht. Die Dimension nimmt von oben nach unten, die Spezialisierung von links nach rechts zu. 64 KAPITEL 3. BASISENTWURF 3.4 Numerisches Verfahren Die mathematischen Inhalte des numerischen Verfahrens zur Simulation kompressibler Strömungen auf einem unstrukturierten Hexaedernetz sind im Kapitel zu den Grundlagen des numerischen Verfahrens (vgl. Kap. 1) detailliert beschrieben. An dieser Stelle soll geklärt werden, wie das numerische Verfahren in das vorgeschlagene Gitterkonzept zu integrieren ist und wie der Daten- und Methodeninhalt der Flächen, Elemente und des Gitters aussehen soll. 3.4.1 Interpolationsobjekte In den Ausdruck der numerischen Flußfunktion werden im Fall niedrigster Approximationsordnung die Werte aus den an der Bezugsfläche ! anliegenden Volumen "# , "$ direkt eingesetzt und zur Integration auf der Fläche wird eine 1-Punkt Integrationsformel verwendet (vgl. Kap. 1.2.2): %&('!) % & % & % & ,/2 .10 254 65798 ;: = < ? >A@ *+ "3 (3.2) Dieses Schema berücksichtigt weder, daß der numerische Fluß auch von der Normalen B abhängt [34], die nicht unbedingt konstant auf der betrachteten Fläche sein muß, noch sieht es eine Möglichkeit zur Erweiterung des Verfahrens auf eine höhere Approximationsordnung vor. Ein Finite Volumen Verfahren mit höherer Approximationsordnung wiederum verwendet zellenweise Approximationen der Lösung durch lineare Funktionen [42] oder Polynome höheren Grades [8], wobei die numerische Lösung auch hier auf den Zellgrenzen unstetig sein kann: % :DCEGF > *+ % H:IC > falls CJEK"# @ (3.3) In diesem Fall ist (3.2) durch den exakten Ausdruck % &5'!) % & , 1 *+ % & 6P78 % & 6P78 2 .10 2 4 6 78ML 6 7 8O 2 N 2 P:IBQ < 2 < 2 >SRT " B 2 (3.4) 2QU ) zu ersetzen, wobei der Faktor B auftritt, weil die Definition der numerischen Flußfunktion aus dem Verfahren niedrigster Ordnung bereits die mit dem Maß der Fläche skalierte Normale enthält (1.15) [34]. In (3.4) bezeichnet % & 2 6 7 8 * !WVYXSZ (3.5) die Fortsetzung der (polynomialen) Approximation der numerischen Lösung aus dem Zeitschritt [ auf die Randfläche !]\_^`"# des Volumens "# , die mit % der globalen Approximation * FaVYX Z auf die folgende Art zusammenhängt: b CcEKQ * % & 2 65798 % % :DC > e + j dgfikmh l :IConqpsrtB!;:IC >u>vgwt+ x wzy j{gd fi| k h l }:IC~nprBQP:IC >u>A@ 3.4. NUMERISCHES VERFAHREN 65 Damit das Integral (3.4) numerisch berechnet werden kann, sind zunächst für die Größen BQ und (3.5) Parameterdarstellungen einzusetzen. Seien dazu F ein geeignetes Parametergebiet und F * \aXS 1VYQ < b E F P: > * C: > + (3.6) eine Parameterdarstellung der Fläche ! dann ist b B Q * Fa VYX w < EF * B : > *+ B Q :IC: >u> + B Q : Q : H> > die Darstellung der Flächennormalen auf dem Parametergebiet F transformierten Größen (3.5) werden nachfolgend abgekürzt durch * F VXZ < b EJF und die % & 2 6 7 8 % & 2 6 7 8 D: C: >H> + : ;: >u> * QP: > *Q+ bezeichnet. Für das numerische Verfahren wird die Einschränkung der Darstellung der Lösungsfunktion auf die Fläche benötigt, wozu die Interpolationsobjekte in den Entwurf eingeführt werden (vgl. Abb. 3.17): Definition: Das Interpolationsobjekt auf dem Volumen " zur Fläche Q\^`"# stellt die Fortsetzung der numerischen Approximation der Lösung auf die Fläche Q (3.5) in den Koordinaten der Flächenparametrisierung (3.6) dar. Wird beispielsweise wird für eine Vierecksfläche im Hexaedernetz eine Referenzabbildung S * , N < N V ! verwendet, dann enthält das Interpolationsobjekt eine Abbildung der Form: Q * , N < N VYX Z @ (3.7) Der mathematische Sachverhalt wird auf die vorgeschlagene Art sehr präzise im Programmentwurf wiedergegeben. Ein Vorteil besteht auch darin, daß jederzeit auf Integrationsformeln beliebiger Ordnung übergegangen werden kann und daß der konkrete geometrische Typ der Elemente zur Berechnung der numerischen Flüsse nicht benötigt wird. 3.4.2 Integrationsformeln Nach der Transformation von (3.4) auf das Parametergebiet der Darstellung der betreffenden Fläche kann der resultierende Ausdruck mit dem Oberflächenintegral durch eine numerische Integrationsformel auf dem Parametergebiet F in der gewünschten Genauigkeit berechnet werden [35]: % & 6 7 8 % & 6 97 8 L 6P78 :IB < 2 < 2 > 2 N 2 RT + L? Q B 4# Q: BQ P: > < ;: 2 2 T : >2 : B : >< Q : > < H : u> > 2 R B ! (3.8) E F @ >A< H: H> > 66 KAPITEL 3. BASISENTWURF Dieser Ausdruck läßt sich für ein Verfahren mit elementweise konstanten Wer ten vereinfachen, weil in diesem Fall die Darstellungen Q bzw H konstant sind, und es folgt bei festgehaltenem Normalenvektor Q : % % : A> < H : H> > + : < > b? EF @ Da die Flußfunktion von Steger und Warming [34] von der Form % % % % Q;:B! < < > + {: < > rBQ ist, und tatsächlich von der Flächennormalen B! an ! nicht abhängt, gilt: (3.8) + % % : < > r14 9¡ ) B @ (3.9) Hier sind die Referenzabbildungen des Einheitswürfels auf die Hexaedervolumen durch trilineare Polynome beschrieben. Daraus ergibt sich die Referenz abbildung : > des Einheitsquadrats auf eine Vierecksfläche als bilineares Polynom. Bezeichne ¢ )£ £ £ ¤ EF die Eckpunkte der Fläche ! , findet man: w :¥ ) ¥ < > ¦N : N , ¥ ) > : N , ¥ > ¢ ) n N : , ¥ ) > : nG¥ > ¢ n ¦ N N w + n ¦ N : N nK¥ ) > : N , ¥ > ¢ s N : nK¥ ) > : nG¥ > ¢ ¤ @ ¦s N N Die Normale an diese Fläche B!;:D§ > ist eine lineare Funktion in Linkes und rechtes Interpolationsobjekt + (3.10) :9¥ ) < ¥ > T . Gij (Di (pk), D j (p k)) Integration der Flußfunktion Flußfunktion G (p : Real [2]) : Vec5 p0 , ..., pn−1 Flußfunktion IntegrationsformelQuadrat integralOrdnung1 () : A :: val_t integralOrdnung2 () : A :: val_t ... 2 Interpolation operator () (p : Real [2]) : Vec5 Schnittstelle der Interpolationsobjekte InterpolationOrdnung0 InterpolationOrdnung1 operator () (p : Real [2]) : Vec5 operator () (p : Real [2]) : Vec5 Verschiedene Implementierungen der Interpolationsobjekte Dl (p) Di , Dj Abbildung 3.17: Zusammenspiel von Integrationsformeln, Funktionenobjekten zur Flußberechnung und den zwei Interpolationsobjekten zur Berechnung der numerischen Flußfunktion auf einer Fläche. 3.4. NUMERISCHES VERFAHREN 67 Eine Integrationsformel erster Ordnung liefert dann das exakte Integral: (3.9) + % % : < > rtB < + :¨ < ¨ > T @ Nachdem die Bausteine des Entwurfs für das numerische Verfahren vorgestellt sind, soll noch darauf eingegangen werden, wie die Komponenten zusammenwirken, um das gewünschte Ergebnis zu erzielen. 3.4.3 Zusammenspiel der Komponenten Die Klassendiagramme (vgl. Abb. 3.17, 3.18) zeigen schematisch, wie die Komponenten Integrationsformel, Interpolationsobjekt und eine Klasse für die numerische Flußfunktion zusammenwirken. In den beiden beteiligten Elementen "# , "$ links und rechts der Bezugsfläche Q werden die Interpolationsobjekte der entsprechenden Ordnung für das Parametergebiet , N < N instantiiert und als Referenz auf die polymorphe Schnittstellen Interpolation dem Funktionsobjekt Flußfunktion bekannt gemacht. Dieses wiederum wird von der Integrationsformel verwendet, um die Werte der numerischen Flußfunktion an den verschiedenen Integrationsstützstellen zu berechnen. Das Ergebnis der Integration ist ein Datum vom Typ des Erhaltungsvektors, welches den beiden Elementen zur Verfügung gestellt werden muß, damit dort die neue Lösungsfunktion nach Abschluß des Zeitschritts bestimmt werden kann (vgl. Kap. 1.3). 0...N GitterEulerImplementierung Fläche flußBerechnen (zeit:Real) : Vec5 Nachbar 2 4−PolygonVerbinder 4-PolygonEulerImplementierung flußBerechnen (e : 4-Polygonverbinder *, f : 4-Polygon *, zeit : Real) : Vec5 flußBerechnen (d : Interpolation, f :4-Polygon *, zeit : Real) : Vec5 flußBerechnenRand (e : 4-Polygonverbinder *) flußBerechnenRand (d : Interpolation) flußBerechnen () : Vec5 flußBerechnen (links : Interpolation &, rechts : Interpolation&, zeit : Real) : Vec5 1 6 Außenflächen HexaederEulerImplementierung 4−PolygonRandImplementierungEuler flußBerechnen (e : 4-Polygonverbinder *, f : 4-Polygon *, zeit : Real) : Vec5 flußBerechnen (d : Interpolation &, f : 4-Polygon *, zeit : Real) : Vec5 flußBerechnenRand (e : 4-Polygonverbinder *) flußBerechnenRand (d : Interpolation &) flusßerechnen (e : 4-Polygonverbinder *, f : 4-Polygon *, zeit : Real) : Vec5 flußBerechnen (d : Interpolation &, f : 4-Polygon *, zeit : Real) : Vec5 flußBerechnenRand (e : 4-Polygonverbinder *) flußBerechnenRand (d : Interpolation &) Abbildung 3.18: Die an der Kette der Methodenaufrufe beteiligten Klassen und Schnittstellen in den Elementen bzw. Randelementen und Flächen. 68 KAPITEL 3. BASISENTWURF Das statische Schema (vgl. Abb. 3.18) sagt noch nichts darüber aus, wann und auf welche Aufforderung hin die benötigten Interpolationsobjekte erzeugt werden, wie sie der Fläche zugänglich gemacht werden, und auf welche Art der berechnete Wert an die anliegenden Elemente übergeben wird. 3.4.4 Methodenauflösung Die Berechnung der numerischen Flüsse auf den feinsten Flächen in der Hierarchie wird von außen aufgerufen (Iteration), die Kette der Operationen beginnt mit der entsprechenden Methode der Iterationsschnittstelle der Fläche (vgl. Kap. 3.3.1). Dann müssen zwei Situationen unterschieden werden: © Die betroffene Fläche liegt zwischen zwei Elementen des Gitters: Der numerische Fluß wird aus den Daten des Erhaltungsvektors der beiden anliegenden Elemente berechnet. © Die Fläche liegt am Rand der Geometrie, also zwischen einem Element und einem Randelement (vgl. Kap. 3.2.4). Die verschiedenen Randtypen sollen durch ein polymorphes Verhalten der beteiligten Randelemente realisiert werden (vgl. Kap. 1.2.4). Die Auswahl (engl.: dispatch) der Methode zur Berechnung der numerischen Flußfunktion soll offenbar von zwei polymorphen Objekten abhängen: Dem Element bzw. Randelement links und rechts der Fläche. Fij Vi Element Vj Element Fläche flußberechnen (zeit:Real) flußberechnen (zeit:Real, left :4−Polygonverbinder *, fläche : 4−Polygon *) Dji new () Interpolation flußberechnen (zeit : Real, rechts : Interpolation & , fläche : 4−Polygon *) new () Interpolation Dij flußberechnen (zeit : Real, links : Interpolation &, rechts : Interpolation &) fluß : Vec5 Gij (D ij (pk), D ji (p k)) fluß : Vec5 fluß : Vec5 Abbildung 3.19: Methodenauflösung im Innern des Gitters: In der dreistufigen Operationenkette werden die Interpolationsobjekte erzeugt und Referenzen darauf zur Fläche übertragen. Die Berechnung der Flußfunktion findet mit dem zweiten Methodenaufruf an die Fläche statt (Pfeil). 3.4. NUMERISCHES VERFAHREN 69 Diese mehrfache Methodenauflösung (engl.: multiple dispatch) wird durch die Programmiersprache C++ nicht unterstützt, ersatzweise liefert eine Kette von einzelnen Methodenaufrufen ein vergleichbares Resultat (visitor pattern) [12]. Die Abläufe sind in den Sequenzdiagrammen dargestellt (vgl. Abb. 3.19-3.21). Rückgabe- bzw. Resultattyp aller Methoden ist der Wert der numerischen Flußfunktion als Erhaltungsvektor, die erste Stelle, an der dieser Wert berechnet werden kann, führt die Berechnung durch und läßt die Aufrufkette zurückkehren. Im Inneren des Gitters ist das die Implementierung der Fläche, am Rand kann das Randelement diese Aufgabe übernehmen. Im Verlauf der Operatio nen werden auch die Interpolationsobjekte Q , H für die Daten links und rechts der Bezugsfläche Q erzeugt und gelöscht (rot). Sobald ein Randelement in der Kette auftritt, ändert sich deren Ablauf entscheidend. Berechnet das Randelement den Wert der Flußfunktion selbst (Ein- bzw. Ausströmungsrandbedingung), benötigt es dazu eventuell das Interpolationsobjekt für die Daten auf der anderen Seite der Fläche, d.h. von der benachbarten Gitterzelle. Trifft der Methodenaufruf von der Fläche zuerst auf das Randelement, dann werden weitere Methodenaufrufe erforderlich, um dieses Datum zum Randelement zu holen“ (vgl. Abb. 3.20). Andernfalls kommt der Aufruf vom Element ” und das Interpolationsobjekt liegt bereits vor (vgl. Abb. 3.21). Bemerkung: Der komplizierte Aufbau des numerischen Verfahrens weist den Vorteil auf, daß alle Situationen, die für ein Finite Volumen Verfahren in Frage kommen, ohne Änderungen an dieser Struktur (der Schnittstellen) realisiert werden können, insbesondere auch die Erweiterung auf eine parallele Verarbeitung (vgl. Kap. 4.3). ª Fij Vi Element Vj Rand Fläche flußberechnen (zeit : Real) flußberechnen (zeit:Real, links : 4−Polygonverbinder *, fläche : 4−Polygon *) flußberechnenRand (zeit : Real, rechts : 4−Polygonverbinder *) new () Interpolation Dij Gij (D ij (pk), D ji (p k)) flußberechnenRand (zeit : Real, links : Interpolation &) fluß : Vec5 fluß : Vec5 fluß : Vec5 Abbildung 3.20: Methodenauflösung am Rand des Gitters: Der Methodenaufruf verläuft von der Fläche zum Randelement (links), das durch weitere Methodenaufrufe die Daten des gegenüberliegenden Elements heranholt, um die Flußfunktion auszuwerten (Pfeil). 70 KAPITEL 3. BASISENTWURF 3.5 Lokale Gitterweitenanpassung 3.5.1 Anforderungen an die lokale Gitterweitenanpassung Vorab werden drei Eigenschaften zusammengestellt, nach denen das Konzept zur lokalen Gitterweitenanpassung sowohl im seriellen Basisentwurf, als auch in dessen Erweiterung auf die parallele Ausführung gestaltet werden soll: 1 Geometrie: Der vorliegende Entwurf beschränkt sich auf die isotrope, d.h. in alle Raumrichtungen gleichmäßige Verfeinerung eines Hexaederelements durch Achtelung (vgl. Kap. 3.2.5). Das Gitter darf in Folge der Gitterweitenanpassung auch nichtkonforme Nachbarschaftsbeziehungen enthalten (vgl. Kap. 3.2.3). 2 Reaktion auf Anforderungen: Die Algorithmen zur Gitterweitenanpassung bearbeiten elementweise vorliegende Anforderungen zur Verfeinerung bzw. Vergröberung. Dabei gelten vom mathematischen Standpunkt folgende Nebenbedingungen: Eine Anforderung zur Verfeinerung muß realisiert werden, eine Anforderung zur Vergröberung kann umgesetzt werden. Das bedeutet, daß das Gitter durchaus feiner sein darf, als vom numerischen Verfahren verlangt wird. 3 Balancierungsbedingung: Für jede Fläche, die ein angrenzendes Element oder Randelement hat, welches ein Blatt der entsprechenden Hierarchie ist, soll gelten: Entweder die Fläche ist selbst ein Blatt der Hierarchie oder alle Kinder der Fläche sind Blätter der Hierarchie. Alle Methoden, die zur Gitterweitenanpassung beitragen, sind so auszulegen, daß das Gitter jederzeit diese Balancierungsbedingung erfüllt, also auch während der Verfeinerung bzw. Vergröberung. Fij Vi Rand Vj Element Fläche flußberechnen (zeit : Real) flußberechnen (zeit : Real, links : 4−Polygonverbinder *, fläche : 4−Polygon *) Dji Interpolation new () flußberechnen (zeit : Real, rechts : Interpolation &) fluß : Vec5 Gij (. , Dji (pk)) fluß : Vec5 fluß : Vec5 Abbildung 3.21: Methodenauflösung am Rand des Gitters: Der Aufruf geht von der Fläche an das Element, wo ein Interpolationsobjekt erzeugt wird (rot). Mit der Referenz darauf kann das Randelement den Wert der numerischen Flußfunktion berechnen. 3.5. LOKALE GITTERWEITENANPASSUNG 71 Die Balancierungsbedingung sorgt einerseits für einen gleichmäßigen Verlauf der Verfeinerungstiefe, andererseits kann der Verfeinerungsalgorithmus selbst unter dieser Nebenbedingung auch auf anisotrope Verfeinerungsregeln ausgedehnt werden [3]. Hinweis: Damit die Balancierungsbedingung erfüllt wird, muß das Gitter gegebenenfalls stärker verfeinert oder schwächer vergröbert werden, als es vom ª numerischen Verfahren vorgeschrieben wird (vgl. Kap. 1.2.5). 3.5.2 Verfeinerung Wie bereits im Basisentwurf dargestellt ist, verfügen alle geometrischen Gitterobjekte über Operationen zur Teilung und sind darüber hinaus auch selbst der Ort, an dem die Assoziationen auf die neuentstandenen Objekte gespeichert werden (vgl. Kap. 3.2.5). Damit ist das Problem der korrekten Teilung und der Verwaltung der neu entstandenen Gitterobjekten rein lokal, es betrifft also nur das zur Teilung aufgeforderte Objekt. Zu untersuchen bleibt, wie die Beziehungen der geometrischen Objekte untereinander während des Verfeinerungsvorgangs modelliert werden sollen. Man findet die folgenden zwei Ausbreitungsrichtungen der Verfeinerungsoperationen, die entsprechende Navigationspfade aus den geometrischen Datenstrukturen des Gitters benötigen (vgl. Kap. 3.2): ➘ Propagation (in der Dimension absteigende Ausbreitung) der Verfeinerung: Die Teilung des höherdimensionalen geometrischen Gebildes er0...N Element Gitter Propagationspfad void verfeinern () void anfordern (Regel) Balancierungspfad 6 1 2 4−PolygonVerbinder ac bool balancieren () N Regel anzeigen () bool verfeinern (Regel) void unbedingtVerfeinern (Regel) hb ar 4−Polygon 1 2...8 1 Hexaeder 4−PolygonRandelement bool balancieren (Regel) void unbedingtVerfeinern (Regel) void anfordern (Regel) void verfeinern () bool balancieren (Regel) void unbedingtVerfeinern (Regel) Außenflächen 6 Kinder Randfläche 1 Abbildung 3.22: Klassendiagramm mit Darstellung der Beziehungen zwischen den an der balancierten Verfeinerung beteiligten Objekte bzw. zwischen deren Klassen. Kanten und Knoten sind nicht dargestellt. 72 KAPITEL 3. BASISENTWURF zwingt eine Teilung seiner niederdimensionalen Bestandteile. Dazu muß die Verfeinerungsregel des Bezugsobjekts auf eine Verfeinerungsregel seiner Berandung projiziert werden. ➚ Balancierung (in der Dimension aufsteigende Ausbreitung) der Verfeinerung: Die eingangs gestellte Forderung nach einer Bedingung zwischen der links- und der rechtsseitigen Verfeinerung an einer nichtkonformen Fläche muß im Verlauf der Verfeinerung befriedigt werden. Die erste Abhängigkeit ist unproblematisch, da die Aufruftiefe eindeutig durch die Anzahl der Raumdimensionen begrenzt ist, und jeweils die volle geometrische Information verfügbar ist, die benötigt wird, um die Teilungsregel in die nächstkleinere Dimension fortzusetzen. Im zweiten Punkt ist die Sache etwas schwieriger, denn alle betroffenen Objekte müssen durch entsprechende Methodenaufrufe in das Geschehen eingebunden werden. Ablauf Bevor der Verfeinerungsablauf anhand der zwei Sequenzdiagramme (vgl. Abb. 3.24, 3.23) in allen Einzelheiten dargestellt wird, sollte verstanden werden, welche Klassen, Schnittstellen bzw. Methoden beteiligt sind. weitere Flächen Hexaeder 4-Polygon 4-Polygon Kante Hexaeder verfeinern () verfeinern (Regel) balancieren (Regel) unbedingtVerf. (Regel) unbedingtVerf. (Regel) new () 4-Rand 4-Rand Hexaeder erfolgreich ? unbedingtVerf. () new () new () Kante Kante Kante 4-Polygon 4-Polygon 4-Polygon erfolgreich ? unbedingtVerf. () unbedingtVerf. (Regel) unbedingtVerf. (Regel) new () Hexaeder Hexaeder Hexaeder Abbildung 3.23: Ablaufschema der Verfeinerung an der Fläche und am Nachbarelement ausgehend von der Verfeinerung des Elements (links oben). 3.5. LOKALE GITTERWEITENANPASSUNG 73 Ausgelöst wird die Verfeinerung durch die entsprechende Methode der Klasse Gitter auf den Grobgitterelementen. Sie wird in der Elementhierarchie bis in die Blätter weitergeleitet, wo die durch einen Fehlerschätzer oder ein Verfeinerungskriterium gesetzte Anforderung vorgefunden wird. Der nachfolgende Verfeinerungsschritt läuft zweistufig ab (vgl. Abb. 3.23): Für den Versuch, exakt nach der Anforderung zu verfeinern, muß zuerst die Verträglichkeit mit der Balancierungsbedingung hergestellt werden. Die Methode balancieren (r : Regel) leitet diese Aufgabe an die anliegenden Nachbar- bzw. Randelemente weiter. Falls alle Methodenaufrufe ein positives Resultat liefern, darf das Bezugselement verfeinert werden und es ist sichergestellt, daß die Balancierungsbedingung erfüllt bleibt. Für den vorliegenden Fall mit der isotropen Elementverfeinerungsregel wird das Ergebnis der Methode balancieren (r : Regel) immer positiv sein, denn im Bedarfsfall wird jedes Nachbarelement verfeinert, dessen Verfeinerungssituation nicht mit der Balancierungsbedingung verträglich ist. Die vom Verfeinerungsalgorithmus genutzten Schnittstellen und Navigationspfade sind im Klassendiagramm (Abb. 3.22) zu erkennen: Die Propagation der Verfeinerung findet in der Dimension absteigend entlang der Geometriesockelklassen Hexaeder bzw. 4-PolygonRand, 4-Polygon und Kante statt. Hier ist jeweils die volle Geometrieinformation verfügbar, und die Teilungsregeln können vom anfordernden Objekt projiziert werden. Hexaeder 4-Rand 4-Polygon Kante verfeinern () verfeinern (Regel) balancieren (Regel) unbedingtVerf. (Regel) unbedingtVerf. (Regel) new () erfolgreich ? new () Kante Kante Kante 4-Polygon 4-Polygon 4-Polygon immer erfolgreich new () 4-Rand 4-Rand 4-Rand unbedingtVerf. () unbedingtVerf. (Regel) new () Hexaeder Hexaeder Hexaeder Abbildung 3.24: Ablaufschema der Verfeinerung am Randstück ausgehend von der Verfeinerung des anliegenden Elements (links oben). 74 KAPITEL 3. BASISENTWURF Aufwendiger ist der Balancierungspfad, der benötigt wird, um die Bedingungen an den nichtkonformen Übergängen einzuhalten (vgl. Kap. 3.2.3): Dort ist nur die Teilungsregel der zugehörigen Fläche bekannt, weshalb das Element bzw. Randelement aus den Regeln auf allen anliegenden Flächen eine passende Elementteilungsregel konstruieren muß. Das Sequenzdiagramm (vgl. Abb. 3.24) stellt die zeitlichen Abläufe während der Verfeinerung dar, falls ein Element und sein gegenüberliegendes Randstück sich verfeinern. In jedem Fall ist es wichtig, daß die Reihenfolge der Erzeugung der geometrischen Objekte mit den verschiedenen Dimensionen eingehalten wird: Eine Fläche kann sich nur verfeinern, wenn die anliegenden Kanten bereits konform mit der neuen Regel geteilt sind usw. Hinweis: Das Randelement darf auf den Methodenaufruf balancieren (r : Regel) mit einer sofortigen Teilung reagieren, da die Anfrage durch die Fläche hindurch sicherlich kompatibel mit der Elementanforderung ist (sie kommt von dort). Tatsächlich muß sogar so vorgegangen werden, weil das Randelement später nicht nochmals aktiv wird (außer man fügte weitere Methodenaufrufe in das Schema ein). ª 3.5.3 Vergröberung Definition: Der Elementbaum wird an der Stelle eines Elements als potentiell vergröberungsfähig bezeichnet, wenn alle Kinder des Elements Blätter sind. Das Element übernimmt nach der Vergröberung als Blatt die Aufgaben der gelöschten Blätter. Analoge Aussagen gelten für die Flächen- und Kantenbäume. Die Vergröberung findet für Elemente statt, falls alle Kinder weiterhin zur Vergröberung markiert worden sind (durch das numerische Verfahren), und die Vergröberung nicht die Balancierungsbedingung verletzt. Ablauf Elementweise stellt sich das Problem der Vergröberung einfacher dar, als das der Verfeinerung: Das Element in der Hierarchie, an dessen Stelle der Elementbaum potentiell vergröbert werden kann, löscht seine Kindelemente, die im Zuge einer früheren Verfeinerung erzeugt worden sind, und natürlich auch die inneren Flächen, Kanten und Knoten (vgl. Abb. 3.25, 5.8). Darüber hinaus werden Methodenaufrufe zwischen (Rand-) Element, Fläche, Kante und 4-Polygonverbinder benötigt, um die Balancierungsbedingung einzuhalten und die Möglichkeit zur Vergröberung an die niederdimensionalen Objekte der Berandung weiterzuvermitteln. 3.5. LOKALE GITTERWEITENANPASSUNG 75 Das Vergröberungskonzept profitiert hinsichtlich seiner algorithmischen Einfachheit von den hierarchischen Navigationswegen (vgl. Kap. 3.2.5). Durch die entsprechenden Assoziationen kann festgestellt werden, welche Gitterobjekte mit den Elementen gelöscht werden müssen: Alle Komponenten, auf die vom groben Element, auf den der Baum sich zurückzieht, zugegriffen werden kann, dürfen ohne weitere Überprüfung gelöscht werden; für die anderen am groben Element anliegenden Flächen und Kantenbäume wird durch Referenzenzählung festgestellt, ob sie noch von anderen höherdimensionalen Gitterobjekten benötigt werden. Das Sequenzdiagramm (vgl. Abb. 3.25) zeigt den Ablauf der Vergröberung am Element, anliegende Randelemente reagieren auf die Vergröberung der Fläche, so daß sie immer exakt deren Verfeinerungstiefe annehmen (nicht dargestellt). vergröbern () Hexaeder Feinere Hexaeder im Hexaeder Grobe Fläche Grobe Kante Hexaeder 4-Polygon Kante Feinere Flächen, Kanten und Knoten im Element, in der Fläche, in der Kante Hexaeder Hexaeder 4-Polygon Hexaeder Hexaeder Kante Hexaeder Hexaeder Knoten vergröbern () 6 x istBlatt () true Balancierungsbedingung true delete () delete () delete () delete () vergröbern () delete () vergröbern () delete () Abbildung 3.25: Sequenzdiagramm zum Ablauf der Vergröberung. Der Austausch mit dem Nachbarn zur Absicherung der Balancierungsbedingungen ist transparent gegenüber dem geometrischen Typ des anliegenden Nachbarelements. 76 KAPITEL 3. BASISENTWURF 77 Kapitel 4 Das parallele Simulationsprogramm Die Erweiterung des adaptiven Simulationsprogramms auf eine verteilt parallele Verarbeitungsstrategie berührt verschiedene Aspekte, und die folgenden Abschnitte zeigen, wie das numerische Verfahren für eine Parallelverarbeitung strukturiert werden muß, wie der Basisentwurf für das adaptive Gitter auf eine verteilte Datenhaltung erweitert werden kann und wie die neu hinzukommende Technik für die dynamische Lastverteilung aussieht. Dazu soll zunächst die Strategie zur Parallelisierung des Finite Volumen Verfahrens (1.13) und des darauf beruhenden Simulationsprogramms unter grundsätzlichen Gesichtspunkten dargestellt werden: Dies umfaßt den datenparallelen Ansatz, die Datenaufteilung und den Programmentwurf. Danach werden die zentralen Komponenten in einem parallelen numerischen Verfahren zur Lösung partieller Differentialgleichungen auf einem unstrukturierten lokal verfeinerten räumlichen Gitter beschrieben: Die Algorithmen zur Identifikation, zur lokalen Gitterweitenanpassung und zur dynamischen Lastverteilung sind die Bestandteile einer parallelen Gitterverwaltung, deren Auslegung entscheidend die Komplexität des Programmentwurfs wie auch die Leistungsfähigkeit des Gesamtverfahrens bestimmt. 4.1 Ansatz zur Parallelisierung Die Parallelisierung eines Finite Volumen Verfahrens durch die Aufteilung des unterliegenden Gitters der Volumenelemente ist ein ebenso natürlicher wie geeigneter heuristischer Ansatz [22, 36], der jedoch auch durch die Anwendung des wesentlich allgemeineren Schemas zur Parallelisierung eines Algorithmus erhalten werden kann (vgl. Kap. 2.1.3) [10]. 78 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM 4.1.1 Datenparalleler Ansatz Die Anwendung der vierstufigen Methodik zur Parallelisierung eines Problems (vgl. Kap. 2.1.3) zeigt, wie der Algorithmus des numerischen Verfahrens (vgl. Kap. 1.3) für die Parallelverarbeitung zerlegt wird: Partitionierung: Die Partitionierung des Problems in eine große Anzahl von Teilproblemen wendet sich auf die Daten an, wobei die Auswahl so zu treffen ist, daß mit jeder atomaren Einheit bereits die Daten für einen möglichst umfangreichen Teilalgorithmus des Gesamtverfahrens zur Verfügung stehen. Naheliegend ist die Idee, die Iterationen über alle Flächen bzw. Elemente des Gitters zu zerlegen (vgl. Kap. 1.3) . Kommunikationsstruktur: Untersucht man die Struktur der Datenzugriffe über die Grenzen der Elemente und Flächen hinaus, findet man folgende Situation: © Die Berechnung der numerischen Flüsse (1.13) und des Verfeinerungskriteriums (1.26) verwendet die Navigationsmöglichkeit entlang der geometrischen Nachbarschaftsrelation (vgl. Kap. 3.2.3). Weiterhin wird aus der Fläche heraus auf die Knoten zugegriffen. © Die Berechnung der Zeitschrittweite (1.24) verwendet .10 die Daten aus dem betreffenden Element und den Zugriff vom Element auf die Knoten. Die Zeitschrittweite wird als Minimum der berechneten Werte über alle Elemente des Gitters gebildet (globale Operation, vgl. Kap. 2.3.1). Agglomeration: Der Entwurf der Gitterdatenstrukturen enthält als Einheiten für eine Agglomeration die Elemente, Flächen, Kanten und Knoten des Grobgitters (vgl. Kap. 3.2.5), denn viele Navigationspfade verlaufen innerhalb dieser Einheiten. Prozessorzuweisung: Grobgitterelemente mit der gesamten enthaltenen Verfeinerungsstruktur können zu Teilgittern zusammengesetzt werden, die sich nur an den Rändern von einem vergleichbaren Gitter im sequentiellen Verfahren unterscheiden. Die Prozessorzuweisung soll die Abbildung (engl.: mapping) der Grobgitterelemente auf die einzelnen Teilgitter vornehmen, wobei jedes Teilgitter von einem Prozessor bearbeitet wird. Agglomeration und Prozessorzuweisung wenden sich an das selbe Problem, nämlich die Berechnung einer Aufteilung des Gitters in möglichst großvolumig zusammenhängende Bereiche. Letztlich ist es vor allem eine Frage der Effizienz, wo die Grenze zu ziehen ist, d.h. welche Elementzahl jeweils aggregiert werden soll, bevor die Prozessorzuweisung stattfindet. 4.1. ANSATZ ZUR PARALLELISIERUNG 79 Eine optimale Steuerungsmöglichkeit könnte diese Grenze im Verlauf der Simulation variieren, der vorliegende Entwurf ist dazu nicht in der Lage: Durch die Elementzahl des Grobgitters, das zu Anfang der Berechnung bereitgestellt wird, ist eine feste Aufteilung der Skalen von Agglomeration und Prozessorzuweisung für die gesamte Simulation vorgegeben, was in zwei Grenzfällen nachteilige Konsequenzen hat: © Solange das initiale, grobe Gitter nicht verfeinert wird, kann die Agglomeration keinen Effizienzgewinn bringen, die Aufteilung wird allein von der Prozessorzuweisung bestimmt: Die Möglichkeit zur Steigerung der Effizienz einiger Algorithmen besteht eventuell nicht mehr. © Enthält das Grobgitter nur ein einziges Element, dann kann, gleichgültig wieviele Elemente im feinsten Gitter entstanden sind, keine Aufteilung auf mehrere Teilgitter erreicht werden: Die Option zur Parallelverarbeitung geht verloren. Der zweite Punkt stellt das gravierendere Problem dar, weshalb im Zweifelsfall ein Grobgitter mit hoher Elementzahl verwendet werden sollte (vgl. Kap. 6.4.1). 4.1.2 Gliederung des Entwurfs Weiterhin stellt sich hier die Frage, wie der objektorientierte Ansatz auf die verteilte Datenhaltung ausgedehnt werden kann, ohne dem seriellen Entwurf « « « « « « « « « « « « « « « « « « « « « « « « « Adaptives Gitter Datenhaltung Numerisches « Verfahren « « « « « « « « « « « « « « « « « « « « Parallele Erweiterung « « « « « « « « « « « Makrogitterumbau Initial « « « « « Grobgittertransfer « « « « « « « « « « « « « « Dyn.« Lastverteilung « « « « Lastausgleich « « « « « « « « « « « « « Reidentifikation « « « « « « « « « « « « « « « « « « « « Initial « « « « Identifikation « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « Teilgittergrenzen « « « « « « Datenaustausch « « « « « « « « « « « « « « « Benötigt XX zu Abbildung 4.1: Ausdehnung des Basisentwurfs zu einer parallelen Gitterverwaltung, die das Kooperationspotential zwischen den Modulen nutzt. Die Pfeile zeigen welche Aufgaben wohin delegiert werden. 80 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM ein globales Konzept mit Zugriffsrechten auf alle Daten und Funktionen überzustülpen. Dies wird nicht allein aus abstrakten Überlegungen heraus angestrebt: Der Erhalt der Kapselung der Daten und der Aufteilung der Zuständigkeiten aus dem seriellen Entwurf sowie deren sinngemäße Übernahme in das verteilte Konzept sichern die Entwicklung gegen eine unbeherrschbare Zunahme von Komplexität und Funktionsüberschneidungen ab. Wie dieses Ziel hier erreicht wird, läßt sich am Strukturplan nachvollziehen (vgl. Abb. 4.1): Die Aufteilung der seriellen Gitterverwaltung auf die Basismodule Adaptive Gitterverwaltung, Numerisches Verfahren und Makrogitterumbau (links) unterstützt entscheidend die verteilte Gitterverwaltung. Deren wichtigste Komponenten Dynamische Lastverteilung, Identifikation und Datanaustausch sind rechts im gelb unterlegten Bereich eingetragen. Die Komponenten des sequentiellen Basisentwurfs selbst erfahren ebenfalls eine Ausdehnung in das parallele Konzept hinein, die in Form einer wohldefinierten Funktions- bzw. Datenausdehnung im Sinne der Objektorientierung erfolgt. 4.2 Aufteilung des Gitters Definition: Die nichtüberlappende Zerlegung des ursprünglichen Gitters in eine Anzahl von Teilgittern ist durch die folgenden Eigenschaften eindeutig beschrieben (vgl. Abb. 4.2): 1. Jedes Kontrollvolumen "# des numerischen Verfahrens (1.13) kommt in genau einem Teilgitter vor, d.h. in genau einem Teilgitter existiert ein Objekt, das die Geometrie des Kontrollvolumens " beschreibt. 0 1 2 3 Abbildung 4.2: Nichtüberlappende Gebietszerlegung für ein Hexaedernetz in einem Würfel (links) und als schematische Darstellung für ein Dreiecksgitter aus acht Elementen. 4.2. AUFTEILUNG DES GITTERS 81 2. Falls ein Element, ein Randelement, eine Fläche eine Kante oder ein Knoten in einem bestimmten Teilgitter vorkommt, dann enthält dieses Teilgitter auch alle Elemente, Randelemente, Flächen, Kanten und Knoten die vom Bezugsobjekt durch die Navigationspfade der Hierarchie und der geometrischen Relationen erreicht werden (vgl. Kap. 3.2.2, 3.2.5). 3. Falls ein Element in einem bestimmten Teilgitter vorkommt, dann enthält dieses Teilgitter auch alle Randelemente die vom Bezugselement durch den Navigationspfad der geometrischen Nachbarschaft erreicht werden können (vgl. Kap. 3.2.3). Diese Randelemente gehören zum physikalischen Gebietsrand, der nachfolgend auch äußerer Rand genannt wird. 4. Jeder Navigationspfad der geometrischen Nachbarschaft endet bei einem Element des Teilgitters oder bei einem Randelement (vgl. Kap. 3.2.3). Der Navigationspfad der Nachbarschaft verläuft demnach niemals zwischen zwei verschiedenen Teilgittern, sondern endet gegebenenfalls bei einem Randelement des künstlichen inneren Teilgitterrands. Diese Art der Aufteilung bedingt, daß kein Navigationspfad von einem Teilgitter in ein anderes gefunden werden kann. Die Realisierung der Navigationspfade durch Zeiger und Referenzen kann also auch dann beibehalten werden, wenn die Teilgitter nicht in einem einheitlichen Adreßbereich gespeichert werden (Voraussetzung für die Parallelverarbeitung auf Multicomputern mit dem Message Passing Programmiermodell, vgl. Kap. 2.1.1, 2.3.1). Die Aufteilung eines Gitters in eine Anzahl von Teilgittern legt nahe, möglichst weitgehend die Darstellung der Teilgitter derjenigen des ursprünglichen MonoGitterkonzepts anzupassen. Der vorliegende Entwurf unterscheidet hinsichtlich der Funktionalität, die auf dem Niveau der Datenstrukturen und Basisalgorithmen (vgl. Kap. 3) spezifiziert ist, nicht zwischen einem Gitter in einem seriellen Verfahren und einem Teilgitter im parallelen Verfahren. Bemerkung: Die Topologie eines unstrukturierten Hexaedernetzes kann recht kompliziert sein, aber in der Regel lassen sich die wesentlichen Aspekte bereits an der stark vereinfachten Situation eines strukturierten, in vier Teile zerlegten Dreiecksnetzes (vgl. Abb. 4.2) herausarbeiten. Die nachfolgenden Abschnitte verwenden diese reduzierte Darstellung als Grundlage für Erläuterungen, wann immer die Zusammenhänge durch den Übergang auf ein komplexes dreidimensionales Gitter keine inhaltliche Veränderung erfahren. ª 82 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM 4.3 Numerisches Verfahren Die Ausdehnung des numerischen Verfahrens in das verteilte Gitterkonzept hinein betrifft die Steuerung der globalen Zeitschrittweite (1.24) und die Bereitstellung eines Interpolationsobjektes für die Berechnung der numerischen Flußfunktion (vgl. Kap. 1.2.2). Zeitschrittweite: Zunächst ist klar, daß die Bestimmung des globalen Minimums der Zeitschrittweite über alle Teilgebiete nach genau dieser (direkten) Vorschrift erfolgen muß, solange mit global einheitlichen Zeitschrittweiten gerechnet wird. Bemerkung: Der dazu erforderliche globale Kommunikationsschritt wirkt synchronisierend, weshalb es günstig ist, ihn an einer Stelle durchzuführen, an der bereits ein synchroner Ausführungsverlauf aus einem anderen Grund ª vorliegt. Berechnung der numerischen Flüsse: Die Zugriffe von den Flächen auf die anliegenden Elemente im numerischen Verfahren, wie sie im Basisentwurf zu finden sind, kann auf einem verteilten Gitter in dieser Form nicht mehr direkt realisiert werden, sobald die Fläche ein Teil des inneren Gebietsrandes ist: Nach der verwendeten Definition der Gebietszerlegung endent der Navigationspfad der geometrischen Nachbarschaft in diesem Fall bei einem Randelement des inneren Randes (vgl. Kap. 4.2). Interpolationsobjekt als Teil des Randelements Teilgittergrenze Anfordern: Interpolationsobjekt Anfordern: Interpolationsobjekt vom Strom rekonstruieren Interpolation ¬ ¬ ­ ­ ¬ ¬ ­ ­ ¬ ¬ ­ ­ Interpolation erzeugen Interpolation Schnittstelle (abstrakt) an das Randelement aushändigen Lesen des Zustands für das interne Interpolationsobjekt Interpolationsobjekt in den Datenstrom schreiben Datenstrom Abbildung 4.3: Datenaustausch im numerischen Verfahren über die Schnittflächen der Teilgitter-Teilgittergrenzen hinweg. Dazu wird auf die Möglichkeit zurückgegriffen, wie im numerischen Verfahren vom anliegenden Element ein Interpolationsobjekt erzeugen zu lassen. 4.3. NUMERISCHES VERFAHREN 83 Hilfreich erweist sich an dieser Stelle die Konstruktion mit den aufgelegten Randelementen (vgl. Kap. 3.2.4): Dort können Daten zwischengespeichert werden, und es lassen sich Methoden definieren, die auf Anforderungen aus dem numerischen Verfahren der Fläche gegenüber ein elementähnliches Verhalten aufweisen. Dem liegt die folgende Idee zugrunde: Im Basisentwurf für das geometrische Nachbarschaftskonzept und das numerische Verfahren war stets vermieden worden, Kenntnisse über den konkreten Elementtyp neben einer Fläche vorauszusetzen. Diese Abstraktion hat zu den Interpolationsobjekten als Vermittlung zwischen den Daten auf einem unbekannten geometrischen Elementtyp und dem bekannten geometrischen Typ der Fläche geführt (vgl. Kap. 3.4). Im Zuge der Erweiterung des numerischen Verfahrens auf verteilte Gitterdaten wird entscheidend vom diesem Abstraktionsaufwand profitiert. Was auf einer Fläche, die zum inneren (künstlichen) Rand eines Teilgitters gehört, vom anliegenden Nachbargitter bekannt sein muß, ist lediglich das (äußere) Interpolationsobjekt für diese Fläche. Elementtyp und weitergehende Referenzen sind nicht erforderlich. Daher kann auf komplizierte Datenausdehnungen wie Geisterzellen [36] verzichtet werden. Derartige Hilfskonstruktionen sind immer dann nötig, wenn das numerische Verfahren in konkreten geometrischen Typen und Datenstrukturen formuliert ist, bzw. wenn der Navigationspfad längs der Nachbarschaftsrelation keine Abstraktion von der Elementklasse enthält. Das Schema (vgl. Abb. 4.3) zeigt den Datenaustausch für das numerische Verfahren. Die Realisierung des Randelements für den inneren Rand läßt vom gegenüberliegenden Element ein Interpolationsobjekt erzeugen. Falls dessen Schnittstelle auch Methoden zur Objektserialisation [17], also zum Schreiben Alle identifizierten Flächen Fläche Fij Strom Element DatenZumStromSchreiben (s : Strom &) new () Interpolation Dji InterpolationSchreiben (d : Interpolation &) Schreiben (s : Strom &) Abbildung 4.4: Schreiben der Interpolationsobjekte in den Datenstrom: Wie im Verlauf des numerischen Verfahrens erzeugt das Element ein temporäres Interpolationsobjekt (Pfeil), dessen Zustand hier aber in einen Datenstrom geschrieben wird. 84 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM und Lesen seines Zustands in einen bzw. aus einem Datenstrom enthält, kann das Interpolationsobjekt ohne Kenntnis seines konkreten Typs (hier also der Approximationsordnung) in den Datenstrom geschrieben werden. Das Randelement im angrenzenden Teilgitter versucht nach der Übertragung der Daten, den darin enthaltenen Zustand des Interpolationsobjekts in eine konkrete Implementierung zu lesen. Dieses Interpolationsobjekt ist allerdings nicht nur von vorübergehender Lebensdauer, sondern fester Bestandteil des Randelements, und wird von diesem verwendet, um im numerischen Verfahren auf Anforderung der Fläche oder des anliegenden Elements das für diesen Zeitschritt korrekte Interpolationsobjekt zu liefern. Bemerkung: Wird der Ansatz zur Objektserialisation aus der Programmiersprache JavaTM [17] zugrunde gelegt, könnte das Problem des Einlesens eines Objekts von unbekanntem Typ in eine konkrete Implementierung (Konsistenzbedingung) vermieden werden, weil das Randelement dann nur mit der Schnittª stelle eines abstrakten Interpolationsobjekts umgehen müßte. Die Sequenzdiagramme (vgl. Abb. 4.4, 4.5) zeigen, wie diese Aufgaben in verschiedenen Schritten gelöst werden. Es fällt auf, daß die Aufrufkette bei der Fläche beginnt und nicht beim Randelement, wie vielleicht zu erwarten wäre. Der Grund dafür ist, daß für die Flächen eine Identifikationsrelation (vgl. Kap. 4.4) besteht, die zur Zuordnung der Randelemente zu den durch sie repräsentierten Elementen verwendet wird. 4.4 Identifikation Nachdem die Aufteilung des Gitters zur Parallelverarbeitung des numerischen Verfahrens festgelegt ist (vgl. Kap. 4.2) stellt sich die Frage, wie diejenigen Flächen, Kanten und Knoten des Gitters, die in mehreren Teilgittern vorkommen, miteinander identifiziert, also in Verbindung gebracht werden können. An- Alle identifizierten Flächen Fläche Fij DatenVomStromLesen (s : Strom &) RandPll Dji Interpolation Strom InterpolationVomStromLesen (d : Interpolation &) Lesen (s : Strom &) Abbildung 4.5: Das Lesen der Interpolationsobjekte erfolgt ebenfalls durch Vermittlung der (identifizierten) Flächen. Im Unterschied zum numerischen Verfahren ist das Interpolationsobjekt (Pfeil) hier Bestandteil des Randelements für den inneren Gebietsrand. 4.4. IDENTIFIKATION 85 schließend muß festgelegt werden, wie diese Verbindungen durch geeignete Datenstrukturen im Programm zu realisieren sind. Nachfolgend werden Gitterobjekte, also Datenstrukturen durch die die Geometrie von Elementen, Randelementen, Flächen, Kanten oder Knoten des geometrischen Gitters beschrieben wird durch Großbuchstaben ® <H¯<@g@i@ bezeichnet. 4.4.1 Identifikationsrelation Definition: Zwei Datenstrukturen ® <u¯ in verschiedenen Teilgittern erfüllen eine Identitätsrelation :I® <u¯°> ²± genau dann, wenn sie die selbe geometrische Situation im Gitter beschreiben. Die Identifikationsrelation : @g<@ > i± ist eine symmetrische, reflexive und transitive Relation. Ferner orientiert sich diese Definition der Identität an der durch ein Objekt repräsentierten geometrischen Information, die sich während dessen Lebensdauer nicht ändert. Bemerkung: In der Praxis kann nur eine Richtung der Definition genutzt werden, nämlich jene, daß Datenstrukturen, die eine Identifikationsrelation erfüllen, auch im Rahmen der Genauigkeit der verwendeten Arithmetik identische Geometrien beschreiben. Die umgekehrte Richtung, also durch den Vergleich der geometrischen Eigenschaften die Identifikationsrelation zu impleª mentieren, ist hingegen nicht empfehlenswert. 4.4.2 Verbindungssterne Da die Identifikationsrelation transitiv ist, muß in der Praxis sichergestellt sein, daß ausgehend von einem Objekt ® alle Objekte ¯W<´³<t@i@i@ in anderen Teilgittern 1 2 2 3 1 2 2 3 4 5 5 6 4 5 5 6 4 5 5 6 4 5 5 6 7 8 8 9 7 8 8 9 Abbildung 4.6: Verbindungssterne zwischen identifizierten Knoten eines Dreiecksgitters: Die Vollverbindung speichert alle Zuordnungen auf jedem Objekt (links). Durch die Auszeichnung eines Objekts als Besitzer oder Zentrum kann die gleiche Funktionalität mit weniger Verbindungen erreicht werden. 86 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM gefunden werden können, die mit diesem identifiziert sind: Die Skizze (vgl. Abb. 4.6) zeigt zwei Möglichkeiten, den Identifikationsstern auszulegen: Die vollständige Verbindung stellt die gesamte Information auf jedem Objekt bereit. Um Informationen zwischen zwei beliebigen Enden des Sterns auszutauschen, genügt hier ein Schritt in der Datenübertragung. Die Situation rechts zeichnet den Knoten des Teilgitters links oben als Zentrum des Sterns aus. Der Austausch von Information zwischen zwei beliebigen Endpunkten verläuft über dessen Zentrum in zwei Schritten. Dieser Ansatz benötigt geringere Datenmengen, ist aber gegenüber der Latenzzeit [15] des Kommunikationsvorgangs sensibler. Alle anderen topologischen Ausprägungen des Verbindungssterns (z.B. Ringe, Bäume oder allgemeine Würfel) haben den entscheidenden Nachteil, daß die Anzahl der benötigten Kommunikationsvorgänge (und damit die Latenzzeit einer bestimmten Operation) von der Größe des Sterns abhängt. Der vorliegende Entwurf macht von der zweiten beschriebenen Möglichkeit Gebrauch: Unter allen Objekten, die in einem Verbindungsstern zusammenhängen, wird das zu dem Teilgitter mit der kleinsten logischen Nummer gehörende als Zentrum ausgezeichnet. 4.4.3 Schlüssel Die Topologie eines unstrukturierten Gitters liegt zum Zeitpunkt der Programmentwicklung nicht fest, weshalb keine Möglichkeit zu einer impliziten Darstellung der Identifikationsrelation, wie z.B. durch eine Indextransformation auf strukturierten Gittern, besteht. Eine geeignete Vorgehensweise zur Implementierung der Identifikationsrelation besteht darin, alle Objekte, für die diese Relation überprüft werden muß, mit einem Schlüssel auszustatten, so daß die Schlüssel verschiedener Obekte genau dann gleich sind, wenn die Identifikationsrelation erfüllt ist [5]: Definition: Allgemein ist ein Schlüssel µ ein Datentyp für den eine strikt schwache Ordnungsrelation : @i<t@Q>u¶¸·º¹ definiert ist: 1. Für zwei Schlüssel » und » gilt: Entweder {: » < » > ¸¶ ·º¹ oder {: » < » > ¶¸·º¹ trifft zu. Zwei Schlüssel gelten als gleich, falls :{» < » > ¶¸º · ¹ und :{» < » > ¶¸·º¹ falsch sind. 2. Für drei Schlüssel » , » und » für die :» < » > ¶¸·º¹ wahr ist, gilt: Entweder :» < » > ¶´·º¹ oder :{» < » > ¶´·º¹ trifft zu. Hier muß weiterhin vorausgesetzt werden, daß der verwendete Datentyp einen Austausch von Schlüsseln zwischen verschiedenen Prozessen der Anwendung mit den Mitteln des Message Passing Programmiermodells ohne Verlust von Information zuläßt (vgl. Kap. 2.3). 4.4. IDENTIFIKATION 87 Da die Vergabe und Verwaltung global (bezüglich aller Teilgitter) eindeutiger Schlüssel für Flächen, Kanten und Knoten sehr aufwendig ist, sind zunächst einige Forderungen an ein Konzept zur Vergabe von Schlüsseln und an die Schlüssel selbst zusammengestellt, die es unter anderem ermöglichen, die geometrischen Eigenschaften des Gitters zur Verbesserung der Effizienz heranzuziehen: Die Schlüssel sollen möglichst einfach sein, wenig Daten beanspruchen und die Implementierung schneller Vergleichsoperationen zulassen. Begründung: Diese Bedingung ist die Voraussetzung dafür, daß die Identifikationsabbildung nach einer Neuverteilung des Gitters schnell und effizient berechnet werden kann. Die Schlüssel sollen voneinander abgeleitet werden können. Begründung: Dies wird nahegelegt, damit der Schlüssel für ein Gitterobjekt höherer Dimension (Kante, Fläche, Element) aus den Schlüsseln der anliegenden Objekte niedriger Dimension aufgebaut sein kann (vgl. Abb. 4.8). Möglichst wenige Schlüssel sollen zu Beginn der Identifikation auf dem verteilten Grobgitter gespeichert sein. Begründung: Falls der Algorithmus mit einem verteilten Startgitter beginnt, müssen dort die Daten zur Berechnung der Identifikationsabbildung durch den (externen) Partitionierer hinterlegt werden. Bei einer Umverteilung des Gitters müssen die Basisinformationen zur Neuberechnung der Identifikationsabbildung zusätzlich übertragen werden, insofern ist auch hier auf Umfang, Komplexität und Redundanzfreiheit zu achten. Die Schlüssel sollen für Objekte gleicher geometrischer Dimension von gleichem Typ sein. Begründung: Auf diese Art kann der Identifikationsalgorithmus unabhängig von den verwendeten geometrischen Elementtypen im numerischen Verfahren definiert werden. Der Typ des Schlüssels wird anhand des Typs der von dem betreffenden Objekt implementierten Iterationsschnittstelle bestimmt (vgl. Kap. 3.3, Abb. 3.16). Um den aufgestellten Forderungen zu entsprechen, wird das folgende Schlüsselkonzept als Basis des Identifikationsmoduls in den Entwurf integriert. Die Typen der Schlüssel sind innerhalb jeder Dimension der geometrischen Objekte einheitlich. Die nachfolgende Aufstellung zeigt wie für Knoten, Kanten und Flächen passende Schlüssel erzeugt werden können: 88 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM ¼ = (1) ¼ ½ Kante: Der Schlüssel einer Kante wird aus dem geordneten Paar der Nummern der anliegenden Grobgitterknoten gebildet. = (1,4) ¾ ¼ ½ = (1,4,7) ¼ ¾ ¿ Knoten: Als Schlüssel eines Grobgitterknotens wird eine global eindeutige Knotennummer verwendet. Diese Knotennummer wird nach dem Aufbau des Grobgitters nicht mehr verändert und es kommen keine weiteren Nummern hinzu. ½ Fläche: Für eine beliebige Fläche wird der Schlüssel aus den globalen Knotennummern dreier anliegender Knoten gebildet. Damit ist der Schlüssel bereits eindeutig. Die drei Knoten sind dabei wie folgt auszuwählen: Die kleinste anliegende Knotennummer und die Nummern der längs des Polygons benachbarten Knoten bilden aufsteigend geordnet einen Vektor mit drei Einträgen. = (1,4,7) Hinweis: Mit den Konventionen zur globalen Ausrichtung der Flächen und Kanten im Grobgitter kann auf die Ordnung der Paare bzw. Vektoren verzichtet ª werden (vgl. Kap. 3.2.2). 4.4.4 Speicherung der Identifikationsrelationen Durch das beschriebene Schlüsselkonzept kann die Identifikationsrelation paarweise nachgeprüft werden. Damit liegt aber noch kein ausreichend leistungsfähiges Verfahren zum Austausch von Daten im numerischen Verfahren zwischen den identifizierten Gitterobjekten vor (vgl. Kap. 4.3). Deshalb wird aus den Informationen, die in Form der Schlüssel zur Verfügung stehen, eine neue Datenstruktur berechnet, die einen effizienteres Vorgehen beim Datenaustausch unterstützt [5, 22]. Diese Technik wurde zunächst für verteilte Gitter ohne Gitterweitenanpassung und dynamische Lastverteilung entwickelt, weil in diesem Fall die Datenstruktur nur genau einmal zu Anfang berechnet werden muß [14], und sich der entstehende zusätzliche Aufwand in jedem Fall durch die erhebliche Beschleunigung im Datenaustausch auszahlt. Damit dieser Ansatz auch auf eine Gitterverwaltung mit zeitlich veränderlicher Gitterstruktur übertragen werden kann, müssen sehr effiziente Algorithmen eingesetzt werden, weil andernfalls die Neuberechnung der Datenstruktur bei häufiger Veränderung des Gitters zu gravierenden Leistungseinbußen führt. 4.4. IDENTIFIKATION 89 Datenstruktur Da im numerischen Verfahren alle Operationen über Elemente oder Flächen iteriert stattfinden, kann auch der Datenaustausch entsprechen zusammengefaßt werden. Der Behälter, der lokal auf einem Teilgitter die Menge der mit Objekten eines anderen Teilgitters identifizierten Gitterobjekte speichert, muß dann keinen direkten Zugriff auf der Basis von Schlüsseln ermöglichen, vielmehr kann anhand der Darstellung (vgl. Abb. 4.7) nachvollzogen werden, daß in einem Kommunikationssystem mit Vektorpuffern versucht werden sollte, möglichst viele Beziehungen gleichzeitig in einem Kommunikationsschritt zu bearbeiten. Im vorliegenden Fall sind alle Knoten, die zum linken und rechten Teilgitter gehören, im Sinne der beschriebenen Operation (Zuweisung, Kopie) gleichwertig. 1. Die Daten der Knoten im linken Teilgitter werden in einer vorgegebenen Reihenfolge in die Sendezeile geschrieben. 2. Übertragen der Sendezeile in die Empfangszeile des rechten Teilgitters. 3. Die Daten werden in der bestehenden Reihenfolge gelesen und an eine Stelle geschrieben, die durch einen Vorwärtsiterator des entsprechenden Behälters [2, 27] referenziert wird. Die Information der Identifikationsabbildung liegt hier auf keinem Teilgebiet vollständig vor, sie ist vielmehr im Zusammenspiel der korrespondierenden Vorwärtsiteratoren zu finden. Zeile an ein anderes Teilgitter übertragen Daten in die Sendezeile schreiben 4,5 9,0 0,0 1,1 4,5 ?,? 8,5 3,7 9,0 ?,? 6,2 1,9 0,0 ?,? 2,7 Daten aus der Empfangszeile lesen 4,5 9,0 0,0 Abbildung 4.7: Datenstruktur zur Speicherung der Identifikationsrelationen: Es genügt die Möglichkeit zur Vorwärtsiteration längs der identifizierten Objekte, um die Daten in die Sendezeile zu schreiben, bzw. sie aus der Empfangszeile des Kommunikationssystems zu entnehmen. 90 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM Algorithmus zur Berechnung der Datenstruktur Ein einfacher Algorithmus zur Berechnung der Datenstruktur aus den lokal verfügbaren Schlüsseln sieht für Knoten, Kanten und Flächen identisch aus und benötigt zwei Kommunikationsschritte (vgl. Kap. 5.8). Algorithmus 4.1: Der Algorithmus ist auf allen Teilgebieten in gleicher Weise auszuführen, wobei nachfolgend die Ausführung auf dem Teilgebiet zum Index ÀEJÁ¨ <t@i@i@g< ¥ , N5à betrachtet wird. Zu Beginn liegen auf dem Teilgebiet die Schlüssel T *+ Á» * Es gibt im Teilgebiet À ein lokales Objekt zu » “ à vor (vgl. ” Kap. 4.4.3). 1. Führe einen (globalen) Kommunikationsschritt mit jedem Teilgebiet zum Index Ä * Ä+ Å À durch: Sende dabei die Menge T und empfange T . ¡ U ) für jeden Schlüssel »GE 2. Bestimme aus den vorliegenden TºÆ £ Æ l xQxQx Ç Abb. 4.6): den Verbindungsstern È:{» > (Vgl. Kap. 4.4.2, È:» > *+ T ÁzÄoEJÁɨ <@g@i@i< ¥ , N5à * »mE T à @ Erfolgt die Berechnung von È:» > für einen bestimmten Schlüssel auf mehreren Teilgebieten, dann sind die jeweils berechneten È:{» > identisch. 3. Bilde für jeden Index Ä < ÄÊ+ Å À eine Familie von Schlüsseln (hier: eine Menge in beliebiger aber festgelegter Reihenfolge): T 1*Q+ÌË » l <t@i@g@i< » < @g@i@g< » & U ) * » E T und À + µSÒ @ ÆÂÏ5hÍÐ fiÎ ¶´Ñ v y Das Teilgebiet wird genau dann Besitzer eines Objekts, wenn dieses dort lokal vorliegt und jedes andere Teilgebiet, auf dem ein Objekt mit identischem Schlüssel vorliegt, einen größeren Index hat. (vgl. Kap. 4.4.2). 4. Führe einen (lokalen) Kommunikationsschritt mit jedem Teilgebiet zu ei nem Index Ä * ÄÊ+ Å À <#T SÓ T +Y Å Ô aus: Sende T und empfange T . Å Ô eine Liste Ö mit Referenzen auf die Erstelle zu jedem Index Ä * T +Õ mit den Schlüsseln »mET verbundenen lokalen Objekte. 5. Suchvorgang: Erstelle zu jeder Familie T eine Liste × mit Referenzen auf die mit den Schlüsseln »ØET verbundenen lokalen Objekte. Ù Nach Abschluß des Algorithmus liegen auf allen Teilgebieten Listen Ö und × vor, für die gilt: × +ÚÔ @ 2 2 2 2 2 2 2. Ö + × und Ö + 1. Ö + 2 2 × @ Was im Besitz des Gebiets À liegt (Liste Ö ), liegt im Nicht-Besitz des Gebiets Ä (Liste × ) . 4.4. IDENTIFIKATION 3. 91 b À<Ú Ä EÌÁ¨ <@g@i@g< ¥ , N5à gilt: Die in der Liste Ö auf Teilgitter À und in der Liste × auf Teilgitter Ä enthaltenen Referenzen verweisen auf Objekte mit identischen Schlüsseln (vgl. Abb. 4.7). Algorithmus 4.1 ist generisch, d.h. er ist identisch zur Berechnung der Datenstrukturen für Knoten, Kanten und Flächen anwendbar. Dies kann in beliebiger Reihenfolge nacheinander geschehen, es bestehen keine Abhängigkeiten. Der Mangel des Algorithmus läßt sich im ersten Schritt bei der Berechnung der Verbindungssterne È:» > erkennen: Der globale Austausch aller Schlüssel ist aufwendig und nicht skalierbar. Falls jedoch der Verbindungsstern È:» > für jeden lokalen Schlüssel »ÕE T schon a-priori bekannt ist, kann auf den nichtskalierbaren Teil des Algorithmus verzichtet werden, denn die weiteren Schritte betreffen nur Teilgitter, die geometrisch in einem Punkt, einer Kante oder einer Fläche aneinander grenzen. Durch eine geeignete Aufteilung des Gitters kann hier eine skalierbare Situation erreicht werden [5]. Die nachfolgend beschriebene Modifikation des Algorithmus nutzt aus, daß die Datenstruktur nicht für beliebige Mengen von Schlüsseln berechnet wird, sondern für Knoten, Kanten und Flächen eines geometrischen Gitters. Beschleunigung des Algorithmus Eine Möglichkeit zur Beschleunigung des Identifikationsalgorithmus 4.1 ist durch die geometrischen Zusammenhänge im Gitter gegeben, unter deren 0 9 6 0 3 3 0 1 2 3 4 6 ⇓ 5 0 0 5 0 6 4 ⇓ 6 0 5 1 3 0 Abbildung 4.8: Beschleunigung der Identifikationsphase durch Schätzung der Verbindungssterne: Sobald die Verbindungssterne der Knoten des Grobgitters bekannt sind, können die der Kanten und Flächen durch Schnittmengenbildung abgeschätzt werden. 92 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM Ausnutzung sich das Problem, daß alle Schlüssel von allen Teilgittern für jedes Objekt zu allen anderen Teilgittern kommuniziert werden müssen, für die zu Flächen und Kanten gehörenden Schlüssel umgehen läßt: Wie im Schema (vgl. Abb. 4.8) angedeutet ist, kann der maximale Verbindungsstern für den Schlüssel »;:µ > einer Kante µ bzw. »;:Û > einer Fläche Û durch die Schnittmenge der Verbindungssterne aller Schlüssel »;:DÜ & > , die zu anliegenden Knoten Ü & gehören, abgeschätzt werden: » + »;:µ > bzw. » + »;:{Û > * È:{» >ÞÝÈ ß :{» >A<àÈ ß :{» > *+ á â ÑIÏPãÂÆ bzw. â ÑIÏPãÂä È:{» :IÜ u> >@ (4.1) Dies senkt die Menge der zu verteilenden Daten entscheidend und führt von der unskalierbaren (alle Teilgitterdaten überall) zu einer skalierbaren Situation (nur Daten der benachbarten Teilgitter). Modifizierter Algorithmus 4.2: Ein beschleunigter Algorithmus zur Berech nung der Datenstruktur :IÖ < × > für Knoten, Kanten und Flächen entsteht, falls der erste Schritt des Algorithmus 4.1 durch die untenstehenden Schritte 1' und 1” ersetzt wird und die Berechnung zuerst für die Knoten des Gitters durchgeführt wird: 1' Wird die Datenstruktur :IÖ < × > für Knoten des Gitters berechnet, dann b setze »E T * È ß :» > + Áɨ <t@i@g@i< ¥ , N5à , sonst berechne È ß :{» > für den Schlüssel » nach der Vorschrift (4.1). 1” Lokaler Kommunikationsschritt: Für alle lokal vorliegenden Schlüssel »mE T : Verteile » an alle Teilgitter Ä für die gilt ÄJE È ß :» > , wobei die Herkunft jedes eingehenden Schlüssels bekannt ist. Ù 4.4.5 Gesamtverfahren zur Identifikation Mit dem Schlüsselkonzept (vgl. Kap. 4.4.3) und den Datenstrukturen zur Speicherung der Identifikationsrelationen (vgl. Kap. 4.4.4) liegen Techniken vor, die auf sporadische Änderung der Gitterstruktur angemessen schnell reagieren können und deshalb geeignet sind, nach der dynamischen Lastverteilung alle Datenstrukturen neuzuberechnen. Dazu wird angenommen daß die dynamische Lastverteilung ein gegenüber den Zeitschritten des numerischen Verfahrens sporadisch auftretendes Ereignis in der Simulation ist (vgl. Kap. 6.2), was für die lokale Gitterweitenanpassung allerdings nicht zutrifft, weil das Gitter in jedem Zeitschritt an die berechnete Lösung angepaßt werden soll. 4.4. IDENTIFIKATION 93 Insofern muß für die Darstellung der Identifikationsrelationen ein Konzept gefunden werden, das von den lokalen Veränderungen in der Verfeinerungsstruktur unabhängig ist und in seiner Effizienz nicht von der Häufigkeit der Verfeinerungs- bzw. Vergröberungsvorgänge abhängt. Implizite Identifikation der Hierarchie Der verwendete Ansatz nutzt die Navigationspfade, die innerhalb des Gitters durch den Verfeinerungsvorgang entstehen (vgl. Kap. 3.2.5) zur impliziten Darstellung der Identifikationsrelationen und erzeugt auf diese Art überhaupt keinen Mehraufwand gegenüber dem seriellen Verfahren mit nur einem Gitter, d.h. es findet nach oder während der Verfeinerung bzw. Vergröberung des Gitters keinen Änderung der Datenstrukturen Ö und × statt. Dies wird erreicht, indem die Datenstrukturen Ö und × nur zur Speicherung der Identifikationsrelationen auf dem Grobgitter verwendet werden, die Ite- ï ò êë î êë ñ ìë íî ìë ðñ é æ è æ åæ ç æ Abbildung 4.9: Implizite Identifikation durch identische Verfeinerungsgeschichte: Über die Teilgittergrenze hinweg stehen sich identische, global einheitlich ausgerichtete Verfeinerungsbäume gegenüber. Der Verlauf der Iteration in der Flächenhierarchie ist unten dargestellt (vgl. Abb. 4.9). Das Gesamtverfahren verwendet Schlüssel zur Identifikation der Grobgitterflächen, -kanten und -knoten zusammen mit den hierarchischen Navigationspfaden. 94 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM ration der Verfeinerungsstruktur hingegen nicht durch eine zusätzliche Liste, sondern durch die bestehenden hierarchischen Navigationspfade vermittelt wird: Durch die globale Ausrichtung der Kanten und Flächen des Grobgitters (vgl. Kap. 3.2.2) werden Bäume mit identischer Verfeinerungsgeschichte auch gleichartig durchlaufen. Für diese implizite Identifikation ist vorausgesetzt, daß jede Verfeinerung auf allen miteinander identifizierten Objekten gleichmäßig stattfindet (Aufgabe des verteilten Verfeinerungsalgorithmus, vgl. Kap. 4.5). Identische Argumente gelten für die Kantenbäume, die aus Kanten des groben Gitters bzw. aus verfeinerten Flächen entstanden sind, gleichermaßen wie für Knoten die innerhalb von Kanten und Flächen entstanden sind: Die Identifikation wird hier ebenfalls implizit durch die Ausrichtung der Kanten bzw. Flächen des Grobgitters und die Iterationsverfahren geleistet (vgl. Kap. 3.2.5, Abb. 3.13). Im Unterschied zum Basisentwurf können jetzt Flächen, Kanten und Knoten in einem Teilgitter vorkommen, die von keinem Element dort referenziert werden. In der Abbildung enthält das Gitter rechts die feinen Flächen, obwohl die Elemente dort nicht so weit verfeinert sind, bzw. dort kein Element gefunden wird, von dem aus eine Navigation zu den feinen Flächen möglich ist. Zusammenfassung: Die Strategie zur Identifikation, die im parallelen Simulationsprogramm realisiert ist, verwendet unterschiedliche Ansätz für das Grobgitter und die hierarchische Struktur, die durch die lokale Gitterweitenanpassung entstanden ist: © Zur Identifikation der Flächen, Kanten und Knoten des Grobgitters werden Schlüssel eingesetzt, damit keine Einschränkungen an die Topologie des Grobgitters durch die Parallelverarbeitung entstehen. © Da die Verfeinerungsregeln schon zur Zeit der Programmentwicklung bekannt sind, können die hierarchischen Navigationspfade verwendet werden, um die Identifikationsrelationen zu implementieren. Die Vorteile dieser Strategie sind offensichtlich: Die Topologie des Grobgitters, die in der Regel durch den verwendeten Gittergenerator vorgegeben wird und für praktische Anwendungen sehr kompliziert sein kann, unterliegt keinen Einschränkungen, das Grobgitter bleibt auch im parallelen Programm ein unstrukturiertes Gitter. Durch Ausnutzung der hierarchischen Navigationswege findet die Neuberechnung der Datenstrukturen, die zur Darstellung der Identifikationsrelationen dienen, nur nach einer dynamischen Lastverteilung statt, jedoch nicht nach einer Gitterweitenanpassung. Auf diese Art wird die Effizienz der Gitterweitenanpassung durch die im parallelen Programm notwendige Identifikation der Teilgitter nicht betroffen. ª 4.5. LOKALE GITTERWEITENANPASSUNG 95 4.5 Lokale Gitterweitenanpassung Auch für die Algorithmen zur Gitterweitenanpassung soll versucht werden, die Ausdehnung in das parallele Gitterkonzept hinein ohne massive Eingriffe in den bestehenden seriellen Entwurf vorzunehmen. Weil die verteilte Gitterverwaltung auf getrennten, aber in ihrem Charakter zum Basisentwurf identischen Teilgittern basiert, darf in jedem Teilgitter verfeinert bzw. vergröbert werden, ohne daß dadurch dessen Integrität gefährdet ist. Natürlich ist nicht zu erwarteten, daß die Strukturen zur Identifikation (vgl. Kap. 4.4.5), die das verteilte Gitter über die lokalen Teilgitter hinaus enthält, nach einem solchen unkoordinierten Vorgehen noch korrekt sind. Dies kann aber erreicht werden, falls der verteilte Algorithmus zwei Bedingungen genügt: 1. Die lokalen Verfeinerungs- und Vergröberungsvorgänge auf den Teilgittern müssen so ablaufen, daß die Balancierungsbedingung auch über die Teilgittergrenzen hinweg eingehalten wird (vgl. Kap. 3.5.1). 2. Die Verfeinerungssituation auf identifizierten Objekten, also auf den Flächen und Kanten am Teilgitterrand muß nach Abschluß des Algorithmus identisch sein (vgl. Kap. 4.4.5). Damit liegt die Idee nahe, die Methoden zur Gitterweitenanpassung, die aus dem Basisentwurf stammen, innerhalb der vergleichbaren Methoden für das verteilte Gitter unverändert anzuwenden, wobei die zusätzlichen Forderungen durch geschickt gewählte Schritte zur Vorbereitung bzw. zum Abschluß der Verfeinerung erfüllt werden. 4.5.1 Verfeinerung Der verteilte Verfeinerungsalgorithmus läßt sich im vorliegenden Fall, also für ausschließlich isotrope Verfeinerungsregeln auf Element und Fläche, einfach aus dem sequentiellen Verfeinerungskonzept entwickeln. Weil die Methode balancieren (r:Regel) für die verwendeten isotropen Regeln das Gitter immer so verändert, daß die Balancierungsbedingung erfüllt bleibt (vgl. Abb. 3.23), wird die Verfeinerung eines Elements nie durch seine Nachbarn blockiert. Der verteilte Verfeinerungsalgorithmus kann in deshalb vier Phasen zerlegt werden (vgl. Abb. 4.10), wobei die zweite Phase den sequentiellen Verfeinerungsschritt auf einem Teilgitter enthält: I Vorbereitungsphase: Die implizit vorliegende Identifikationsrelation für die Flächen und Kanten wird auf jedem Teilgitter in einer geeigneten Datenstruktur gesichert, weil die miteinander identifizierten Teilbäume vorübergehend eine unterschiedliche Verfeinerungssituation aufweisen können (vgl. Kap. 4.4.5). Diese Datenstrukturen werden in den Schritten (3) und (P) benötigt. 96 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM 1+2 Serieller Verfeinerungsschritt: Alle Teilgitter werden nach Maßgabe der Verfeinerungsanforderung verfeinert und erfüllen nur noch lokal die Balancierungsbedingung, d.h. diese kann über die Teilgittergrenzen hinweg teilweise verletzt sein (vgl. Kap. 3.5.1). 3 Iterative Balancierungsphase: Anschließend werden über die Flächen die Verfeinerungsregeln zwischen den Teilgittern ausgetauscht und weitere Elemente verfeinert um die Balancierungsbedingung wieder herzustellen. Dieser Schritt muß iteriert werden, bis keine Elemente mehr verfeinert werden (globales Abbruchkriterium). P Ausgleichsschritt: Abschließend werden die identifizierten Kantenbäume hinsichtlich ihrer Verfeinerung abgeglichen. Dies benötigt nur einen Schritt, weil die Verfeinerung einer Kante keine in der Dimension aufsteigende Rückwirkung auf Flächen oder Elemente hat. Entscheidend für die Arbeitsweise des parallelen Verfeinerungsalgorithmus ist, daß jedes Element, jede Fläche und jede Kante in einem Verfeinerungsschritt höchstens einmal geteilt wird. óô õ ô ö ô Abbildung 4.10: Ablauf der Verfeinerung im verteilten Gitter: Das rot eingezeichnete Element im linken Teilgitter soll verfeinert werden. Die Verfeinerung geht durch die Fläche auf das benachbarte Teilgitter über und erzwingt dort die Verfeinerung eines Elements, damit die Balancierungsbedingung erfüllt bleibt. 4.5. LOKALE GITTERWEITENANPASSUNG 97 Die iterative Balancierungsphase (3) ist der von der Laufzeit gesehen der aufwendigste Teil des verteilten Verfeinerungsalgorithmus, denn nach jedem Schritt muß für alle Teilgitter mittels globaler Kommunikationsvorgänge geprüft werden, ob dort weitere Elemente (am Rand) verfeinert worden sind und deshalb ein weiterer Balancierungsschritt erforderlich ist (vgl. Kap. 6.1.4). Der verteilte Verfeinerungsalgorithmus erzeugt bei gleicher Markierung eine zum sequentiellen Algorithmus identische Verfeinerungssituation. 4.5.2 Vergröberung Um den Vergröberungsalgorithmus des Basisentwurfs (vgl. Kap. 3.5.3) in das parallele Konzept übernehmen zu können, muß ein zusätzliches Problem beherrscht werden, denn die Teilgitter enthalten Flächen und Kanten, die keine niederdimensionalen Bestandteile der Elemente bzw. Flächen des Teilgitters sind, und daher auch nicht durch die Zählung von Referenzen aus dem Teilgitter vor der Löschung bewahrt werden (vgl. Abb. 4.9). Weil die Datenstrukturen des Basisentwurfs nur Eigenschaften des seriellen Gitters beschreiben sollen, wird darauf verzichtet, die Referenzenzähler einfach von außen auf den globalen Wert (also die Summe aller Zähler auf dem Verbindungsstern) einzustellen. Ein vernünftigerer Ansatz besteht darin, im Basisentwurf bereits eine Möglichkeit zum Unterbinden der Vergröberung vorzusehen, ohne dort davon Gebrauch zu machen. Zusammen mit dieser Möglichkeit kann der verteilte Algorithmus zur Vergröberung ebenfalls durch Hinzufügen einiger Schritte zum seriellen Algorithmus des Basisentwurfs formuliert werden: I Vorbereitungsphase: Alle Flächen und Kanten des Gitters, die potentiell vergröbert werden können und in meherern Teilgittern vorkommen, sind gegen die Vergröberung zu sperren (vgl. Kap. 3.5.3), wozu ein geeigneter Mechanismus vorzusehen ist. S Serieller Vergröberungsschritt: Der verteilte Algorithmus zur Vergröberung ruft hier die entsprechende seriellen Methode des Teilgitters auf, um die möglichen Vergröberungen vorzunehmen. P Abschlußschritt: Die in Schritt (I) gegen eine Vergröberung gesperrten Flächen und Kanten werden jetzt (in dieser Reihenfolge) daraufhin untersucht, ob eine Vergröberung stattfinden kann. Dazu sind die Referenzenzähler über die Teilgittergrenzen hinweg zu vergleichen. Falls in einem Teilgitter eine Referenz gefunden wurde, darf das Objekt nirgends gelöscht werden. Die durch den sequentiellen bzw. den verteilten Algorithmus zur Vergröberung erzeugten Gitter sind bei gleicher Anforderung und gleichem Ausgangsgitter nicht unbedingt gleich. Dies ist auch nicht zu erwarten, denn das Resultat der 98 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM Anwendung des Vergröberungsalgorithmus aus dem Basisentwurf hängt nicht nur von den gesetzten Markierungen und dem aktuellen Verfeinerungszustand ab, sondern offenbar auch von der Reihenfolge, in der die vergröberungsfähigen Knoten in der Elementhierarchie besucht werden. 4.6 Dynamische Lastverteilung Im letzten Abschnitt dieses Kapitels kann nun die Komponente für die dynamische Lastverteilung während der parallelen Simulation vorgestellt werden. Wie in der Einleitung zu diesem Kapitel (vgl. Abb. 4.1) ausgeführt ist, sollen alle Strukturen des verteilten Programms, die nicht integrale Bestandteile der dynamischen Lastverteilung sind, davon unabhängig formuliert werden, wobei darauf zu achten ist, daß der Funktionsinhalt letztlich auch zur dynamischen Umverteilung des Gitters verwendet werden kann. Das Modul zur Umverteilung des Gitters reagiert auf jede Änderung der Verfeinerungsstruktur des Gitters (vgl. Kap. 5.5) und besteht aus zwei Komponenten: Eine Datenbasis wird lokal auf allen Teilgittern erstellt. Darin sind alle Informationen enthalten, die benötigt werden zu bewerten, ob und gegebenenfalls wie eine Neuaufteilung des Grobgitters vorzunehmen ist. óô õ ô ö ô Abbildung 4.11: Ablauf der Vergröberung im verteilten Gitter: Die rot eingezeichneten Elemente im linken Teilgitter sollen zusammengefaßt werden. 4.6. DYNAMISCHE LASTVERTEILUNG 99 Falls eine Umverteilung vorzunehmen ist, berechnet diese Komponente anhand der vorliegenden Daten eine neue Zuordnung aller Grobgitterzellen auf die Teilgitter (Prozessorzuweisung, vgl. Kap. 2.1.3). Die zweite Komponente realisiert den Transfer der zu verschiebenden Gitterteile und zwar für jede mögliche Zuordnung, die Funktionsweise der Algorithmen zum Transfer des Gitters bedingt also keine Einschränkung an die Methodik zur Berechnung der Neuverteilung. 4.6.1 Berechnung der Aufteilung des Grobgitters Aufwandsmodell für das numerische Verfahren Das Aufwandsmodell soll eine einfach zu berechnende Beziehung zwischen dem Verfeinerungszustand des Gitters zu einem Zeitpunkt der Simulation und dem Aufwand des Gesamtverfahrens im nachfolgenden Zeitschritt liefern. Anhand des Aufwandsmodells soll es darüberhinaus möglich sein, die voraussichtliche Dauer (Laufzeit) der nachfolgenden Zeitschritte des numerischen Verfahrens und der lokalen Gitterweitenanpassung auch für eine angenommene andere Aufteilung des Gitters abschätzen zu können, um dadurch Kosten oder Gewinn einer dynamischen Lastverteilung zu erkennen. Annahme: Der Aufwand, der im numerischen Verfahren auf allen Flächen und Elementen entsteht, die durch die hierarchischen Navigationswege ausgehend von der selben Grobgitterzelle (Agglomerationseinheit) erreicht werden können, wird als proportional zur Anzahl der Blätter in der Elementhierarchie, die von dieser Grobgitterzelle erreicht werden können, angesehen (vgl. Abb. 3.13). Das vorgeschlagene Aufwandsmodell unterscheidet nicht zwischen flächenund elementbasierten Teilen des numerischen Verfahrens was innerhalb gewisser Grenzen zulässig ist, wie die folgende Abschätzung zeigt: Behauptung: Für das beschriebene nichtkonforme Hexaedernetz und die zugrunde gelegten Verfeinerungsregeln (vgl. Kap. 3.2) kann die Anzahl der 2 2 2 ÷2 feinsten inneren Flächen bzw. Kanten (Blätter der Hierarchie), die in und an einem Grobgitterelement liegen, für eine große Verfeinerungstiefe durch die 2 ø~2 Anzahl der Blätter der Elementhierarchie mit passenden Konstanten nach oben und unten abgeschätzt werden. Eine ähnliche Abschätzung gilt auch für 2 2 die Anzahl der Knoten " : ù ù r r 2 ø~2ú 2 2ûú 2 ø~2ú 2 ÷2ýúaþ 2 ø~2ú 2 " 2ÿú ù ü ¨ 2 ø~2 2 ø]2 r r 2 ø~2 ¦ ù < r Nü r 2 ø~2 < ü 2 ø~2 (4.2) 100 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM 2 2 32 ø~2 Beweis: Betrachtet man zunächst das Verhältnis von Flächen und Elementen im Gitter, dann fällt auf, daß jede Fläche von einem oder von zwei Elementen referenziert werden kann - entsprechend der lokalen Verfeinerungssituation. Die kleinste Anzahl an Flächen erhält man, falls möglichst jede Fläche von zwei Elementen referenziert wird. Dies entspricht einer gleichmäßigen Verfeinerung, alle Blätter der Elementhierarchie sind vom gleichen Verfeinerungsniveau (Breitenwachstum). Wird die Betrachtung nun auf die an einem Grobgitterelement anliegenden Flächenbäume und die Flächen- sowie Elementbäume innerhalb dieses Elements eingeschränkt (vgl. Abb. 3.13, 3.14) gelangt man auf folgende Gleichung für die 2 ø]2 2 2 Entwicklung der Anzahl an Elementen und Flächen nach einer weiteren globalen Verfeinerung [GV [àn N : 2 ø~2 2 ø~2 l + N 2 2 þ l + 2 2 &5'!) + &5'!) ¦ + Für Folge der Quotienten gilt offenbar ¥ l 2 2 r ø ¥ 2 ø~2 r & & n ¥ r (4.3) 2 ø~2 & @ ù þ N ¥|n (4.4) Mit elementaren Überlegungen findet man, daß eine allgemeine iterierte Abbil mit einem Startwert &%(' +*-) , auf dung der Form "! für $# eine monoton fallende Folge mit Grenzwert .0/21 6 43 5 7 ! führt, woraus zusammen mit (4.4) das Verhältnis der Flächen- und Elementzahl nach vielen Verfeinerungsschritten zu 2. /21 43 5 89 ø 9 7 ù (4.5) bestimmt werden kann. Ebenfalls anhand der Skizze (vgl. Abb. 3.14) können ÷: und Knoten die zu (4.3) analogen Vorschriften für die Anzahl der Kanten ;$ nach jedem weiteren Verfeinerungsschritt erstellt werden: ÷: % ; % ÷: ;$ < 4? ; ÷: = > ÷: þ ø ø Mit (4.5) folgen durch sukzessives Auflösen die unteren Abschätzungen (linke Seite) der Behauptung (4.2). Um die oberen Abschätzungen nachzuprüfen, wird eine Situation konstruiert, in der jede Fläche nur von genau einem Element referenziert wird. Dadurch 4.6. DYNAMISCHE LASTVERTEILUNG 101 entsteht pro Element die maximal mögliche Anzahl von Flächen. Eine solche Verfeinerungsstruktur liegt beispielsweise vor, falls der Elementbaum in jedem Schritt immer nur an einem seiner bereits am weitesten verfeinerten Blätter fortgesetzt wird (Tiefenwachstum). @ Wiederum zeigt die Skizze (vgl. Abb. 3.14), wie sich teren Verfeinerung entwickeln: @ %A % FE @ @ < BDC 7 E HGI=J G und mit jeder wei- DK4L (4.6) Die Gleichung für die Anzahl der Elemente ist klar, an der Stelle des groben Hexaederelements entstehen acht neue: Die Gesamtzahl nimmt um sieben zu. Die Situation bei den Flächen ist ähnlich: Alle sechs Außenflächen des groben Hexaeders werden durch insgesamt 24 feine Flächen ersetzt, im Element ent @ stehen nochmals zwölf feine Flächen (vgl. Abb. 3.13). und entwickeln sich proportional zur Tiefe der Verfeinerung. Für den Grenzwert findet man @ 0. /21 43 5 K4L C und damit die obere Abschätzung der ersten Gleichung aus (4.2). Abzählen liefert ebenso die zu (4.6) korrespondierenden Ausdrücke für die Anzahl an M" ; Kanten und Knoten nach jedem weiteren Verfeinerungsschritt M: % G ; %S UT M: ; M" N ;$ V 7H GODG=PHGI=J EQ ;$ GP E V M: W >=RG Daraus folgen die übrigen oberen Abschätzungen aus (4.2). X Das vorgeschlagene Aufwandsmodell macht lediglich von den Abschätzungen für die Anzahl der Flächen im Gitter Gebrauch, weil dort der Aufwand zur Berechnung der numerischen Flüsse lokalisiert ist. Obwohl die Anzahl der feinsten Flächen im Gitter auch in jedem Schritt der Verfeinerung durch eine direkte Zählung bestimmt werden kann, bietet die Abschätzung (4.2) in der Praxis den Vorteil eines deutlich geringeren Aufwands. Die Abschätzung liefert die Anzahl der Flächen aus der bekannten Anzahl der Elemente innerhalb eines Bereichs von Y 18 %, was sich im vorliegenden Fall als ausreichend genau erweist (vgl. Kap. 6). Modellgraph für den Aufwand im numerischen Verfahren Da die Verteilung des Gitters in Einheiten von Grobgitterzellen und deren Inhalt an feinen Elementen, Flächen Kanten und Knoten erfolgen soll (Agglomeration, vgl. Kap. 4.1.1), besteht die Aufgabe darin, das Grobgitter so an die zur Verfügung stehenden Prozessoren zuzuweisen, daß deren Belastung im numerischen Verfahren nahezu gleich ist (Prozessorzuweisung, vgl. Kap. 4.1.1). 102 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM Durch das einfache Aufwandsmodell (4.2) wird die Frage der Lastbewertung beantwortet: Der Aufwand im numerischen Verfahren wird als proportional zur Anzahl der Blätter in der Elementhierarchie angenommen, womit im Kriterium zur Steuerung der dynamischen Lastverteilung (2.12) die anteilige Laufzeit Z ,[\[^] _ , bei ausreichender Genauigkeit durch die bekannte anteilige Elementzahl @ _ ersetzt werden kann: 16`acbed ]0fgihkjl 7 bnm 7"po b 7:qoro @tsu @ _v d^w [\[xhyj @$ z{ 2 (4.7) Weiterhin soll die Aufteilung des Grobgitters den zusätzlichen Aufwand, der aus Identifikation, verteilter Gitterweitenanpassung und Datentransfer im numerischen Verfahren besteht, möglichst klein halten. Dieser Aufwand wird üblicherweise mit der Zahl der Schnittflächen“ im verteil” ten Gitter verbunden. Für die vorliegende Problemstellung ist dieses Vorgehen sogar exakt: | | Auf den Flächen des Gitters, die zum inneren Rand gehören, die also Bestandteil mehrerer Teilgitter sind, wird der Fluß aufgrund des mehrfachen Vorkommens der Fläche zweimal berechnet (vgl. Kap. 4.3). | Auf den Randelementen, die den inneren Rand gegenüber den mehrdeutigen Flächen darstellen, müssen die Interpolationsobjekte in jedem Zeitschritt zwischen den Teilgittern ausgetauscht werden, woraus ein bestimmter Kommunikationsaufwand resultiert. Der Aufwand des Identifikationsalgorithmus (vgl. Kap. 4.4.4) ist ebenfalls proportional zur Anzahl der Flächen, Kanten und Knoten, die in mehreren Teilgittern vorkommen. Mit diesen Aufwandsbetrachtungen kann das Problem der Prozessorzuweisung in ein Partitionierungsproblem für einen ungerichteten gewichteten Graphen umformuliert werden (vgl. Abb. 4.12). Definition: Es seien } , ~ 9 b } o nichtleere Mengen mit }$~u U und p H "} mit v v Gt l wobei die Kardinalität der Menge angibt. Zusammen mit den Abbildunb 9 b o o gen Qi~ } , ~ und }F heißt }lr~6ly-lyl ein ungeb o richteter gewichteter Graph bzw. }lr~6lrlr . Dabei bezeichnet } die Menge der Ecken des Graphen und ~ die Menge der Kanten von . Um die bislang noch unscharf umschriebenen Ziele der Prozessorzuweisung in ein berechenbares Kostenfunktional umwandeln zu können, wird zunächst aus den bekannten Größen des hierarchischen Gitters und der Topologie des unterliegenden Grobgitters nach den folgenden Vorschriften ein Graph erstellt: 4.6. DYNAMISCHE LASTVERTEILUNG ω=13 θ=29 103 Jede Fläche des Grobgitters, die auf einem inneren Rand des Teilgitters liegt, wird durch eine Kante VB~ im Graphen dargestellt, deren Geb o wicht aus der Anzahl der feinsten Flächen im Baum über dieser Grobgitterfläche mit einem passenden Faktor bestimmt wird. Jedes Element des Grobgitters wird durch eine Ecke } im Graphen b o repräsentiert, deren Gewicht aus der Anzahl der feinsten Elemente @ im Baum über diesem Grobgitterelement bestimmt wird. Das im folgenden Abschnitt beschriebene Graphenabbildungsproblem bzw. das einfachere Graphenpartitionierungsproblem sind zusammen mit diesem Modell die geeignete Beschreibung des Problems der optimalen Verteilung der Grobgittereinheiten auf die zur Verfügung stehenden Prozessoren. Das Graphenpartitionierungsproblem Mit der Darstellung des Grobgitters als Graph liegt ein Modell vor, das den Operationsinhalt und die Datenzusammenhänge in einer Form zusammenfaßt, für die sich die Frage einer optimalen Aufteilung des Gitters, die einerseits eine gleichmäßige Belastung der Prozessoren erzeugt und andererseits möglichst θ=15 ω=7 ω=7 θ=29 θ=8 ω=4 ω=13 θ=15 Abbildung 4.12: Darstellung des Berechnungs- und Kommunikationsaufwands für ein Gitter durch einen gewichteten Graphen. Die vier Grobgitterelemente erhalten als Gewichte die Anzahl der enthaltenen feinen Elemente, die Flächen jene der enthaltenen feinen Flächen. 104 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM wenige Navigationspfade unterbricht, durch das abstrakte Graphenpartitionierungsproblem ausdrücken läßt: b o Definition: Für einen ungerichteten gewichteten Graphen }lr~6lyl löst 7¡ die Abbildung :R}B L l 02 l das Graphenpartitionierungsproblem, falls sie das Kostenfunktional ¢ £^¤¦¥ h¨§ hk©«ª­¬4®A¯­h¨§ hk©e¬4° b o ±7V²x³ ¥ ³ ¥ hyª­§ hk©2ªy´ (4.8) unter der Nebenbedingung µ z{ L l 02 l 7" ¶· ¢ ¸ h¨¬4°c¹ ³ ¥ hkª ¤ _«º b o7 ¢ b o¼ ½ p » ¾ hk© ¬4° v 16`a b o h\¬4° (4.9) minimiert. Wird mit der Modellgraph aus dem vorigen Abschnitt identifiziert, dann minimiert die Lösung des Graphenabbildungsproblems den Aufwand, der durch die Datenzugriffe über Prozessorgrenzen hinweg entsteht (4.8), bei gleichzeitiger ausgeglichener Verteilung des Aufwands im numerischen Verfahren (4.9). Für das Graphenpartitionierungsproblem (4.8) und (4.9) läßt sich im allgemeinen, d.h. für allgemeines , kein Algorithmus angegeben, der mit polynomialem Zeitaufwand eine Lösung berechnet. Der Aufwand einer vollständigen Suche nimmt oft exponentiell mit der Größe }¿ des Graphen zu [13]. Da das Problem aber in der Informatik und in der Nachrichtentechnik häufig auftritt, stehen effiziente Verfahren zur Approximation der optimalen Lösung oder zur Verbesserung einer bestehenden Graphenpartitionierung zur Verfügung [19, 30]. Graphenpartitionierung und dynamische Lastverteilung Die Zerlegung eines Graphen im Sinne von (4.8) und (4.9) stellt ein diskretes Optimierungsproblem dar, weshalb nicht erwartet werden darf, daß die Lösung, die ein entsprechendes Verfahren liefert, stetig von Eingangsgrößen wie einzelnen Ecken- oder Kantengewichten des Graphen abhängt. Ein weiteres Problem besteht darin, daß selbst die optimale Lösung des Graphenpartitionierungsproblems (4.8) und (4.9) noch mehrdeutig ist: Es bleibt die Freiheit einer Permutation der Teilgebiete. In der Praxis zeigt sich häufig, daß die erneute Anwendung des identischen Partitionierungsalgorithmus auf ein Problem mit leicht modifizierten Ecken- oder Kantengewichten lediglich einige Ecken zwischen den Partitionen verschiebt, darüberhinaus aber noch zu einer globalen Permutation der Partitionsnummern führt. Ausgehend von dieser Beobachtung wird vermutet, daß es in vielen Fällen ei7¡ 7" Á à und die ne Permutation ÀB L l 02 l L l 22 le gibt, für die gilt: À"ÂU 4.6. DYNAMISCHE LASTVERTEILUNG 105 nachfolgende Anwendung von À auf die vom verwendeten Partitionierungsalgorithmus bestimmte Zuweisung zu den Teilgebieten reduziert den Aufwand beim Transfer der zu verschiebenden Teilgitter. b o Im folgenden ist  }l~6lylr ein Modellgraph für ein Gitter bestehend aus einer Menge von Ecken } und einer Menge ungerichteter Kanten ~ . Die Ecken } sind fortlaufend numeriert von p% bis ¹ °Ä¹ *i . Außerdem sind für alle b o b o Ecken des Graphen Gewichte Å _ unabhängig von _ vorgesehen, wobei b _o die einzelnen Werte Å später festgelegt werden. Definition: Neupartitionierung des Graphen bedeutet den Übergang von 7 einer Abbildung £ }ÆÇ L l 22 le auf eine neue (nachfolgende) Abbildung " 7 + £ È t} L l 02 lÉ , wobei die Anzahl der Partitionen im Schritt und É diejenige im Schritt ist. Dabei stellt sich die Frage nach den Kosten des nachfolgenden Lasttransfers, in dessen Verlauf Teile des Gitters mit assoziierten Daten zwischen den Prozessen ausgetauscht werden müssen. Aufwandsmodell für den Gittertransfer Für die Elemente des Grobgitters ist die Frage, was transportiert werden muß, durch die beiden Partitionierungsabbildungen £ und £+È beantwortet, bei der Betrachtung der Flächen, Kanten und Knoten müssen aber bereits existierende Kopien in den Zielgittern berücksichtigt werden (vgl. Kap. 4.2). Mit den Abschätzungen (4.2) werden hier vereinfachend nur die Elementbewegungen berücksichtigt, im Modell des Graphen verursacht also nur die Verschiebung einer Ecke zu einer anderen Partition einen feststellbaren Aufwand. Weiterhin sei die Anzahl der Partitionen vor und nach der Neuaufteilung identisch Â É . { Definition: Die Überdeckung Ê _ÌË der Partitionen (Teilgraphen) und Í bezüglich des Übergangs von £ auf £+È wird definiert als die Summe der b o b o b o Eckengewichte Å der zu verschiebenden Ecken pÎ$}V £  Á £+È : b o Ê _Ë £ Ï £+È Â ¢ Å I ³ Ó ¸ hЬ°ÒÑ ¥ hkª ¤ _ § ³IÓrÔtÕ ¥ hyª ¤ Ë\º b o (4.10) Damit kann nun ein zunächst rein formales Kostenfunktional für den Lasttransfer konstruiert werden: Definition: Kostenfunktional für den Gittertransfer. d^Ö×ØÙb £ o £+È Â Ú ¢ ÛÝÜ Þß&àrá á âxã Ûpå ä Þ b o £+È Õ Ê _ÌË £ Ï (4.11) Damit das Kostenfunktional den Aufwand des Gittertransfers richtig beschreibt, b o müssen noch die Gewichte Å _ der Ecken im Modellgraphen entsprechend 106 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM angepaßt werden (vgl. Kap. 5.6). Ziel müßte es nun sein, dieses Kostenfunktional zum statischen Partitionierungsproblem hinzuzufügen und dadurch gleichzeitig die Dauer des Lasttransfers und der Kommunikation im numerischen Verfahren zu reduzieren. Das kann hier nicht erreicht werden, denn die Algorithmen zur statischen Graphenzerlegung stammen aus Bibliotheken und können nicht geändert werden. Es bleibt aber noch die angesprochene Möglichkeit, die Symmetrie des Partitionierungsergebnisses unter Permutation der Gebietsnummern zum Zweck der Verbesserung des Partitionierungsergebnisses auszunutzen. Ziel: Unter allen möglichen Permutationen ÀæÏçSlèÀéêë<ê der Index7F menge ê  L l 22 le ist diejenige zu finden, die das folgende modifizierte Kostenfunktional minimiert: d^Ö×ØÙb ¢ o £ Ú £+È 4ì¨À  ÛíÜ Þ4ß&àyá á â^ã Ûå ä î^ï Þeð {­ó b o Õ Ê _+ñ ¥ Ë ª £ Ï £+È Ïò (4.12) Der Raum, in dem die Lösung zu suchen ist, umfaßt alle ô möglichen Permutationen der Indexmenge. Die vollständige Suche kann daher selbst für eine moderate Zahl von Teilgebieten sehr aufwendig werden. Deshalb wird die exakte Lösung des Optimierungsproblems vermieden und auf die folgende, einfache Heuristik ausgewichen: Algorithmus 4.3: Konstruktion einer Permutation À Ö Ø zur Reduktion des Aufwands im Gittertransfer. £ 9 ê +§ "ê  % 9 ê +§  ê ,  solange finde setze setze  L l 20 l 7" z  L l 20 l 7" L $#$ Ó Ó { Õ l­ÍõöÊ Ì_ Ë Â ò R÷ Ý] ¬4ø § ùS¬4ø ú Ê¿] £ b{ o  À Ö Ø Í 9 £+È £+È { Â ê £  ê und ê û ê 9£ û +Í ü Bemerkung: Der angegebene Algorithmus kann offenbar mit einem Aufwand, der linear mit der Anzahl der Teilgebiete zunimmt, implementiert werden. ý 4.6.2 Umverteilung des Gitters Der verteilte Entwurf des parallelen Verfahrens bedingt, daß Teile des Gitters immer wieder von Partition zu Partition bewegt werden, um eine möglichst gleichmäßige Belastung der einzelnen Prozesse zu erreichen. 4.6. DYNAMISCHE LASTVERTEILUNG 107 Die beschriebene Strategie, eine Umverteilung nur auf dem Niveau des Grobgitters vorzunehmen (vgl. Kap. 4.1.1), wirkt sich günstig auf den Entwurf des Moduls zum Gittertransfer aus, er kann geradlinig aus den Komponenten der seriellen Gitterverwaltung weitergeführt werden. Dies ist vor allem deshalb günstig weil die Komponente zur Umverteilung des Gitters erfahrungsgemäß wohl die am schwierigsten zu realisierende sein dürfte. Die Gründe dafür sind im wesentlichen, daß (scheinbar) kein Gegenstück dazu im Entwurf für das sequentielle Simulationsprogramm vorliegt und die Lastverteilung dennoch massive Eingriffe in den grundlegenden Datenbestand des Gitters vornehmen soll. Das ist erfreulicherweise nur scheinbar der Fall: Genau wie die lokale Gitterweitenanpassung hat auch die dynamische Lastverteilung ihre Grundlagen im seriellen Entwurf, zumindest an den Stellen, an denen sie das Gitter direkt manipulieren muß. Es handelt sich dabei um das Modul zum Aufbau des Grobgitters (vgl. Kap. 3.2.6, 5.2) und die Methoden zur Sicherung und Wiederherstellung des hierarchischen Gitterzustands (Verfeinerungssituation) aus entsprechenden Dateien bzw. Datenströmen (vgl. Kap. 3.13, 5.2). Verteiltes Gitter (Interface) 1 1 1 Verteiltes Grobgitter Grobgitter (Project) Instantiierung Konkretes verteiltes Gitter (Director) Konkretes Verteiltes Grobgitter (Factory) mg : Konkretes Verteiltes Grobgitter & Erbauer (Builder) Instantiierung 0...N Instantiierung 1 0...N 0...N HexaederGeometriesockel ParallelErweiterungIF ParallelErweiterungIF restore(Datenstrom (Datenstrom&) &) restore Erbauer für Teilgitter 1 Konkretes KonkretesHexaederelement Hexaederelement außen : Map < 4−PolygonRand * > innen : Map < 4−PolygonRand * > 1 KonkreteParallelerweiterung Parallelerweiterung** ee: :Konkrete Instantiierung hexaederEinfügen (Datenstrom &) 4−PolygonEinfügen (Datenstrom &) kanteEinfügen (Datenstrom &) knotenEinfügen (Datenstrom &) 1 KonkreteParallelerweiterung Parallelerweiterung Konkrete KonkretesHexaederelement hh: :KonkretesHexaederelement restore(Datenstrom (Datenstrom&) &) restore Abbildung 4.13: Ausdehnung der Builder-Klasse für das Grobgitter aus dem Basisentwurf durch Vererbung. Das Schema des Zusammenwirkens der drei Module beim Aufbau des Grobgitters bleibt unverändert erhalten (vgl. Abb. 3.15). 108 KAPITEL 4. DAS PARALLELE SIMULATIONSPROGRAMM Der objektorientierte Ansatz bleibt auch im Fall der dynamischen Lastverteilung erhalten, d.h. es wird nicht von außen in die Integrität des Teilgitters eingegriffen. Der Erbauer (Builder) des Grobgitters für ein verteiltes Gitter bietet gegenüber dem konkreten verteilten Gitter die selbe Schnittstelle an, wie sein Äquivalent für das Monogitter im Basisentwurf. Genaugenommen werden die bestehenden Möglichkeiten durch Vererbung übernommen und an einigen Stellen in das verteilte Konzept hinein erweitert (vgl. Abb. 4.13). Das Modul zur dynamischen Umverteilung des Grobgitters kann auf diese Art recht einfach realisiert werden: Die codierten Grobgitterdaten werden wie im Basisentwurf in entsprechende Datenströme geschrieben, die jedoch nicht mit Dateien, sondern mit den Builder-Objekten auf dem Zielgitter verbunden sind. Der einzige Unterschied zum Basisentwurf taucht beim Heraustrennen eines Elements aus dem Gitterverband auf: Falls eine Fläche der Elementberandung auf dem inneren Rand des verteilten Gitters liegt, müssen hier die zugehörigen Randelemente angelegt werden (vgl. Kap. 4.2,4.3). 109 Kapitel 5 Dokumentation zur Implementierung Hinweise zur Darstellung Jeder Abschnitt enthält zusätzlich zu den Erklärungen eine Aufstellung aller Dateien, auf die das betreffende Modul bzw. Paket in der Implementierung verteilt ist. Dies soll zusammen mit dem Index (vgl. Anh. C) eine schnelle Zuordnung der Quelldateien ermöglichen. Dabei macht das Symbol in der ersten Spalte der Tabelle deutlich, welche Teile der Implementierung die betreffenden Datei enthält: .h Deklarationsdateien .h Deklarationspaket .cc Definitionsdateien Die Unterteilung in Deklarations- und Definitionsdateien geht bereits auf Eigenschaften der Programmiersprache C++ [29] ein, wogegen die Paketdefinitionen nicht strikt im Sinne der UML [7] auszulegen sind: Oftmals handelt es sich nur um eine Sammlung inhaltlich zusammengehöriger Klassen, die eventuell in einem eigenen Namensraum enthalten sind. 5.1 Adaptives Gitter Die Darstellung der geometrischen Objekte des Gitters, also der Elemente, Flächen, Kanten und Knoten mit den Mitteln der Programmiersprache C++ folgt 110 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG dem vorgestellten Entwurf (vgl. Kap. 3.2): Die drei Schichten Iterationsschnittstellen, Geometriesockelklassen und Implementierungsschicht finden sich bis auf Details mit technischem Charakter im Programmcode wieder. Zusätzlich enthalten die Iterationsschnittstellen weitere Basisklassen, mit deren Hilfe die Integration des numerischen Verfahrens und die Erweiterung auf ein verteiltes Gitter erreicht werden kann, wobei diejenigen Klassen, die Gegenstand eventueller Ergänzungen sein können, grau dargestellt sind (vgl. Abb. 5.1-5.4). Neben dem Daten- und Funktionsinhalt sind auch die Dateien so gruppiert, daß eine gute Trennung zwischen dem Basispaket, ausreichend für die seriellen (nicht verteilten) Anwendungen, und dem Ergänzungspaket (vgl. Kap. 5.1.2) für die Unterstützung paralleler (verteilter) Anwendungen erreicht wird. 5.1.1 Gitterdatenstrukturen und Basisalgorithmen Aufteilung des Pakets: Datei Kurzbeschreibung gitter sti.h Paket mit den Iterationsschnittstellen für Element, Randelement, Fläche, Kante, Knoten, Grobgitterbehälter und Gitterverwaltung, den Geometriesockelklassen für Hexaeder, 4-Polygon und 4-Polygonrandelement sowie der Konstruktionsschnittstelle des Grobgitterbeh älters (vgl. Kap. 3.3). .cc gitter sti.cc Alle Methodendefinitionen, die auf den Iterationsschnittstellen aufgesetzt werden können: Erzeugung der Baumiteratoren, Backup/Restore, Verfeinerung/Vergröberung. .cc gitter geo.cc Alle Methodendefinitionen, die auf den Geometriesockelklassen aufgebaut werden können: Integritätstest auf den Elementen und die Methoden auf der Konstruktionsschnittstelle des Grobgitters. .h gitter impl.h Klassendefinitionen für leere Gitterteile, wenn keine speziellen Implementierungen benötigt werden. Alle Operationen sind in der Deklarationsdatei definiert (inline), weshalb keine weitere Definitionsdatei vorliegt. .h .cc gitter mgb.h/.cc Konstruktion des Grobgitters (vgl. Kap., 3.2.6): Definition der Konstruktionsobjekte mit assoziativen Behältern, die das Grobgitter aus den Geometriesockelklassen aufbauen können. .h 5.1. ADAPTIVES GITTER .h gitter hexa top.h 111 Schablonenklassen zur Ausprägung von Hexaedern, 4-Polygonrändern, 4-Polygonen und Kanten mit den entsprechenden Verfeinerungsoperationen aus den Implementierungen in gitter impl.h oder aus eigenen Klassen, die sich von den Geometriesockelklassen ableiten. Erweiterungen Die Datenstrukturen sind sehr flexibel und lassen eine Erweiterung des numerischen Algorithmus ohne aufwendige redundante Neucodierung zu. Insbesondere liegt eine sehr einfache Situation vor, falls die vorhandenen Elementtypen (Hexaeder, Vierecksfläche) sowie die isotropen Verfeinerungsregeln beibehalten werden. Zweiteiliges Konzept: Die Datenstruktur der Elemente, Flächen, Randelemente und Kanten zerfällt in zwei Teile, wodurch es zusammen mit dem Typkonzept gelingt, die Konsistenz und Erfüllung der geometrischen Relationen abzusichern und trotzdem flexible Verhältnisse für die Entwicklung zu erzielen. Prinzipiell handelt es sich um eine Sockel-Deckel Konstruktion: Die Geometriesockelklassen in der Datei gitter sti.h (vgl. Kap. 3.3) enthalten sämtliche Voraussetzungen (Methoden) zur Navigation längs der geometrischen Zusammenhänge (vgl. Kap. 3.2). Darüber hinaus besteht ein abstrakter Zugang zu den lokalen Methoden der Gitterweitenanpassung: Es können Markierungen gesetzt und gelesen werden. Auf Gitterobjekten, die keine Blätter der Hierarchie sind, kann auf die inneren Komponenten nach einem festen Prototypen zugegriffen werden (vgl. Kap. 3.2.5). Mit den Schablonenklassen aus der Datei gitter hexa top.h können konkrete Implementierungen der Elemente, Flächen und Kanten erzeugt werden, die alle abstrakten Methoden zur Navigation und Gitterweitenanpassung aus den Geometriesockelklassen ausfüllen. Diese Schablonenklassen stellen die Abschlüsse“ (Deckel) für eine eigene Implementie” rung dar. Die Klassen der geometrischen Gitterobjekte sind also an der Stelle aufgeschnitten, an der die Anforderungen eines numerischen Verfahrens von der Basisklasse (Geometriesockelklasse) bereits vollständig erfüllt sind. Der Nutzen dieser Lösung besteht in einer sehr sicheren und schnellen Vorgehensweise falls neue Klassen für die geometrischen Objekte mit erweiterten Eigenschaften erstellt werden sollen. Im wesentlichen wird man dabei in vier logischen Schritten vorgehen: 112 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG 1. Einrichten der Schnittstellenmethoden in den Iterationsschnittstellen der erweiterten bzw. geänderten geometrischen Gitterbestandteile. Die Iterationsschnittstellen sind nach der Dimension der davon abgeleiteten geometrischen Objekte geordnet (vgl. Kap. 3.3). 2. Realisierung des numerischen Verfahrens mit den in den Geometriesockelklassen enthaltenen Möglichkeiten zur Navigation längs der geometrischen Beziehungen und zum Zugriff auf die Verfeinerungsinformation. Die neu zu schaffenden Klassen werden also zweckmäßigerweise von den Geometriesockelklassen oder bestehenden Implementierungen, die weiterverwendet werden sollen, abgeleitet. Diese Klassen sind jetzt noch abstrakt und können nicht instantiiert werden. 3. Ausprägen der Schablonen aus gitter hexa top.h mit den in Punkt 2 beschriebenen Implementierungen liefert instantiierbare Klassen mit dem gewünschten Verhalten unter Verfeinerungsanforderungen. Die Klasse des Grobgitterbehälters ist abzuleiten, damit die Virtuellen Konstruktoren (factory methods) [12] zur Bereitstellung der Elemente, Flächen, Kanten und Knoten für das Grobgitter überschrieben werden können. 4. Der neu geschaffene Grobgitterbehälter muß in einem abgeleiteten Gitter denjenigen, der vom Basisklassengitter (vgl. gitter impl.h ) verwendet wird, überdecken (vgl. Kap. 3.2.1, Abb. 3.5). Die Klassendiagramme (vgl. Abb. 5.2-5.4) geben einen Überblick über die Schnittstellenhierarchie der geometrischen Objekte und die Navigationsmöglichkeiten entlang der geometrischen Relationen (vgl. Kap. 3.2). Hinweis: Falls zusätzliche Elementtypen wie Tetraeder, Prismen oder Pyramiden in die Implementierung eingefügt werden sollen, muß der Satz der Geometriesockelklassen (gitter sti.h) und Schablonen (gitter hexa top.h) um die entsprechenden Klassen ergänzt werden. Die Erläuterungen dazu gehen jeý doch über den Rahmen dieser Dokumentation hinaus. 5.1. ADAPTIVES GITTER 113 Parallelerweiterung Anwendungsschnittstelle Iterationszugriff 0...N Gitter Knoten level : Int level () : Int punkt () : Real [3] Zugriff auf die Geometrieinformation 2 1..N KnotenGeometrieSockel KanteGeometrieSockel coordinaten : Real [3] punkt () : Real [3] schlüssel () : Int Vertexmplementierung Abbildung 5.1: Klassen- und Schnittstellenhierarchie der Knoten. Die Klasse Vertex ist von den Iterationsmethoden aus sichtbar, die Geometriesockelklasse nur ausgehend von den assoziierten Objekten der Geometriesockelklasse der Kante (vgl. Kap. 3.3, Abb. 3.16). Parallelerweiterung Anwendungsschnittstelle Iterationszugriff 0...N Kante Gitter bool istBlatt () int level () kinderIteration () : Kante* innereKnotenIteration () : Knoten * Zugriff auf die Geometrieinformation 2 KnotenGeometrieSockel 1..N 4 KanteGeometrieSockel 1..N 4−PolygonGeometrieSockel knoten : VertexGeometrieSockel (*) [2] knoten (i : Int) : KnotenGeometrieSockel * kindKante (i : Int) : KanteGeometrieSockel * KanteImplementierung Abbildung 5.2: Klassen- und Schnittstellenhierarchie der Kanten. Eingezeichnet sind die Navigationsmöglichkeiten in Richtung absteigender Dimension, hier also Fläche-Kante-Knoten. 114 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG Parallelerweiterung Anwendungsschnittstelle Iterationszugriff 0...N Fläche Gitter bool istBlatt () int level () kinder () : Fläche * innereKanten () : Kante * innereKnotenIteration () : Knoten * Zugriff auf die Geometrieinformation 4 1..N 6 KanteGeometrieSockel 1,2 4−PolygonGeometrieSockel HexaederGeometrieSockel kanten : KanteGeometrieSockel (*) [4] orientierung : Int [4] kante (i : Int) : KanteGeometrieSockel * knoten (i : Int) : VertexGeometrieSockel * knoten (i : Int,j : Int) : KnotenGeometrieSockel * kindFläche (i : Int) : KanteGeometrieSockel * 4−PolygonImplementierung Abbildung 5.3: Klassen- und Schnittstellenhierarchie der Flächen. Die Navigationsmöglichkeit entlang der geometrischen Nachbarschaftsbeziehung ist in Abb. 5.4 eingetragen. Parallelerweiterung Anwendungsschnittstelle Iterationszugriff 2 4−PolygonVerbinder 2 6 4−PolygonGeometrieSockel 0...N Element Gitter bool istBlatt () int level () kinder () : Element * innereFlächen () : Fläche * innereKanten () : Kante * innereKnoten () : Knoten * verfeinern () 2 HexaederGeometrieSockel außenflächen : 4-PolygonGeometrie * drehung : Int fläche (i : Int) : 4-PolygonGeometrieSockel * knoten (i : Int) : KnotenGeometrieSockel * knoten (i : Int, j: Int) : KnotenGeometrieSockel * kindHexaeder (i : Int) : HexaederGeometrieSockel * HexaederImplementierung Abbildung 5.4: Klassen- und Schnittstellenhierarchie der Elemente. Die Schnittstelle 4-PolygonVerbinder realisiert das geometrische Nachbarschaftskonzept (vgl. Kap. 3.2.3). 5.1. ADAPTIVES GITTER 115 5.1.2 Das verteilte Gitter Die Strategie zur Aufteilung des Gitters auf mehrere Teilgitter folgt dem Entwurf des verteilten Gitters (vgl. Kap. 4.1.1). Um die Quelldateien des Basisentwurfs von den Erweiterungen, die für die verteilte Gitterverwaltung bestehen, zu entkoppeln, sind die Schnittstellen der für das verteilte Gitter ausgerüsteten Elemente, Flächen, Kanten und Randelemente nur über ein Methodenpaar in der Iterationsschnittstelle dieser Typen erreichbar (versteckt). Auf diese Art sind die Schnittstellenklassen der Komponenten des verteilten Gitters in den Deklarationsdateien des Basisentwurfs nur namentlich, nicht jedoch inhaltlich bekannt. Die Gitterobjekte für das verteilte Gitter enthalten eine Komponente (Erweiterung), die für die Realisierung der Methoden, wie sie von der verteilten Gitterverwaltung benötigt werden, mit Daten und einer Referenz auf das umgebende Gitterobjekt ausgestattet ist. Aus praktischen Gründen folgen die Schnittstellenklassen der Erweiterungen für die parallele Gitterverwaltung dem Konzept der fetten Schnittstellen [29]: So findet beispielsweise keine Unterscheidung zwischen Element- und Randelementerweiterung statt. Das relativ strikte Typkonzept aus dem Basisentwurf weicht an dieser Stelle bedauerlicherweise etwas auf. Aufteilung des Pakets: Datei Kurzbeschreibung .h parallel.h Deklaration der Methoden in den Iterationsschnittstellen, die den Zugriff auf die Schnittstellen der (parallelen) Erweiterungen für die Gitterobjekte vermitteln. Auf diese Art bleibt der Methodeninhalt der Erweiterungen für das verteilte Gitter im Basisentwurf unsichtbar. .h gitter pll sti.h Paket mit den Basisklassen und Schnittstellen für das verteilte Gitter (vgl. gitter sti.h). Definition der Schnittstellen der parallelen Erweiterungen, die in den Elementen, Flächen, Kanten bzw. Knoten eingebaut sind. Der Zugriff geschieht indirekt über die Iterationsschnittstellen (gitter sti.h). gitter pll sti.cc Definition aller Methoden, die bereits mit den Schnittstellen der Parallelerweiterungen der Elemente, Flächen, Kanten und Knoten realisiert werden können. Ebenfalls enthalten sind alle auf die Situation eines verteilten Gitters ausgedehnten Basisalgorithmen aus gitter sti.cc und die Methoden zur Konstruktion der geteilten (identifizierten) Iterationsobjekte (vgl. Kap. 4.4.1). .cc 116 .h .cc .cc .h KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG gitter pll impl.h/.cc Klassendefinitionen für die Basisimplementierungen der Erweiterungsobjekte zu den (Grobgitter-) Knoten, Kanten, Flächen, Elemente und Randelemente für das verteilte leere“ Gitter ohne Daten ” und Methoden, die über die Notwendigkeiten der Gitterverwaltung bzw. -darstellung hinausgehen. gitter pll idn.cc Alle Funktionenschablonen und Methoden zur Identifikation des verteilten Grobgitters (vgl. Kap. 4.4). Die Identifikation der Elemente, Flächen, Kanten und Knoten unterscheidet sich nur hinsichtlich ihrer Schlüssellänge und kann daher durch die mehrfache Ausprägung einer Funktionsschablone realisiert werden. gitter hexa top pll.h Schablonen zum Übernehmen von Randelementimplementierungen aus dem seriellen in das verteilte Gitterkonzept (Adapterklassen). Diese Form der Implementierung trägt dem Umstand Rechnung, daß üblicherweise verhältnismäßig viele unterschiedliche Realisierungen von Randelementen, den Bedürfnissen des numerischen Verfahrens folgend, vom sequentiellen in das verteilte Verfahren übernommen werden sollen. Erweiterungen Der Einbau weiterer Methoden (eines numerischen Verfahrens) in die Klassen der Elemente, Flächen, Kanten oder Knoten im verteilten Gitter ist zunächst völlig identisch zum Vorgehen für die Erweiterung der Klassen aus dem Basispaket (vgl. Kap. 5.1.1). Zusätzlich muß den Anforderungen an die neu geschaffenen Elemente, Flächen, Kanten, Knoten oder Randelemente in Bezug auf Datenaustausch und dynamische Lastverteilung Rechnung getragen werden. Dies geschieht durch das Überschreiben einiger Methoden in den parallelen Erweiterungen der betreffenden Gitterobjekte. Darauf kann hier nicht eingegangen werden. 5.2 Sicherung und Wiederherstellung Die Sicherung bzw. Wiederherstellung des Grobgitters sowie des aktuellen Verfeinerungszustands ist nicht nur für den Programmstart/-neustart bedeutend, sondern auch für die dynamische Lastverteilung, die Teile des Gitters zwischen den verschiedenen Prozessen bewegt. 5.2. SICHERUNG UND WIEDERHERSTELLUNG 117 5.2.1 Grobgitter Die Wiederherstellung bzw. Konstruktion des Grobgitters nach dem in einer Datei gesicherten Zustand wird vom Modul zum Auf- und Umbau des Grobgitters übernommen (vgl. Kap. 3.2.6). Dessen sinnvolle Funktionsausdehnung in einem verteilten adaptiven Gitter besteht in der Unterstützung des Transfers der Grobgitterelemente zwischen Teilgittern für die dynamische Lastverteilung (vgl. Kap. 4.6.2). Aufteilung des Pakets: Datei .h .cc .cc Kurzbeschreibung gitter mgb.h/.cc Konstruktion des Grobgitters (vgl. Kap. 3.2.6, 5.1.1). gitter geo.cc Modul zur Sicherung des Grobgitters in eine Datei nach dessen Änderung im Verlauf der dynamischen Lastverteilung. 5.2.2 Verfeinerungsstruktur Die Sicherung und Wiederherstellung (Backup/Restore) der Verfeinerungsstruktur des Gitters geschieht durch die Gitterobjekte selbst, denn dort sind die Verfeinerungsregeln bekannt. Das Vorgehen ist möglichst einfach: Die Verfeinerungsregeln werden für jeden Teilbaum der Kanten-, Flächen- und Elementhierarchie so gespeichert, daß der Teilbaum daraus umgekehrt wieder durch fortgesetzte Verfeinerung neu erzeugt werden kann. Auch die Methoden zur Sicherung- und Wiederherstellung des Verfeinerungszustands stehen im Sinne der kooperativen Aufteilung dem Modul zum Gittertransfer zur Verfügung, um mit dem Grobgitterelement auch die Verfeinerungsinformation zwischen Teilgittern verschieben zu können. Aufteilung des Pakets: Datei .h .cc Kurzbeschreibung gitter sti.h Schnittstellendefinitionen für die Eintrittspunkte der rekursiven Backup- und Restoremethoden in die Teilbäume der Element-, Flächen- und Kantenhierarchie. gitter sti.cc Methoden zum Sichern der Verfeinerungssituation und zur Wiederherstellung des Gitters aus der Verfeinerungsinformation. Diese Methoden greifen nur auf Schnittstellen zu, die vom konkreten geometrischen Typ unabhängig sind. 118 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG .cc gitter pll sti.cc Parallele Erweiterung des Backup/Restore Basiskonzepts aus gitter sti.cc zur Erzeugung verschiedener durchnumerierter Dateinamen. .cc gitter euler impl.cc Erweiterung des Backup/Restore Basiskonzepts für das numerische Verfahren: Die elementresidenten Daten und die Zeit werden ebenfalls gesichert bzw. wiederhergestellt. .cc gitter euler pll impl.cc Erweiterung des Backup/Restore Konzepts für das serielle numerische Verfahren auf die parallele Situation durch die Erzeugung verschiedener Dateinamen. 5.3 Numerisches Verfahren Für das numerische Verfahren wird gezeigt, wie eine Integration in den bestehenden Entwurf von Gitterdatenstrukturen und Basisalgorithmen aussehen kann (vgl. Kap. 3.4). Die anschließende Ausdehnung auf ein verteiltes Gitter benötigt keine umfangreiche Ergänzung des Daten- bzw. Methodeninhalts der verschiedenen Klassen sondern lediglich eine weitere Implementierung des Randelements für den inneren Rand (vgl. Kap. 4.3). Um die Komponenten des numerischen Verfahrens zu entflechten und deren Verwendung in anderem Zusammenhang zu erleichtern, ist das Paket an dieser Stelle aufgeteilt in einen Teil mit spezifischen Datenstrukturen für das explizite Finite Volumen Verfahren (1.12) und einen Teil, der Integrationsformeln, Referenzabbildungen und allgemeine Hilfsmittel für eine größere Klassen von numerischen Verfahren enthält. HexaederEulerImplementierung 4-PolygonEulerImplementierung 4−PolygonRandImplementierungEuler 2 Interpolation Instantiierung operator () (kartenpunkt : Real [2]) : Vec5 Linkes und rechtes Interpolationsobjekt zur Flussberechnung InterpolationOrdnung0 InterpolationOrdnung1 operator () (kartenpunkt : Real [2]) : Vec5 operator () (kartenpunkt : Real [2]) : Vec5 base : Vec5 koeffizienten : Vec5 [4] Abbildung 5.5: Schnittstelle und Implementierung der Interpolationsobjekte. Der Funktionsaufrufoperator liefert mit der Stützstelle in lokalen Koordinaten den Wert der Erhaltungsgrößen an dieser Stelle. Die Implementierungen unterscheiden sich hinsichtlich der Ordnung des Interpolationspolynoms. 5.3. NUMERISCHES VERFAHREN 119 5.3.1 Kompressible Euler-Gleichungen Das Paket faßt alle Deklarationen und Definitionen zusammen, die Bestandteile des expliziten Finite Volumen Verfahrens für die kompressiblen EulerGleichungen in drei Raumdimensionen enthalten. Aufteilung des Pakets: Dateiname Kurzbeschreibung euler.h/.cc Paket mit Klassendefinitionen für die Elementdaten, den Erhaltungsvektor und die Interpolationsobjekte nullter und erster Ordnung (vgl. Kap. 3.4, Abb. 3.17). Schablonen zur Erzeugung der Randbehandlung, und zum Anschluß der numerischen Flüsse an die Integrationsobjekte. swflux.cc Prozeduren mit ANSI-C Schnittstellen zur Berechnung der Flußfunktion nach Steger und Warming (vgl. Kap. 1.2.3) [34, 42]. .h gitter sti.h Abstrakte Definitionen für die Methoden in den Schnittstellen und Geometriesockelklassen, die für die Methodenauflösung bei der Berechnung der numerischen Flüsse benötigt werden (vgl. Kap. 3.4). .h .cc gitter euler impl.h Klassendefinitionen aller Gitterkomponenten, die für das numerische Verfahren erweitert sind: Ein Hexaeder mit Dateninhalt und Methoden zur Interpolation und Restriktion (1.28),(1.29) bei Verfeinerung bzw. Vergröberung, eine Vierecksfläche mit Methoden zur Berechnung der numerischen Flüsse und Randelementimplementierungen zur korrekten Behandlung der Randbedingungen (vgl. Kap.1.2.4, 3.4, Abb. 3.20). gitter euler impl.cc Implementierung der Methoden des für das numerische Verfahren erweiterten Gitters: Zeitschrittberechnung, Bestimmung des Verfeinerungskriteriums und Sicherung bzw. Wiederherstellung der Elementdaten (Erhaltungsvektor). gitter euler pll impl.h Klassen, die eine Behandlung der inneren Ränder des verteilten Gitters ermöglichen (vgl. Kap. 4.3). Diese Randelemente verhalten sich auch bei Verfeinerung und Vergröberung bzgl. Interpolation (1.28) bzw. Restriktion (1.29) im Sinne des numerischen Verfahrens korrekt. .h .cc .cc .cc .h 120 .cc KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG gitter euler pll impl.cc Erweiterung des Zeitschrittverfahrens auf das verteilte parallele Gitterkonzept mit zusätzlichem globalem Abgleich der Zeitschrittweite und einer Methode für den Datenaustausch zwischen den Zeitschritten (vgl.Kap. 4.3). 5.3.2 Integrationsformeln Das Paket enthält zwei parametrisierbare Klassen, die zur Volumen- bzw. Oberflächenintegration auf Hexaederelementen mit verschiedener Ordnung eingesetzt werden können (vgl. Kap. 3.4.2). Weiterhin stehen Klassen mit Implementierungen der Referenzabbildung vom Einheitswürfel in einen verformten Hexaeder mit geraden Kanten (trilinearer Ansatz) und vom Einheitsquadrat in eine Außenfläche dieses Elements (bilinearer Ansatz) zur Verfügung (3.10). Aufteilung des Pakets: Dateiname .h .cc Kurzbeschreibung mapp cube 3d.h Parametrisierbare Klassen mit Integrationsmethoden für den Einheitswürfel und dessen Oberflächen sowie Klassen zur Beschreibung der trilinearen und bilinearen Referenzabbildung. mapp cube 3d.cc Definition der konstanten Klassenvariablen für die Integrationsstützstellen und -gewichte sowie der umfangreicheren Operationen. Hinweis: Die Berechnung der numerischen Flußfunktion stellt ein Zusammenspiel aus der konkreten Implementierung der numerischen Flußfunktion, den Festlegungen für die Parametrisierungen der Zellgrenzflächen und deren Parametergebieten, den konkreten Interpolationsobjekten für die verschiedenen Approximationsordungen und den Integrationsformeln dar. Viele Klassen (euler.h) sind als Schablonen formuliert, damit die entsprechenden Berechnungsformeln für die numerische Flußfunktion baukastenartig zusammengestellt werden können (vgl. Kap. 3.4, Abb. 3.17). þ 5.3. NUMERISCHES VERFAHREN 121 VolumenBerechnung << utility >> QuadraturWürfel3DBasis Argumenttyp − : arg_t Werttyp Real : val_t operator () (Weltpunkt : Real [3], \ Kartenpunkt : Real [3], Argument : arg_t) : val_t Stützstellen : Real Gewichte : Real i : Integrationsobjekt TrilineareReferenzAbbildungWürfel QuadraturWürfel3D 1 1 typedef arg_t typedef val_t determinanteBerechnen () : Real abbilden (Kartenpunkt : Real [3], Weltpunkt : Real [3]) invertieren (Weltpunkt : Real [3], Kartenpunkt : Real [3]) integrieren2 (a : arg_t) : val_t integrieren3 (a : arg_t) : val_t Würfeleckpunkte : Real [3] Koeffizienten : Real [8][3] map : Referenzabbildung Abbildung 5.6: Parametrisierbare Klasse mit Integrationsformeln für den Einheitswürfel. Zur Konstruktion wird eine entsprechende Referenzabbildung benötigt. Die Ausprägung mit der Klasse VolumenBerechnung liefert Formeln zur Volumenintegration. OberflächenBerechnung << utility >> QuadraturRechtecksflächeBasis Argumenttyp − : arg_t Werttyp Real : val_t operator () (Kartenpunkt : Real [2], \ Normale : Real [3], Argument : arg_t) : val_t Stützstellen : Real Gewichte : Real i : Integrationsobjekt QuadraturRechtecksfläche typedef arg_t typedef val_t integrieren (a : arg_t, Auflösung : Int) : val_t integrieren1 (a : arg_t) : val_t integrieren3 (a : arg_t) : val_t BilineareReferenzAbbildungOberfläche 1 1 abbilden (Kartenpunkt : Real [2], Weltpunkt : Real [3]) invertieren (Weltpunkt : Real [3], Kartenpunkt : Real [2]) normale (Kartenpunkt : Real [2], Normale : Real [3]) Flächeneckpunkte : Real [3] AbbildungsKoeffizienten : Real [4][3] NormalenKoeffizienten : Real [3][3] map : Referenzabbildung Abbildung 5.7: Parametrisierbare Klasse mit Integrationsformeln für die das Einheitsquadrat. Zur Konstruktion wird eine entsprechende Referenzabbildung benötigt. Die Ausprägung mit der Klasse OberflächenBerechnung liefert Formeln zur Oberflächenintegration. 122 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG 5.4 Identifikation Die Identifikationsrelationen für die Knoten, Kanten und Flächen des Grobgitters werden nach dessen Veränderung neu berechnet und in passenden Datenstrukturen gespeichert (vgl. Kap. 4.4). Demgegenüber entsteht die Identifikation der Knoten, Kanten und Flächen innerhalb der Gitterhierarchie durch deren globale Ausrichtung und adäquate Iterationsklassen (vgl. Kap. 5.7). Aufteilung des Pakets: Dateiname Kurzbeschreibung .h key.h Klassendefinitionen für die zur Identifikation der Grobgitterobjekte verwendeten Schlüssel (vgl. Kap. 4.4). .h gitter pll sti.h Schnittstellendefinitionen für die Methoden zur Schlüsselerzeugung und zur Schätzung des Verbindungssterns (vgl. Kap. 4.4.2). Weiterhin enthalten sind die Schnittstellendefinitionen für den Zugang zu den Identifikationsiteratoren (Iteratorpaar) (vgl. Kap 4.4.1). gitter pll sti.cc Implementierungen für die paarweisen Iterationsobjekte, durch die die Identifikationsrelation sowohl für das Grobgitter als auch innerhalb der Hierarchie nach außen repräsentiert wird. Die Struktur ähnelt dem Aufbau der Iterationsobjekte für das Gitter (gitter sti.cc). Allerdings gibt es nur für Knoten, Kanten und Flächen des Gitters Identifikationsiteratoren. .cc Hinweis: Der Algorithmus zur Berechnung der Datenstruktur (vgl. Kap. 4.4.3) ist als Schablone implementiert und wird jeweils für Knoten, Kanten und Flächen ausgeprägt. þ 5.5 Datenaustausch im parallelen Verfahren Der Austausch von Daten zwischen den Partitionen des verteilten Gitters muß immer erfolgen, sobald ein Datum, das in mehreren Teilgittern vorkommt, verändert wurde und die durchgeführte Veränderung auf anderen Teilgittern sichtbar werden soll (vgl. Kap. 4.3). Um hier eine möglichst strukturierte Situation zu erreichen, ist der Datenaustausch nach einem dreistufigen Plan hierarchisiert, der festlegt, wie die Gitterverwaltung auf eine Änderung des Zustands auf einem Teilgitter reagiert: 5.5. DATENAUSTAUSCH IM PARALLELEN VERFAHREN Änderung: 123 Reaktion: 1 Grobgitter Sämtliche Datenstrukturen der Identifikationsabbildung werden neu erzeugt, vergleichbar mit einem Programmstart. Weiterhin werden die Nummern der Grobgitterelemente, wie sie für die Datenbasis der dynamischen Lastverteilung erforderlich sind, neu vergeben. Anschließend folgt die Reaktion Punkt 2. 2 Verfeinerungssituation Die Datenbasis für die Steuerung der dynamischen Lastverteilung wird neu erzeugt. Eventuell findet eine Umverteilung des Gitters statt. Anschließend folgt die Reaktion Punkt 3. 3 Numerische Daten Die Daten in den Randelementen des inneren“ ” Rands werden ersetzt (vgl. Kap. 4.3). Dieser Vorgang wird nach jedem Zeitschritt des numerischen Verfahrens ausgelöst. Im Zuge dieser Aufteilung entsteht die Möglichkeit, eine Relation wie bedingt ” auch“ in den Entwurf einbetten zu können: Es wird davon ausgegangen, daß eine Änderung des Grobgitterzustands (z.B. als Folge einer Neuverteilung des Gitters) auch eine Aufdatierung der Verfeinerungsinformation und (dadurch) der Daten des numerischen Verfahrens erforderlich macht. Umgekehrt bedingt der Wechsel von einem Zeitschritt zum nächsten im numerischen Verfahren allein noch keine Konsistenzprobleme in der Grobgitterdatenhaltung bzw. in der Verfeinerungsstruktur. Aufteilung des Pakets: Datei .cc .h .cc .cc Kurzbeschreibung gitter pll sti.cc Prototypen für die Reaktion der Gitterverwaltung auf Änderungen des Grobgitters (Lastverteilung) bzw. des Verfeinerungszustands (Vergröberung/Verfeinerung). gitter pll impl.h/.cc Konkrete Realisierungen der o.g. Prototypen für ein Gitter aus leeren“ Elemente, Flächen, Kanten ” und Knoten. gitter euler pll impl.cc An die Datenhaltung im parallelen numerischen Verfahren angepaßte Methoden zum Datenaustausch nach Verfeinerung/ Vergröberung bzw. nach einer Grobgitteränderung (Lastverteilung). 124 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG 5.6 Dynamische Lastverteilung Die Gliederung des Entwurfs für die verteilte Gitterverwaltung (vgl. Kap. 4.6, Abb. 4.1) bedingt ein verstreutes Auftreten von Methoden und Daten für die dynamische Lastverteilung: Sie ist kein eigenständiges übergreifendes Konzept in der verteilten Gitterverwaltung, sondern verwendet Funktionalität aus anderen Modulen in der angebotenen Form für ihre Belange. Insbesondere stellt die Sicherungs- / Wiederherstellungsfunktionalität des Basisentwurfs (vgl. Kap. 5.2) eine zentrale Säule im Modul der dynamischen Lastverteilung dar. Desweiteren benötigt die Berechnung einer neuen Gitteraufteilung die Gewichte der Elementbäume über den Grobgitterelementen bzw. die Gewichte der Flächenbäume über den Flächen des Grobgitters (vgl.Kap. 4.6.1, Abb. 4.12) zur Festlegung des Modellgraphen. Diese Information wird in einer Datenbasis lokal auf jedem Teilgitter gesammelt und anschließend zu einer globalen Graphendarstellung auf jedem Teilgitter zusammengeführt, aus der das CSR (Compressed Storage Representation) Format erzeugt wird, welches von den Standardverfahren zur Partitionierung gewichteter Graphen aus den Bibliotheken [19, 30] verwendet wird. Aufteilung des Pakets: Datei Kurzbeschreibung gitter pll sti.h Beschreibung der Schnittstellen der Element-, Randelement-, Flächen-, Kanten- und Knotenerweiterungen für die verteilte Organisation des Gitters: Darin enthalten sind alle Methoden, mit denen sich die Lastverteilung an die Gitterobjekte wendet, wie z.B. Zuweisung zu einem neuen Teilgitter, Ein- und Auspacken der Teilbäume, Vergabe der Grobgitternumerierung und Anfragen der Daten für die Lastbewertung und Neuzuweisung (Elementbaum- und Flächenbaumgewichte; vgl. Kap. 4.6.1, Abb. 4.12). .cc gitter pll sti.cc Implementierungen der Methoden aus gitter pll sti.h , zusätzliche Module zur Numerierung der Grobgitterelemente und das Kriterium (2.10), wann eine Lastverteilung vorzunehmen ist (vgl. Kap. 2.4.1). .cc gitter pll mgb.cc Erweiterung des virtuellen Konstruktors für das Grobgitter aus gitter mgb.h um die Möglichkeit, aus einen Datenstrom, wie ihn die dynamische Lastverteilung erzeugt, lesen zu können (vgl. Kap. 4.6). .h 5.6. DYNAMISCHE LASTVERTEILUNG .h .cc .h .cc .h .cc 125 gitter pll ldb.h Definition der Klassen für die Datenbasis zur Lastbewertung und Neuverteilung. Diese Datenbasis besteht aus assoziativen Behältern, die Knoten bzw. Kanten des Grobgittergraphen sammeln, und können durch eine globale Operation zu einer globalen Graphendarstellung assembliert werden. gitter pll ldb.cc Methode zur Neupartitionierung des Grobgitters anhand seiner Darstellung als Graph (vgl. Abb. 4.12): Dazu werden lokale Heuristiken aus einer Bibliothek eingesetzt [30] und ein Algorithmus zur Reduktion der Kosten des Lasttransfers durch Permutation der Teilgebietsnummern (vgl. Kap. 4.6.1). gitter pll impl.h/.cc Implementierung aller Schnittstellenmethoden aus dem ersten Punkt für ein leeres“ Gitter ohne Da” teninhalt. Im einzelnen sind dies Methoden mit denen die Lastverteilung Teile des Grobgitters an ein neues Teilgebiet zuweisen kann, Methoden zur Kodierung der Grobgitterobjekte als Datenstrom bzw. Methoden zum Aufbau des Verfeinerungsbaums über einem Grobgitterobjekt aus einem Datenstrom (vgl. Kap. 5.8). gitter euler pll impl.h/.cc Redefinition aller Operationen aus ter pll impl.h/.cc, die mit den Daten des merischen Verfahrens umgehen müssen: transportierte Elementbäume müssen auch Daten in den Blättern übertragen werden. gitnuFür die 5.6.1 Anpassungen: Die dynamische Lastverteilung kann in mehreren Punkten an die Bedürfnisse eines unterschiedlichen bzw. erweiterten numerischen Verfahrens angepaßt werden: Aufwandsmodell: Eventuell ist das Aufwandsmodell in der Form zu ändern, daß die Verhältnisse zwischen Knotengewichten (Berechnungsaufwand) und Kantengewichten (Kommunikationsaufwand) neu vorgegeben werden: Falls die Knotengewichte verhältnismäßig zu klein sind, erzeugen die Standardverfahren häufig Graphen mit sehr unausgewogenen Partitionslasten (vgl. Kap. 4.6.1). Partitionierungsmethode: Die Berechnung der Lastzuweisung wird bisher in Form einer Graphenpartitionierung realisiert und auf allen Teilgittern völlig identisch und global durchgeführt. Diese Lösung bietet die Möglichkeit, einerseits Standardbibliotheken für die Graphenpartitionierung zu verwenden, die in 126 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG der Regel nicht zur Parallelverarbeitung vorbereitet sind, andererseits können aber auch eigene Heuristiken zur Lastzuweisung schnell entwickelt werden, weil immer die globale Information zur Verfügung steht. Die Lastzuweisung wird mit lokalen Heuristiken aus der PARTY-Bibliothek [30] zur Graphenpartitionierung durchgeführt, weshalb die Methode zur Neupartitionierung (in gitter pll ldb.cc ) zuerst einen Satz von Vektoren mit den Daten zur Graphenbeschreibung erzeugen, wie die Aufrufkonvention der Bibliothek es fordert. Dabei handelt es sich um das CSR (Compressed Storage Representation) Graphenformat [19]. Erweiterung des Datentransfers: Falls zusätzliche Daten auf den Elementen, Flächen Kanten oder Knoten mit in den Datentransfer einbezogen werden sollen, hat dies an der Stelle der Erweiterungsklasse des betreffenden Gitterobjekts zu geschehen (vgl. Kap. 5.1.2). Das Schema, wie dem Transfer des Grobgitterelements ein Datentransfer hinzugefügt werden kann, läßt sich anhand des Transfers der elementresidenten Daten (Erhaltungsvektor) im parallelen Simulationsprogramm nachvollziehen (gitter euler pll impl.h/.cc ). 5.7 Iterationspaket Aufgrund der hierarchischen Anordnung (vgl. Kap. 3.2, Abb. 3.13) der Gitterkomponenten wird die Zugehörigkeit zu einer Iterationsschnittstelle (Element, Fläche, Kante oder Knoten) nicht direkt durch eine Behälterklasse vermittelt. Elemente Flächen Kanten Knoten SubTree SubTree Wrapper SubTree Abbildung 5.8: Zerlegung in Basisiterationsklassen: Auf einem isotrop verfeinerten Hexaederelement werden ein Elementbaum, ein Flächenbaum, ein Kantenbaum und ein einzelner Knoten vorgefunden. 5.7. ITERATIONSPAKET 127 Deshalb muß eine solche Gliederung während der Iteration vorgenommen werden, was konkret z.B. bedeutet, daß sich ein Durchlauf über alle Knoten des Gitters unsichtbar auch auf dessen Kanten, Flächen und Elemente erstreckt. Standardentwurfsmuster: Das Iterationskonzept folgt zunächst dem Standardentwurfsmuster des Iterator Pattern [12], die Schnittstelle läßt eine Vorwärtsiteration [2] zu. Der Funktionsumfang ist somit eingeschränkt, zufälliger Zugriff auf bestimmte Gitterobjekte ist nicht möglich. Andererseits macht es wenig Sinn, Funktionalität im Entwurf festzuschreiben, die mit den gewählten Datenstrukturen nicht mit dem erwarteten Zeitverhalten realisiert werden kann [27]. Vorschlag: Es besteht demnach Bedarf an einfach verwendbaren Iterationsklassen, die geschachtelte Iterationen in nahezu jeder beliebigen Art bereitstellen. Die Idee liegt nahe, alle Iterationsvorgänge in Basisiterationen zu zerlegen und jene wiederum baukastenartig auf verschiedene Arten zusammenzusetzen (vgl. Abb. 5.8): List SubTree Listeniterator: Der Listeniterator vermittelt den Durchlauf einer verketten Liste, die alle Elemente, Flächen Kanten bzw. Knoten des Grobgitters enthält. Der Listeniterator ist im wesentlichen ein Adapter zu den Datenstrukturen der Standard Template Library [27]. Teilbaumiterator mit Filter: Um einen Teilbaum von Objekten eines einheitlichen Typs zu durchlaufen. Das Iterationsobjekt wird mit einer Referenz auf die Wurzel des Teilbaums konstruiert. Zusätzlich ist ein Filter (Comparison Object [27]) eingebaut, der es ermöglicht, nur eine Teilmenge zu erfassen. Beispiel: Der Teilbaumiterator soll im numerischen Verfahren eine Iteration über alle Elemente der Hierarchie, die Blätter der Hierarchie sind, ermöglichen. Wrapper Wrapper: Wrapper (Decorator Pattern [12]) werden benötigt, um einen Typwechsel bzgl. des Gegenstandes der Iteration zu vermitteln. Der Wrapper wandelt den Gegenstand des eingeschlossenen (umwickelten) Iterationsobjekts in einen Gegenstand (bzw. Referenz) von anderem Typ um, nach Maßgabe einer festgelegten Konversionsfunktion. Beispiel: Aus einem Hexaederelement können Teilbaumiteratoren für die inneren Flächen- oder Kantenbäume (vgl. Abb. 5.8) konstruiert werden. Um an den inneren Knoten zu gelangen, wird nur der Wrapper benötigt. Insert Verknüpfungsiterator: Der Verknüpfungsiterator setzt eine Iteration in eine andere ein, vorausgesetzt der Gegenstand der ersten Iteration läßt die Konstruktion des zweiten Iteratorobjekts zu (vgl. SubTree, Wrapper). 128 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG Beispiel: Der Listeniterator durchläuft alle Elemente des Grobgitters, wobei auf jedem Grobgitterelement ein Teilbaumiterator errichtet wird, der nur die Blätter des Teilbaums zeigt. Auf diese Art werden alle Blätter der Elementbäume durchlaufen. Align Verbinder: Iteratorverbinder verbinden die Iteration zweier oder mehrerer Iterationsobjekte linear. Die eingeschlossenen Iterationsobjekte werden nacheinander ausgewertet. Es gibt Iteratorverbinder, die als Schablonen mit den konkreten Typen der Iterationsobjekte ausgeprägt werden und solche für die polymorphe Schnittstelle. Beispiel: Das Grobgitter speichert nicht alle Elemente in einem Container, sondern ordnet sie nach der Geometriesockelklasse, d.h. nach dem Elementtyp an. Deshalb muß ein Iterationsobjekt für die Grobgitterelemente alle Behälter nacheinander durchlaufen. Proxy Proxy: Der Platzhalter (Proxy Pattern [12]) ermöglicht als nichtabstraktes Typargument die Ausprägung einer Schablone für eine andere Iterationsklasse, wenn die Iteration über eine polymorphe Schnittstelle verlaufen soll. Das Proxyobjekt delegiert die Iteration an die Schnittstelle, auf die es eine Referenz hält. Beispiel: Die Listeniteratoren des Grobgitters werden in die Iteration des hierarchischen Gitters durch Proxies eingesetzt, was die Möglichkeit eröffnet, die Behälterklassen des Grobgitters auszutauschen. Aufteilung des Pakets: Datei Kurzbeschreibung .h walk.h Alle Schablonen, die zum Zusammensetzen komplizierterer Iterationsklassen benötigt werden: Listeniterator, Teilbaumiterator, Wrapper, Iteratorverknüpfung, Iteratorverbinder. Das Iteratorproxy gehört inhaltlich zu den Schnittstellen des Gitters. .h gitter sti.h Definition der Standardschnittstelle für alle Iterationsobjekte und der Iteratorproxies zum Anschluß der Grobgitteriteration an die hierarchischen Iterationsverfahren. gitter sti.cc Alle Methoden des Gitters, die Iterationsobjekte für die Elemente, Flächen, Kanten und Knoten des Grobgitters und die jeweiligen Blätter des hierarchischen Gitters erzeugen. gitter pll sti.h Standardschnittstelle der geteilten Iteratoren für mehrdeutige Gitterelemente im verteilten Gitter. Definition eines Referenzierungsobjekts (engl.: smartpointer) für die geteilten Iteratoren. .cc .h 5.8. SCHNITTSTELLE ZUM MESSAGE PASSING SYSTEM .cc gitter pll sti.cc 129 Alle Methoden, die für ein verteiltes Gitter Paare von Iterationsobjekten mit der Identifikationsabbildung erzeugen. Erweiterungen: Der Satz von Basisiterationsklassen reicht für alle möglichen Anwendungen aus. Eventuell werden eigene Filter, d.h. Vergleichsobjekte benötigt, um neuartige zusammengesetzte Iteratorenklassen erstellen zu können. Das Iteratorenpaket ist ein Basiswerkzeug zur schnellen und sicheren Anpassung des Gitterkonzepts an die Bedürfnisse neuer numerischer Algorithmen. 5.8 Schnittstelle zum Message Passing System Die Schnittstelle zum Message Passing System (vgl. Kap. 2.3.1) ist möglichst schmal und beschreibt nur die Operationen, die im Simulationsprogramm tatsächlich benötigt werden, was eine Anpassung auf verschiedene Bibliotheken oder Programmiermodelle bzw. Standards erleichtert. Dies drückt sich in der vorgeschlagenen Schnittstellen- und Klassenhierarchie (vgl. Abb. 5.10) sowie im Umfang der enthaltenen Operationen aus. Deren konkrete Implementierung verwendet eine Bibliothek nach dem Message Passing ItemType << interface >> Iterator typedef val_t first () next () size () done () : bool item () : val_t IteratorA, IteratorB return true ItemType, Filter IteratorA, Konverter IteratorVerknüpfung IteratorDecorator innen : IteratorA aussen : IteratorB i : Iterator first () next () size () done () : bool item () : val_t return 0 first () next () size () done () : bool item () : val_t TeilbaumIterator wurzel : ItemType & stack : ItemType * first () next () size () done () : bool item () : val_t Abbildung 5.9: Hierarchie der Iteratorklassen: Die Instanzen der Schnittstellenklasse (oben) sind leere Iterationsobjekte. Die abgeleiteten Realisierungen als Teilbaum-, Verknüpfungs-, Listen-, Proxy-, Wrapper- und Verbindungsiterator lassen sich untereinander zu Iterationsklassen für kompliziertere Vorgänge (Datenhaltung) verbinden. 130 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG Interface Standard MPI [26], um die verschiedenen Methoden zur globalen und lokalen Kommunikation zu realisieren. Aufteilung des Pakets: Datei Kurzbeschreibung .h mpAccess.h Schnittstellendefinitionen der globalen und lokalen Dienste, die von der Anwendung angefordert werden können (vgl. Abb. 5.10). .h serialize.h Definition und Implementierung einer einfachen Lösung für ein strombasiertes Konzept zum Datentransfer. Es findet keine Kodierung bzw. Konversion der Daten statt. Hinweis: Falls die Datendarstellung über die an einer Anwendung beteiligten Prozesse variiert (heterogener Rechner), muß an dieser Stelle eine einheitliche Kodierung der Daten hinzugefügt werden. GlobaleMessagePassingDienste poolGröße () : Int meinRang () : Int globalesMaximum (i : Typ) : Typ globaleSumme (i : Typ) : Typ globalSammeln (v :Typ ) : Vector < Typ > barriere () LokaleMessagePassingDienste links : Set < Int > anzahlLinks () : Int linkNachRangUmrechnen (link : Int) : Int rangNachLinkUmrechen (rang : Int) : Int linkEinfügen (rang : Int) alleLinksEntfernen () linksSymmetrischEinfügen (links : set < Int > ) linksAnzeigen () lokalAustauschen (v : Vector < Typ > ) : Vector < Vector < Typ > > MPI_basierteImplementierung poolGröße () : Int meinRang () : Int globalesMaximum (i : Typ) : Typ globaleSumme (i : Typ) : Typ globalSammeln (v :Typ ) : Vector < Typ > barriere () lokalAustauschen (v : Vector < Typ > ) : Vector < Vector < Typ > > MPI_Allreduce (..,MPI_Op,...) MPI_Allgather (...,MPI_Type, ...) MPI_Barrier (MPI_Comm ...) communicator : MPI_comm Abbildung 5.10: Klassenhierarchie des Zugangs zum Message Passing System: Die globale Kommunikation liegt an oberster Stelle, sie wird u.a. auch zur Verwaltung der Kommunikationssterne der lokalen Methoden benötigt. 5.9. AUSFÜHRBARE PROGRAMME .cc .h .cc 131 mpAccess.cc Definition aller Operationen, die nur auf den abstrakten Schnittstellenbeschreibungen aufsetzen und somit transparent gegenüber einem Austausch der Message Passing Bibliothek sind. mpAccessMPI.h Klassendefinitionen für die konkrete Implementierung der Schnittstellen zum Message Passing System auf der Basis einer Bibliothek nach dem MPI Standard [26] und Funktionenschablonen für die konkreten Implementierungen (mpAccessMPI.cc). mpAccessMPI.cc Definition der globalen und lokalen Message Passing Dienste aus den Schnittstellen mit den Mittel der Bibliothek nach dem MPI Standard [26]. Dazu sind zwei Klassen mit polymorphen Schnittstellen definiert: Eine beschreibt die Funktionalität zur Abwicklung aller Aufgaben, die eine globale Kommunikation erfordern, wie die Bestimmung des globalen Maximums, eine Barriere oder das Assemblieren des globalen Verbindungssterns. Die zweite, davon abgeleitete Schnittstelle bezieht sich auf die Kommunikation über den lokalen Verbindungsstern, z.B. Datenaustausch zwischen benachbarten Teilgebieten. Diese Hierarchie ergibt sich auf natürliche Art, weil Funktionen auf den lokalen Verbindungssternen, wie z.B. das symmetrische Einsetzen von Verbindungen, die Verfügbarkeit globaler Kommunikationswege voraussetzen. 5.9 Ausführbare Programme Die Quelldateien, die zum Umfang dieser Arbeit gehören, lassen den Aufbau von zwei verschiedenen Projekten mit jeweils einem ausführbaren Programm für die serielle und die parallele Bearbeitung zu: ÿ ÿ Euler-Gleichungen: Simulationsprogramm für die kompressible reibungsfreie Durchströmung einer komplexen dreidimensionalen Geometrie. Die ausführbaren Programme werden unter den Namen main euler (serielles Verfahren) bzw. main euler pll (paralleles Verfahren) angelegt. Ball: Undokumentiertes Testproblem ball zur lokalen Gitterweitenanpassung: Durch den Würfel wird längs der Verbindungslinie der Schwerpunkte von linker und rechter Seitenfläche eine kugelförmige Verfeinerungszone hindurch bewegt, innerhalb derer alle Elemente bis zu einem wählbaren, maximalen Verhältnis verfeinert werden. Die zugehörige parallele Version ball pll Version kann bei der Weiterentwicklung von Komponenten der dynamischen Lastverteilung als Testproblem verwendet werden (vgl. Anh. B). 132 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG Weitere Quelldateien Um die ausführbaren Programme aufbauen zu können, werden noch ein Makefile und entsprechende Quelldateien mit den Hauptroutinen der einzelnen Projekte benötigt. Diese und alle weiteren Dateien, die inhaltlich keinem der vorangehenden Abschnitte zugeordnet sind, werden nachfolgend beschrieben, wodurch der Index der Quelldateien zu einer vollständigen Referenz wird (vgl. Anh. C). Datei Kurzbeschreibung makefile Makefile für alle vier Teilprojekte, das speziell für den C++ Compiler der IBM RS 6000 SP eingerichtet ist. .cc main euler.cc Hauptroutine des seriellen Verfahrens zur Simulation kompressibler Strömungen in 3D auf unstrukturierten Hexaedernetzen mit lokaler Gitterweitenanpassung. .cc main euler pll.cc Hauptroutine des parallelen Simulationsprogramms mit lokaler Gitterweitenanpassung und dynamischer Lastverteilung. .cc ball.cc Serielles Testprogramm für die lokale Gitterweitenanpassung mit einer zeitabhängigen kugelförmigen Verfeinerungszone. .cc ball pll.cc Verteilt-paralleles Testproblem für Gitterweitenanpassung und dynamische Lastverteilung. myalloc.h/.cc Basisklasse (Allokator), die eine Fragmentierung des Adreßbereichs aufgrund der Objekterzeugung und -löschung während der lokalen Gitterweitenanpassung vermeidet. .h .cc Übersetzen der Programme Zum Übersetzen der Programme wird ein ANSI-konformer C++ Compiler oder der IBM CSet C++ Compiler verwendet. Ausführen der Programme Um die Programme mit den sequentiellen bzw. parallelen Verfahren für die kompressiblen Euler-Gleichungen ausführen zu können, werden noch folgende zusätzliche Dateien benötigt (vgl. Anh. B): ÿ Eine Datei mit dem initialen Hexaedernetz (Grobgitter) als Klartext der Knotenkoordinaten und Element-Knoten Zusammenhänge. Der Dateiname wird mit der Kommandozeile übergeben. 5.9. AUSFÜHRBARE PROGRAMME ÿ 133 ÿ Eine Datei mit den konfigurierbaren Parametern des numerischen Verfahrens und der Gitterweitenanpassung. Der Dateiname ist fest eingestellt auf: const_ffs.dat Für die parallelen Programme ist ferner eine Datei mit den Einstellungen für die dynamische Lastverteilung erforderlich. Der Dateiname ist fest eingestellt auf: lastverteilung.cfg Hinweis: Weitere Hinweise zu Konfigurations- und Gitterdateien sind auf dem CD-ROM Datenträger enthalten (README Dateien in verschiedenen Verzeichnissen). þ Sequentielles Programm Die Programme für sequentielle Ausführung werden ohne Verwendung einer Message Passing Bibliothek übersetzt und gebunden und können daher auf konventionelle Art aufgerufen werden: > main_euler <Grobgitter> <Backup> [Restore] Das zweite Argument der Kommandozeile ist verbindlich, und enthält den Namen, aus dem durch Erweiterung mit .<Zeitschritt> der Dateiname für die Sicherungsdatei im entsprechenden Zeitschritt gebildet werden soll. Das optionale dritte Argument wird angegeben, falls die Rechnung aus einer Sicherungsdatei gestartet werden soll, es enthält in diesem Fall den Dateinamen. Paralleles Programm Das parallele Programm wird in der vorliegenden Form mit dem standardisierten Ladebefehl für Anwendungen, die mit einer MPI konformen Bibliothek [26] gebunden sind, aufgerufen: > mpirun -np # main_euler_pll <Grobgitter> <Backup> [Restore] Hinweis: Eine Besonderheit ergibt sich beim Anlegen der Sicherungsdateien: Da die dynamische Lastverteilung die Grobgitterstruktur der verschiedenen Teilgitter von Zeit zu Zeit verändert, werden mit jedem Sicherungsvorgang auch die Grobgitterdaten gesichert, falls sie sich vom Zustand der vorangegangenen Sicherung unterscheiden. Die Dateinamen werden vom parallelen Programm nochmals mit .<Teilgitternummer> erweitert, um für jedes Teilgitter einen eindeutigen Dateinamen zu bilden. þ 134 KAPITEL 5. DOKUMENTATION ZUR IMPLEMENTIERUNG 135 Kapitel 6 Testbeispiele, Messungen, Ergebnisse und Bewertung Das parallele Programm zur Simulation kompressibler Strömungen auf Parallelrechnern mit verteiltem Hauptspeicher soll abschließend hinsichtlich seiner Leistungsfähigkeit untersucht werden. Dazu werden Testsituationen konstruiert, in deren Rahmen die zur Bewertung der Beschleunigung, der Skalierbarkeit und des Nutzens der dynamischen Lastverteilung nach den vorgestellten Definitionen (vgl. Kap. 2.4) benötigten Zeitmessungen durchgeführt werden können. Zu jedem Test gehören mehrere Messungen (Experimente), durch die das Verhalten der Programmausführung für verschiedene Parameter studiert wird. Aus den gewonnenen Meßdaten können die entsprechenden Größen berechnet und, daran anschließend, bewertet werden. Dadurch lassen sich Anhaltspunkte für eine Weiterentwicklung einzelner Komponenten des Programms finden. 6.1 Hinweise 6.1.1 Zeitmessung Die Ausführungszeit der Anwendung sowie die anteilige Laufzeit von bestimmten Teilalgorithmen wird mit der Funktion clockt_t clock () aus der Standardbibliothek gemessen. Dabei ist zu berücksichtigen, daß diese Funktion nicht grundsätzlich die Realzeit der Anwendung, wie sie von den Definitionen (vgl. Kap. 2.4) gefordert wird, wiedergibt. Die gemessenen Zeitintervalle sind mit der Realzeit nur identisch, solange der Rechner exklusiv benutzt wird, und gewisse Systemaufrufe nicht innerhalb der 136 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG Zeitmessung erfolgen. Die gewählte Vorgehensweise zur Zeitmessung ist aus den folgenden Gründen gerechtfertigt und korrekt: - Der Parallelrechner stand den Anwendungen exklusiv zur Verfügung. - Die Flußberechnung des numerischen Verfahrens enthält keine Systemaufrufe, die eine Zeitmessung verfälschen könnten. Deshalb wurde dieser Teilalgorithmus stellvertretend für die anteilige Laufzeit des gesamten numerischen Verfahrens ausgewählt (vgl. Kap. 6.1.4). - Während des gesamten Zeitschritts werden auch Funktionen aus der Message Passing Bibliothek aufgerufen, die bedingt durch mögliche Wartezeiten problematisch sein könnten: Zur Bestätigung der gemessenen Werte wurde in einigen Fällen die Summe der Laufzeiten aller Zeitschritte gegen die durch externe Messung bestimmte Gesamtlaufzeit der Anwendung getestet und mit ausreichender Genauigkeit bestätigt. Bemerkung: Eine alternative Möglichkeit besteht darin, zur Zeitmessung das þ MPI Profiling Interface [26] heranzuziehen. 6.1.2 Problemstellung Geometrie: Als Testproblem wird die Simulation der zeitabhängigen Durchströmung eines Windkanals mit gegen die Strömung einspringender Stufe betrachtet. Es handelt sich um die in drei Raumdimensionen ausgedehnte Geometrie des Forward-Facing-Step [43] (vgl. Abb. 6.1). Alle Längen in der Zeichnung sind bezogen auf eine Einheitslänge angegeben, weil im Fall der reibungsfreien Euler-Gleichungen die Dimensionen Länge und Zeit durch die Schallgeschwindigkeit linear miteinander gekoppelt sind (vgl. Kap. 1.1). 1 LE 0,2 LE z 0,6 LE y 3,0 LE x Abbildung 6.1: Abmessungen des Windkanals mit einspringender Stufe für die Testrechnungen zur Leistungsmessung [43]. 6.1. HINWEISE 137 Die Ausdehnung der Geometrie in Richtung der y-Achse wird so gewählt, daß die zugehörige Raumrichtung durch das gröbste Gitter in acht Teilen diskretisiert wird (ca. 0,5 LE). Randbedingungen: Die Rand- und Anfangsbedingungen entsprechen denen des Standardtestproblems [43], damit vergleichbare, bekannte Simulationsergebnisse erhalten werden: Im einzelnen sind dies der konstante Einströmwert am linken Rand des Windkanals und die Anfangswerte auf allen Zellen des Gitters. Beide Werte sind identisch festgelegt zu (6.1) was für einen Windkanal ohne Stufe bereits die stationäre Lösung des Anfangsrandwertproblems darstellt. Die Skizze (vgl. Abb. 6.2) zeigt die Lage der verschiedenen Randtypen: Die Anströmung der Geometrie erfolgt von links, die y-Achse weist vom Betrachter weg. Die zeitliche Entwicklung der Strömung ist bereits ausführlich studiert worden [42]: Es entsteht zuerst eine kleine Stoßwelle an der Stufe, die sich dann rasch vergrößert. Sobald sie eine Begrenzung der Geometrie berührt, wird sie dort reflektiert, wodurch man ein zu Anfang zeitlich sehr schnell wechselndes Muster von Stoßwellen im Windkanal erhält. Die numerische Simulation mit dem verwendeten einfachen Verfahren erreicht für große Zeiten langsam eine stationäre Situation. Einströmung Reflexionsrand Ausströmung z Sliprandbedingung !y x Abbildung 6.2: Randbedingungen für die Testsituation: Konstante Überschalleinströmung von links (blau), freie Ausströmung nach rechts (rot), die Sliprandbedingung auf den Flächen vorne, hinten und vor der Stufe (grün) sowie eine Reflexionsrandbedingung auf allen anderen Flächen (gelb) [43]. 138 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG Damit enthält dieses Simulationsproblem vor allem zwei Schwierigkeiten für die dynamische Lastverteilung: ÿ ÿ Zu Beginn der Berechnung entsteht eine kleine, sehr stark verfeinerte Zone an der Stufe. Falls diese nicht mehr genügend Elemente des Grobgitters überdeckt, kann kein vollständiger Lastausgleich mehr gewährleistet sein (vgl. Kap. 4.1.1). Die entstehenden Stoßwellen bewegen sich großräumig innerhalb des Berechnungsgebiets. Hier stellt sich die Frage, wie oft das Gitter neu verteilt werden muß, um eine gleichmäßige Belastung des Parallelrechners zu erreichen. 6.1.3 Basisproblem Die Problemstellungen für die Leistungsmessung und die Bewertung der dynamischen Lastverteilung werden ausgehend von einer Referenzrechnung zu dem Basisproblem konstruiert bzw. festgelegt. Die Simulation für dieses Basisproblem umfaßt die numerische Berechnung der Lösungsfunktion des physikalischen Testproblems aus dem vorigen Abschnitt, wobei die Parameter der Parallelverarbeitung, der dynamischen Lastverteilung, der lokalen Gitterweitenanpassung und des numerischen Verfahrens folgendermaßen vorgegeben werden: ÿ ÿ Numerisches Verfahren: CFL - Zahl (1.24): . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "$#&% '( Startzeit: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ()+*-,/.* Endzeit: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (0213 5476 ÿ Gitter/Verfeinerungskriterium: Grobgitter: . . . . . . . . . . . . . . . . . Hexaedernetz aus 8336 Elementen Grenzwerte (1.27): . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 '9:; '< Dynamische Lastverteilung: Teilgitter: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = Verfahren: . . . . . . . . . . . . . . . . . . . . . Heuristik von Kernighan-Lin [30] Parameter (4.7): . . . . . . . . . . . . . . . . . >@? 02 BA CED FGD HCIJD FGD Zu jedem der beschriebenen Experimente werden aus Gründen der Übersichtlichkeit nur die von diesen Festlegungen abweichenden Parameter angegeben. 6.1.4 Diagramme Beschleunigung und Skalierung im Gesamtverfahren sind üblicherweise über viele Zeitschritte der Simulation gemittelte Größen, wodurch dem Umstand 6.1. HINWEISE 139 Rechnung getragen wird, daß Gitterweitenanpassung und Lastverteilung sporadisch über die Berechnung verteilt auftreten und ebenfalls neben dem numerischen Verfahren angemessen in der Messung zu berücksichtigen sind. Gerade deshalb lohnt es sich aber auch, Unterprogrammlaufzeiten für jeden Berechnungsschritt des numerischen Verfahrens zu messen und eventuell in einem Diagramm darzustellen. Falls die Algorithmen, deren anteilige Laufzeit betrachtet wird, einigermaßen geschickt gewählt sind, sollten die entsprechenden Messungen wesentlich reichhaltigere Informationen zur Bewertung und eventuellen Anpassung einzelner Komponenten oder Parameter des parallelen Simulationsprogramms liefern. Für jedes der nachfolgend beschriebenen Experimente wurde ein Laufzeitdiagramm angelegt und die folgende Legende gibt an, welche Größen gemessen und eventuell in der Darstellung miteinander verknüpft sind. Weiterhin findet sich dort auch die Bedeutung der im Diagramm aufgetragenen Werte und damit die Begründung, warum gerade dieser Wert interessant sein sollte. Zudem wird auf die wichtigsten Merkmale, die sich an den verschiedenen Kurven erkennen lassen, Bezug genommen. Die zentralen, sich wiederholenden Muster im Verlauf der Kurven, die z.B. über Häufigkeit, Kosten und Gewinn Elementanzahl, skaliert auf ca. 3/4 der Höhe des Diagramms Maximalwert und Mittelwert der Laufzeit für die Berechnung der numerischen Flüsse Laufzeit des gesamten synchronisierten Zeitschritts Aktivit ät der dynamischen Lastverteilung 30 Anzahl der Elemente, Maximum: 522262 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 2694 s 25 Sekunden 20 Beschleunigung der nachfolgenden Zeitschritte 15 10 5 0 300 350 Annäherung von Maximalwert und Mittelwert durch die Lastverteilung 400 Lfd. Nr. des Zeitschritts 450 500 Fluktuationen in der Laufzeit des gesamten Zeitschritts werden durch verschiedene Iterationstiefen im Algorithmus zur Gitterweitenanpassung hervorgerufen Abbildung 6.3: Beispieldiagramm mit den charakteristischen Merkmalen der Diagramme zu den verschiedenen Laufzeitmessungen. Dargestellt ist ein Ausschnitt aus einem Originaldatensatz. 140 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG der dynamischen Lastverteilung wichtige Hinweise geben, sind im Beispieldiagramm (vgl. Abb. 6.3) herausgestellt: Legende zu den Laufzeitdiagrammen: Die Anzahl der Elemente im gesamten Gitter, gemessen alle 16 Zeitschritte und dazwischen linear interpoliert. Dieser Wert ist mit einem passenden Faktor skaliert, um den Kurvenverlauf oberhalb der anderen Kurven zu erreichen. Der Maximalwert über alle Zeitschritte ist in der Legende angegeben. Bedeutung: Der Verlauf der Elementzahl ist als qualitativer Referenzwert für den Gesamtaufwand zu sehen (vgl. Kap. 4.6.1). Die Laufzeit, die für einen gesamten synchronisierten Zeitschritt im Simulationsverfahren benötigt wird. Sie ist definitionsgemäß identisch für alle Prozesse und summiert sich zur realen Gesamtausführungszeit der Anwendung (vgl. Kap. 6.1.1). Bedeutung: Der zusätzliche Zeitaufwand für eine dynamische Lastverteilung führt zu einer deutlich sichtbaren Nadel im Verlauf dieser Kurve, wie z.B. in der Mitte des Beispieldiagramms (vgl. Abb. 6.3). Danach sollte sich erwartungsgemäß die Laufzeit für die nachfolgenden Zeitschritte signifikant verkürzen. Für einen ausgewählten Teilalgorithmus des numerischen Verfahrens, der auf allen Teilgebieten völlig unabhängig ausgeführt wird, wird die Laufzeit für jeden Prozeß und Zeitschritt gemessen. Das Diagramm enthält den Maximalwert (rot) und Mittelwert (blau) über alle Prozesse für jeden Zeitschritt. Hierzu wird die Berechnung der numerischen Flüsse ausgewählt, die ca. 70% des Aufwands für das numerische Verfahren enthält und keine Kommunikationsvorgänge bedingt (vgl. Kap. 1.3). Bedeutung: Die Abweichung zwischen den zwei Werten liefert einen Anhaltspunkt für eine eventuell ungleiche Verteilung der Ausführungszeit, d.h. für einen ineffizienten Einsatz des Rechners. Die mittlere Ausführungszeit sollte auch in der Praxis (!) nur von Daten wie der Elementzahl und der Verfeinerungssituation abhängen. Der Zusammenhang zwischen einer Gleichverteilung der Elemente und der resultierenden Ausführungszeit ist nicht selbstverständlich, sondern kann herangezogen werden, um aus den Messungen heraus die Modellierung des Verfahrensaufwands durch die Elementzahl zu rechtfertigen (vgl. Kap. 4.6.1). Da der Algorithmus zur Gitterweitenanpassung von sehr vielen globalen Kommunikationsvorgängen durchzogen ist, wurde darauf verzichtet, auch dort die Korrelation zwischen Elementzahl und Ausführungszeit zu untersuchen. 6.1. HINWEISE 141 Im Beispieldiagramm findet sich unten rechts der Hinweis auf eine leichte Unregelmäßigkeit in der Laufzeit des gesamten Zeitschritts, die offenbar nicht vom numerischen Verfahren ausgeht. Sind die Impulse vergleichsweise klein, sollten sie auf die Gitterweitenanpassung zurückgeführt werden, die je nach Tiefe der Rekursion Teile des Algorithmus mehrfach iterieren muß (vgl. Kap. 4.5.1). 6.1.5 Visualisierte Strömungssimulation Auf dem beigefügten CD-ROM Datenträger (vgl. Anh. B) sind animierte grafische Darstellungen der Simulation abgelegt, die zwar noch keine quantitativen Belege für die Leistungsfähigkeit der Implementierung sind, aber zusätzliche Informationen für die Interpretation der Diagramme und Leistungsdaten in den folgenden Abschnitten enthalten. Aus technischen Gründen kann nicht jeder Zeitschritt einzeln gespeichert werden. Deshalb ist bis zur Zeit KMLON'PQ nur jeder fünfte Zeitschritt und danach nur jeder zehnte als Bild in der Animation vorhanden, wobei die Bildfrequenz entsprechend angepaßt ist. Die Einzelbilder wurden mit der Visualisierungsbibliothek GRAPE angefertigt [31, 33]. Lösungsfunktion (Dichte) Gitter, Teilgitter mit gleicher Farbe Anteilige Elementanzahl im Teilgitter Abbildung 6.4: Die visualisierte Strömumgssimulation stellt die wichtigsten Zusammenhänge grafisch dar: Oben die Dichtekomponente der Lösungsfunktion, darunter das adaptive Gitter, dessen Elemente nach Zugehörigkeit zu den Prozessen eingefärbt sind. Der Farbbalken stellt die Verteilung dar (vgl. Anh. A). 142 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG 6.1.6 Parallelrechnersystem Alle Testrechnungen wurden auf einem Parallelrechner vom Typ IBM RS/6000 SP am Rechenzentrum der Universität Karlsruhe durchgeführt. Wie im Kapitel zur Parallelisierung bereits hervorgehoben ist, handelt es sich bei der IBM SP um einen verbindungsorientierten Multicomputer, d.h. der Parallelrechner setzt sich aus einer großen Anzahl von Einprozessorsystemen zusammen, die über ein Verbindungsnetzwerk untereinander Daten austauschen können. Technische Daten: Jeder Knoten dieses Parallelrechners stellt ein nahezu eigenständiges Einprozessorsystem bestehend aus einem 120 bzw. 77 MHz Power2 Superscalar Prozessor und einem lokalen Hauptspeicher mit einer Kapazität von 512 bzw. 2.048 MBytes dar, vergleichbar mit einem sehr leistungsfähigen Arbeitsplatzrechner. Betriebsform: Der Betrieb ist auf kürzeste Verweilzeit ausgelegt: Zum einen stehen die angeforderten Knoten jeder Anwendung exklusiv zur Verfügung, andererseits wird auch das Verbindungsnetzwerk zwischen den zugeteilten Knoten exklusiv belegt. Das bedeutet, daß alle Zeitmessungen absolut unbeeinflußt von anderen Anwendungen und dem Betriebszustand weiterer, nicht der Anwendung zugeteilter Knoten sind. Eine Mittelung über mehrere Messungen ist deshalb nicht erforderlich. Es stellt sich heraus, daß die Zeitmessungen mit jedem weiteren Experiment sehr gut reproduziert werden. Beschränkungen: Betriebsbedingt ist die Laufzeit von Anwendungen auf vier Stunden beschränkt. Ebenso darf keine Anwendung mehr als 128 Knoten des Rechners reservieren. Für Rechnungen mit sehr großem Bedarf an Hauptspeicher stehen acht Knoten mit jeweils ca. zwei Gigabytes Kapazität zur Verfügung, allerdings nur mit den schwächeren 77 MHz Prozessoren. Messungen auf diesem Prozessortyp sind wiederum nur bis zu max. 32 Knoten möglich. An dieser Stelle sollte klar werden, daß nicht alle Meßreihen so aussehen können, wie sie theoretisch erwartet werden: Falls Basismessungen auf einem Knoten in der Meßreihe vorkommen, muß auf die Partition mit 77 MHz Knoten ausgewichen werden, um einen Knoten mit ausreichender Hauptspeicherkapazität vorzufinden. In dieser Partition stehen aber nur bis zu max. 32 Prozessoren zur Verfügung. Wird auf den Einprozessor-Referenzwert verzichtet, besteht die Möglichkeit auf der Produktionspartition auch mit bis zu 128 Prozessoren zu messen. Daher beginnen manche Meßreihen erst bei 10 bzw. 20 Prozessoren. 6.2. DYNAMISCHE LASTVERTEILUNG 143 6.2 Dynamische Lastverteilung Die Untersuchung des Verhaltens der dynamischen Lastverteilung ist ein zentrales Anliegen dieses Kapitels, weil die Technik, die dabei zur Anwendung kommt, weitgehend neu ist und durch die verwendete Strategie einerseits viel Potential für eine effiziente Implementierung bietet, andererseits aber auch gewisse Einschränkungen an die Vorgaben in der Problemstellung macht (vgl. Kap. 4.1.1). 6.2.1 Aktivität Zwei Diagramme mit allen Zeitschrittwerten für die gemessenen Laufzeiten vermitteln einen qualitativen Eindruck von der Aktivität der dynamischen Lastverteilung. Schon hier zeigt sich, warum der Anfangsphase der Berechnung Simulation: Forward-Facing-Step, 10 Teile, t=0.0 bis t=1.0, SP 120 MHz Knoten 40 Anzahl der Elemente, Maximum: 605037 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 28395 s 35 Sekunden 30 25 20 15 10 5 0 0 500 1000 Zeitschritt 1500 2000 Simulation: Forward-Facing-Step, 10 Teile, t=1.0 bis t=1.95, SP 120 MHz Knoten 40 Anzahl der Elemente, Maximum: 546713 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 33015 s 35 Sekunden 30 25 20 15 10 5 0 2500 3000 3500 Zeitschritt 4000 4500 Abbildung 6.5: Diagramm der Rechenzeiten für alle Zeitschritte des Basisproblems. Erkennbar ist die hohe Aktivität der dynamischen Lastverteilung am Anfang der Simulation. 144 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG später nochmals besondere Aufmerksamkeit gewidmet wird: Die durch den zusätzlichen Aufwand der Lastverteilung hervorgerufenen Nadeln in der Kurve der Gesamtlaufzeit des Zeitschritts sind gegenüber der Laufzeit des numerischen Verfahrens unverhältnismäßig groß, und treten exzessiv auf. Trotzdem sollte berücksichtigt werden, daß damit nur ein kleiner Teil der Gesamtlaufzeit verbunden ist. (Das Diagramm enthält fast 5.000 Zeitschritte). In weiten Teilen der Programmausführung findet man subjektiv ausgeglichene Verhältnisse vor. Die Endphase der Rechnung ist weniger interessant, weil dort langsam ein stationärer Zustand der numerischen Lösung und der Verfeinerungssituation erreicht wird (vgl. Kap. 6.1.2). Zusätzlich kann die zeitliche Entwicklung der Lösungsfunktion, des Gitters und der Verteilung der Grobgitterzellen anhand der animierten Visualisierung auf dem CD-ROM Datenträger verfolgt werden (vgl. Anhang B). 6.2.2 Aufwand und Nutzen Die dynamische Umverteilung der Elemente des Gitters während einer zeitabhängigen Berechnung mit lokaler Gitterweitenanpassung ist eine Spezialität“ ” des für Rechnerarchitekturen mit verteiltem Hauptspeicher entworfenen Programms und damit ein Zusatzaufwand, der weder mit der Simulationsaufgabe noch mit dem numerischen Verfahren in unmittelbarem Zusammenhang steht. Deshalb soll hier untersucht werden, ob dieser zusätzliche Aufwand gerechtfertigt ist, und zwar in dem Sinne, daß durch die Mittel der Lastverteilung die Gesamtausführungszeit tatsächlich verkürzt wird. Dazu werden drei Testsituationen betrachtet: Situation A An der ersten Testsituation soll untersucht werden, wie stark ausgehend von einem bestimmten Zeitpunkt während der Berechnung die bis dahin eingehaltene Lastgleichheit durch zeitabhängige Phänomene gestört wird, und wieviel Zeit demgegenüber in der Referenzsituation zur Wiederherstellung der Lastgleichheit aufzuwenden ist. Ausgewählt wird dazu eine Simulationsphase mit nahezu konstanter Elementzahl von ca. 550.000 Elementen, die durch die Gitterweitenanpassung im wesentlichen umverteilt werden. Es bietet sich die Berechnung der Strömung zwischen den Zeitpunkten KLRNPS und K;LETPN an, die bei den gegebenen Einstellungen 567 Zeitschritte benötigt. Die Messungen wurden mit und ohne dynamische Lastverteilung auf 10 Prozessoren durchgeführt. Die Elementzahl je Teilgitter U VWU X beträgt im ersten Fall maximal 110% vom Mittelwert. 6.2. DYNAMISCHE LASTVERTEILUNG 145 Ergebnisse: Die Diagramme (vgl. Abb. 6.6) zeigen, daß bis zum 250. Zeitschritt beide Rechnungen nahezu identisch verlaufen, danach aber im Referenzexperiment eine Umverteilung des Gitters vorgenommen wird. Im Experiment ohne Lastausgleich wird hier langsam eine ungleiche Verteilung der Laufzeiten des numerischen Verfahrens erkennbar, die sich bis zum Ende des Experiments auf ca. 63% erhöht. Die Referenzsituation weist lediglich eine maximale Laufzeitabweichung von 17 % auf. Ebenfalls deutlich ist die Überlegenheit der Berechnung mit dynamischer Lastverteilung, wenn die Gesamtlaufzeit betrachtet wird: Das Verfahren ohne Lastausgleich benötigt mit 8620 Sekunden etwa 13% mehr Laufzeit als das Referenzverfahren mit 7629 Sekunden. Forward-Facing-Step, 10 Teile, Keine Lastverteilung, t=0.8 bis t=1.0, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 547154 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 8620 s 30 Sekunden 25 20 15 10 5 0 0 100 200 300 Zeitschritt 400 500 Forward-Facing-Step, 10 Teile, 0.0 < Balance < 1.1, t=0.8 bis t=1.0, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 547154 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 7629 s 30 Sekunden 25 20 15 10 5 0 0 100 200 300 Zeitschritt 400 500 Abbildung 6.6: Diagramm zur Testsituation A: Die Berechnung wurde auf zehn Teilgebiete aufgeteilt und jeweils ohne dynamische Lastverteilung (oben) und mit dynamischer Lastverteilung (unten) durchgeführt. 146 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG Situation B Das zweite Testproblem untersucht die Auswirkung einer Skalierung des Problems, indem die Elementzahl im gesamten Gitter auf ca. 1.260.000 Elemente erhöht wird. Es handelt sich im wesentlichen um das große Testproblem zur Messung der Beschleunigung und Skalierung (vgl. Kap. 6.3). Bedingt durch die Problemgröße und den verkleinerten Zeitschritt konnten im Rahmen der für eine Anwendung zur Verfügung stehenden Zeit nur 224 Zeitschritte berechnet werden. Die Messungen wurden wie im vorangegangenen Fall jeweils mit und ohne dynamischen Lastausgleich durchgeführt, wobei die Parameter zur Steuerung der Lastverteilung aus dem Basisproblem übernommen sind. D.h. die zulässige Elementzahl je Teilgitter beträgt im Experiment mit Lastausgleich maximal bis zu 110% vom Mittelwert. Forward-Facing-Step, 20 Teile, Keine Lastverteilung, t=0.82 bis t=0.86, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 1258235 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 3281 s 30 Sekunden 25 20 15 10 5 0 0 50 100 Zeitschritt 150 200 Forward-Facing-Step, 20 Teile, 0.0 < Balance < 1.1, t=0.82 bis t=0.86, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 1259096 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 3161 s 30 Sekunden 25 20 15 10 5 0 0 50 100 Zeitschritt 150 200 Abbildung 6.7: Diagramm zur Testsituation B: Die Berechnung wurde auf 20 Teilgebiete aufgeteilt und jeweils ohne dynamische Lastverteilung (oben) und mit dynamischer Lastverteilung (unten) durchgeführt. 6.2. DYNAMISCHE LASTVERTEILUNG 147 Ergebnisse: Die Messung am großen Testproblem bestätigt die Ergebnisse des vorigen Abschnitts, allerdings weniger deutlich: Bedingt durch die kürzere Phase der Simulation zwischen K$LYN'PS und K$LYN'PSZ bewegt sich die Verfeinerungszone weniger signifikant und die Belastung der einzelnen Prozessoren bleibt gleichmäßiger. Das Verfahren ohne dynamischen Lastausgleich benötigt hier mit 3281 Sekunden nur etwa 4% mehr als das Verfahren mit dynamischem Lastausgleich. Die Ergebnisse dieser Messungen werden später noch zur Bestimmung der Skalierung des Programms herangezogen. Situation C Der qualitative Überblick über die Laufzeiten der Simulation (vgl. Kap. 6.2.1) zeigt zu Beginn der Berechnung eine sehr hohe Aktivität der dynamischen Lastverteilung. Weiterhin stellt sich heraus, daß die Verhältnisse von mittlerer und maximaler Laufzeit der Flußberechnung durch die Lastverteilung während der ersten 60 bis 100 Zeitschritte sogar verschlechtert werden; dennoch erfolgt in fast jedem Zeitschritt der Versuch, eine neue Aufteilung des Gitters vorzunehmen. Damit liegt ein starker Hinweis vor, daß in dieser singulären Situation mit sehr wenigen stark verfeinerten Elementen des Grobgitters eventuell eine Verbesserung erreicht werden kann, wenn entweder die Lastverteilung ausgesetzt oder das Kriterium für die zulässige Ungleichverteilung der Elementzahl (4.7) gelockert wird. Um diese Möglichkeiten zu untersuchen, werden der Referenzsituation mit einem Ausschnitt aus der Simulation des Basisproblems zwei modifizierte Verfahren gegenübergestellt. Die Einzelheiten sind: Experiment: 1 Referenzsituation aus dem Basisproblem mit einer zulässigen Elementzahl von maximal 110% des Partitionsmittelwerts. Die Referenzsituation wendet damit das schärfste Kriterium zur Steuerung der dynamischen Lastverteilung an, was in den Diagrammen (vgl. Abb. 6.8) an der kleinen Abweichung zwischen Maximal- und Mittelwert der Laufzeit der Flußberechnung zu erkennen ist. 2 Verändertes Kriterium für die dynamische Lastverteilung 4.7. Die zulässige Elementzahl beträgt hier maximal 130 % vom Mittelwert. Das Diagramm zeigt deutlich die Sägezahnstruktur, die durch die Drift in der Abweichung der maximalen Laufzeiten der Teilgebiete verursacht wird. 3 Für das dritte Experiment wird vorab eine Aufteilung des Grobgitters bestimmt und die dynamische Lastverteilung für die gesamte Berechnung ausgesetzt. Die Zerlegung des Grobgitters erfolgt entlang der Symmetrierichtung (y-Achse, vgl. Abb. 6.1), was aber nicht vollständig möglich 148 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG ist, weil das Grobgitter in dieser Raumrichtung nur acht Elementlagen aufweist. Die erkennbare Abweichung in den maximalen und mittleren Laufzeiten des numerischen Verfahrens ist auf diesen Umstand zurückzuführen. Bemerkung: Das Vorgehen im dritten Experiment ist sozusagen das Beste, was man tun kann, falls für das Simulationsproblem kein Verfahren mit dynamischer Lastverteilung zur Verfügung steht. Allerdings wird die relativ ausgeglichene Laufzeit durch große Schnittflächen im Gitter und damit durch einen [ hohen Kommunikationsaufwand erkauft (vgl. Kap. 4.6.1). Ergebnisse: Tabelle 6.1 und die Laufzeitdiagramme (vgl. Abb. 6.8) geben Anlaß zu den folgenden Beobachtungen: \ Für die Dauer der ersten 100 Zeitschritte ist das Verfahren ohne dynamische Lastverteilung deutlich im Vorteil. Es verursacht keinen zusätzlichen Aufwand und hat trotzdem eine verhältnismäßig ausgeglichene Laufzeitverteilung mit ca. 120% - 140% maximaler Abweichung vom Mittelwert. \ Zwischen dem 101. und dem 400. Zeitschritt bietet das Verfahren mit größerer Abweichung von der optimal verteilten Elementzahl die effizienteste Möglichkeit. \ Gegen Ende des Tests, also zwischen dem 401. und dem 847. Zeitschritt, wird langsam die Überlegenheit einer strikten Begrenzung der Schieflage in der Elementverteilung sichtbar: Das Referenzproblem liefert hier die kürzeste Laufzeit. Bemerkung: Als Nebeneffekt findet man mit den Messungen eine deutliche Bestätigung dafür, daß die gemittelten Zeitwerte der Flußberechnung ein gutes Maß für den Gesamtzeitaufwand für diesen Teil des numerischen Verfahrens sind: Die Linie der Mittelwerte verläuft identisch in allen drei Diagrammen, unabhängig von der Gesamtlaufzeit des Zeitschritts. [ Effizienz und Nutzen der dynamischen Lastverteilung Zeit [s] für die Zeitschritte von Experiment Summe 0 - 100 101 - 400 401 - 847 1 692 1825 5257 7774 2 329 1636 5422 7387 3 257 2295 6681 9233 Tabelle 6.1: Laufzeiten der drei Experimente zur dynamischen Lastverteilung aufgeschlüsselt nach drei Phasen. Die kürzeste Laufzeit ist jeweils hervorgehoben. 6.2. DYNAMISCHE LASTVERTEILUNG 149 Forward-Facing-Step, 10 Teile, 0.0 < Balance < 1.1, SP 120 MHz Knoten 40 Anzahl der Elemente, Maximum: 535261 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 7773 s 35 Sekunden 30 25 20 15 10 5 0 0 100 200 300 400 500 Zeitschritt 600 700 800 Forward-Facing-Step, 10 Teile, 0.0 < Balance < 1.3, SP 120 MHz Knoten 40 Anzahl der Elemente, Maximum: 527029 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 7386 s 35 Sekunden 30 25 20 15 10 5 0 0 100 200 300 400 500 Zeitschritt 600 700 800 Forward-Facing-Step, 10 Teile, statische Lastverteilung, SP 120 MHz Knoten 40 Anzahl der Elemente, Maximum: 532048 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 9232 s 35 Sekunden 30 25 20 15 10 5 0 0 100 200 300 400 500 Zeitschritt 600 700 800 Abbildung 6.8: Testsituation C: Oben als Referenzsituation das Diagramm zum Basisproblem bis t=0,3. In der Mitte eine Simulation mit größerer zulässiger Abweichung von der mittleren Elementzahl (starke Sägezahnstruktur). Unten eine Simulation ohne dynamische Lastverteilung, mit einer vorab bestimmten Zerlegung des Grobgitters. 150 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG 6.3 Beschleunigung und Skalierung Zur Messung der Beschleunigung des Gesamtverfahrens durch die Parallelisierung wird ein Zeitintervall der Simulation mit nahezu konstanter Elementzahl ausgewählt, das die für die Lastverteilung singulären Situationen am Anfang (hohe Aktivität) oder am Ende der Simulation (keine Aktivität) nicht enthält. 6.3.1 Vergleich mit dem seriellen Programm Tabelle 6.2 ermöglicht den Vergleich des parallelen Programms mit seiner sequentiellen Basiskomponente, die keinen zusätzlichen Aufwand zur Berech- Beschleunigungsmessung mit ca. 760.000 Elementen Beschleunigung gegenüber Anzahl Teilgitter / Prozessoren Laufzeit [s] Seriell 16663 1 1 19479 0,86 1,00 – 2 9913 1,68 1,96 1,8 - 2 3 6747 2,46 2,89 2,7 - 3 4 5323 3,13 3,66 3,6 - 4 5 4278 3,90 4,55 4,5 - 5 6 3646 4,57 5,34 5,5 - 6 7 3180 5,24 6,13 6,4 - 7 8 2784 5,98 7,00 7,3 - 8 10 2357 7,07 8,26 9,1 - 10 14 1771 9,41 11,00 12,8 - 14 20 1314 12,68 14,82 18,2 - 20 32 910 18,31 21,41 29,1 - 32 1. Zeile theoretisch erreichbar 2. Zeile – Vergleichsrechnung: Gleichmäßig feines Gitter, ca. 4,4 Mio. Elemente, keine Gitterweitenanpassung, keine dynamische Lastverteilung 32 2016 – Tabelle 6.2: Beschleunigung der Simulation durch Parallelverarbeitung ausgehend von einem Teilgebiet, d.h. einem eingesetzten Prozessor. Die rechnerischen Werte der Beschleunigung sind jeweils bezüglich der sequentiellen bzw. der parallelen Programmversion mit nur einem Teilgitter angegeben. 6.3. BESCHLEUNIGUNG UND SKALIERUNG 151 nung der Datenbasis der Lastverteilung und zur verteilten Verfeinerung enthält. Die vom parallelen Programm benötigte zusätzliche Laufzeit ergibt sich aus der ersten und zweiten Zeile zu ca. 17%. Ebenfalls eingetragen sind die Beschleunigungswerte gegenüber dem seriellen Programm bzw. gegenüber der parallelen Ausführung auf einem Teilgebiet für verschiedene parallele Anwendungen mit bis zu 32 Teilgebieten (Prozessoren). Die letzte Spalte enthält die durch die Grenzen der Lastverteilung vorgegebenen theoretischen Grenzen der Beschleunigung (vgl. Kap. 2.4.1). Der gemessene Wert sollte zwischen der Anzahl der Prozessoren und diesem Wert liegen, was für die Rechnungen mit bis zu vier Teilgebieten auch zutrifft. Die Experimente mit fünf bis 32 Prozessoren unterschreiten diese theoretische Schranke bereits. Zusätzlich enthält die Tabelle in der letzten Zeile die Werte einer Vergleichsrechnung, die auf einem global verfeinerten Gitter mit der Gitterweite des kleinsten Elementdurchmessers der adaptiven Berechnung durchgeführt wurde. Daraus resultiert eine um den Faktor 5,6 erhöhte Elementzahl (4,4 Mio. anstelle von 760.000). Die Laufzeit hat sich gegenüber der adaptiven Version offensichtlich mehr als verdoppelt (+ 120%), obwohl auf Gitterweitenanpassung und dynamische Lastverteilung verzichtet werden kann. Das liefert einen deutlichen Beleg für die Vorteile der Simulationsrechnung mit lokaler Gitterweitenanpassung, selbst wenn dadurch auf verteilt-parallelen Rechnersystemen ein echter Zusatzaufwand für die dynamische Lastverteilung nötig ist. Hinweis: Alle Testrechnungen wurden auf 77 MHz Knoten durchgeführt, die über eine große Hauptspeicherkapazität verfügen. Daraus resultiert verglichen [ mit den 120 MHz Knoten eine um ca. 52% längere Gesamtlaufzeit. 6.3.2 Kleines Testproblem Grundlage für das kleine Testproblem ist das Zeitintervall von K]L^N'PS bis K_L`TPaN aus dem Basisproblem (vgl. Kap. 6.1.3). Gestartet wird mit Daten aus Beschleunigungsmessung mit ca. 540.000 Elementen Beschleunigung gegenüber 1.Zeile Anzahl Teilgitter / Prozessoren Laufzeit [s] 10 7629 1 20 4693 1,63 1,8 - 2 40 3738 2,04 3,6 - 4 Meßwert theoretisch Tabelle 6.3: Berechnete Beschleunigung des Gesamtverfahrens aus den Meßwerten des kleinen Testproblems. 152 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG einer Berechnung mit zehn Teilgebieten, weshalb bei einer größeren Anzahl von Prozessoren im ersten Zeitschritt eine Lastverteilung erfolgt. Die Diagramme für 20 und 40 Prozessoren zeigen am Anfang eine Nadel in der Laufzeit, die auf diesen Umstand zurückgeht (vgl. Abb. 6.9). Ergebnisse: Die Daten für die Ausführungszeiten sind dem Laufzeitdiagramm (vgl. Abb. 6.9) und der Tabelle 6.3 zu entnehmen: Erkennbar ist in den Diagrammen eine erwartungsgemäß höhere der Aktivität der dynamischen Lastverteilung bei einer größeren Anzahl von Teilgebieten. Aus den gemessenen Daten für die Gesamtlaufzeit können die Werte der Beschleunigung bcd2defTN'PaZNg und bcd2defT=NP(h7Ng nach der Definition (2.1) berechnet werden. Auch hier sollte beachtet werden, daß die Beschleunigungswerte nur mit den Werten der durch (2.11) abgeschätzten theoretisch erreichbaren Beschleunigung verglichen werden, die im ungünstigsten Fall, d.h. konstante maximale Lastungleichverteilung während der gesamten Simulationsrechnung, deutlich reduzierte Werte annimmt. 6.3.3 Großes Testproblem Zur Bestimmung der Skalierbarkeit des Gesamtverfahrens wird die Beschleunigung noch für ein größeres Testproblem bestimmt. Um auch hier mit den Daten der Simulation zum Zeitpunkt K;LiNPaS starten zu können, werden die Parameter zur Steuerung der Gitterweitenanpassung so verändert, daß sich eine höhere Elementzahl ergeben hat. Alle Rechnungen starten aus einem Datensatz für 20 Teile, weshalb die Messungen für 40, 80 und 120 Teilgebiete auch hier eine entsprechende Nadel am Anfang aufweisen, die von der initialen Lastverteilung verursacht wird (vgl. Beschleunigungsmessung mit ca. 1.220.000 Elementen Beschleunigung gegenüber 1.Zeile Anzahl Teilgitter / Prozessoren Laufzeit [s] 20 3161 1 40 2007 1,58 1,8 - 2 80 1623 1,95 2,7 - 4 120 1502 2,10 4,0 - 6 Meßwert theoretisch Tabelle 6.4: Berechnete Beschleunigung des Gesamtverfahrens aus den Meßwerten des großen Testproblems. Im Fall der Aufteilung des Gitters auf 120 Prozessoren sinkt die Anzahl der Elemente pro Teilgitter bereits auf ca. 10.000 ab. 6.3. BESCHLEUNIGUNG UND SKALIERUNG 153 Abb. 6.10, 6.11). Zur Zeit der Messung bestand auf dem Parallelrechner am Rechenzentrum der Universität Karlsruhe eine Beschränkung von maximal 128 Prozessoren pro Anwendung, weshalb die Beschleunigungswerte nur für bis zu 120 Prozessoren vorliegen (anstelle von 160). Ergebnisse: Alle gemessenen Gesamtlaufzeiten sowie die Werte für die Beschleunigung der Anwendung bjcd2dekZNPhNg , bjcd2delZmNPaSN7g und bjcd2delZmNPT=ZNg sind abschließend in Tabelle 6.4 zusammengestellt. Daß die Werte für die Beschleunigung bei 120 und 80 Prozessoren weit vom anzunehmenden Grenzwert, der durch das Verhältnis der Prozessorzahlen (6 bzw. 4) vorgegeben ist, entfernt sind, sollte nicht zu negativ ausgelegt werden: Unter der Annahme, daß die Modellierung des Berechnungsaufwands exakt ist, findet man mit den Begründungen aus Kapitel 2.4, daß der durch die zulässige Abweichung vom Partitionsmittelwert der Elementzahl noch erreichbare Speedup bei ca. 4 bzw. 2,7 liegen kann. Die Diagramme auf den folgenden Seiten zeigen die Ausführungszeiten für die verschiedenen Messungen. Beobachtung: Die sieben Diagramme mit den Messungen der Zeitschrittlaufzeit für die Experimente zum Beschleunigungsverhalten legen den Schluß nahe, daß eine Ausführungszeit von ca. vier Sekunden pro Zeitschritt nicht unterschritten werden kann. Dies deutet sich schon bei der Untersuchung des seriellen Programms an: Dort findet man z.B. signifikante konstante Zeiten für die Erzeugung der Iterationsobjekte (vgl. Kap. 5.7) in jedem Zeitschritt der Si[ mulation. 154 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG Forward-Facing-Step, 10 Teile, 0.0 < Balance < 1.1, t=0.8 bis t=1.0, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 547154 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 7629 s 30 Sekunden 25 20 15 10 5 0 0 100 200 300 Zeitschritt 400 500 Forward-Facing-Step, 20 Teile, 0.0 < Balance < 1.1, t=0.8 bis t=1.0, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 545236 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 4693 s 30 Sekunden 25 20 15 10 5 0 0 100 200 300 Zeitschritt 400 500 Forward-Facing-Step, 40 Teile, 0.0 < Balance < 1.1, t=0.8 bis t=1.0, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 546727 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 3738 s 30 Sekunden 25 20 15 10 5 0 0 100 200 300 Zeitschritt 400 500 Abbildung 6.9: Diagramme zur Messung der Beschleunigung am kleinen Testproblem, 20, 40 und 80 Teilgebiete. Die zulässige Elementzahl in der Partition beträgt max. 110% vom Mittelwert. Deutlich zu erkennen ist die zunehmende Aktivität der dynamischen Lastverteilung mit ansteigender Anzahl von Teilgebieten (vgl. Abb. 6.10). 6.3. BESCHLEUNIGUNG UND SKALIERUNG 155 Forward-Facing-Step, 20 Teile, 0.0 < Balance < 1.1, t=0.82 bis t=0.86, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 1259096 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 3161 s 30 Sekunden 25 20 15 10 5 0 0 50 100 Zeitschritt 150 200 Forward-Facing-Step, 40 Teile, 0.0 < Balance < 1.3, t=0.82 bis t=0.86, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 1258235 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 2007 s 30 Sekunden 25 20 15 10 5 0 0 50 100 Zeitschritt 150 200 Forward-Facing-Step, 80 Teile, 0.0 < Balance < 1.5, t=0.82 bis t=0.86, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 1258235 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 1623 s 30 Sekunden 25 20 15 10 5 0 0 50 100 Zeitschritt 150 200 Abbildung 6.10: Diagramme zur Messung der Beschleunigung am großen Testproblem auf 20, 40 und 80 Teilgebieten. Die Zulässige Elementzahl in der Partition beträgt max. 110% (oben), 120 % (Mitte) bzw. 150% (unten) vom Mittelwert. Dadurch wird eine übermäßige Aktivität der dynamischen Lastverteilung vermieden (vgl. Abb. 6.9). 156 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG 6.3.4 Skalierung Die Skalierbarkeit kann für die vorliegende Problemstellung nicht mit der durch die Definition (2.4) möglichen Präzision bestimmt werden, weil es dazu nötig wäre, auf eine Messung am seriellen Verfahren zurückzugehen, um das skalierte Problem festzulegen. Der Datenumfang läßt dies hier aber nicht zu. Deshalb wurde das im Sinne der Definition skalierte Problem durch ein Problem mit skalierter Elementzahl ersetzt. Aber selbst unter dieser vereinfachenden Annahme stößt man auf weitere Schwierigkeiten: Da es nicht möglich ist, a-priori die Schranken (1.27) für das Verfeinerungskriterium so einzustellen, daß sich eine bestimmte Elementzahl ergibt, muß mit signifikanten Abweichungen der Elementzahl vom gewünschten Wert umgegangen werden. Außerdem ist zu berücksichtigen, daß die Skalierungsmessung nur das Skalierungsverhalten auf dem Niveau der Zeitschrittschleife mißt. Das nichtskalierbare Verhalten des verwendeten expliziten Finite Volumen Verfahrens, das aus der CFL-Bedingung an die Zeitschrittweite (1.24) resultiert, wird von den hier berechneten Werten nicht wiedergegeben. Die Meßwerte, die in die Definition der Skalierung (2.4) eingesetzt werden, stammen aus den Beschleunigungsmessungen am großen und am kleinen Testproblem (vgl. Kap. 6.3). Tabelle 6.5 enthält im oberen Teil die gemittelte Elementzahl während der adaptiven Berechnung (Spalte 2) und die mittlere Dauer eines Zeitschritts (Spalte 3) jeweils für das kleine und das große Testproblem. Im unteren Teil der Tabelle sind die drei möglichen Kombinationen für einen Faktor-2-Skalierungswert no d2cqp ekZPrsg angegeben. Forward-Facing-Step, 120 Teile, 0.0 < Balance < 1.5, t=0.82 bis t=0.86, SP 120 MHz Knoten 35 Anzahl der Elemente, Maximum: 1258235 Laufzeit num. Fluss Mittelwert Laufzeit num. Fluss max. Wert Ges. Zeitschritt, Summe: 1502 s 30 Sekunden 25 20 15 10 5 0 0 50 100 Zeitschritt 150 200 Abbildung 6.11: Diagramm 4 zur Messung der Beschleunigung am großen Testproblem, 120 Teilgebiete. Die zulässige Elementzahl in der Partition beträgt max. 150% vom Mittelwert. 6.4. BEWERTUNG DER ERGEBNISSE 157 Beobachtung: Offensichtlich fallen die Skalierungswerte in allen drei Fällen sehr gut aus, theoretisch kann bei exakter Anwendung der Definition bestenfalls ein Wert von 1,0 erreicht werden (vgl. Kap. 2.4). Darüber hinaus wird die Elementzahl in allen Kombinationen mehr als verdoppelt, erwartungsgemäß sollte der Skalierungswert dadurch verkleinert werden. Die Gründe dafür sind nicht ganz durchsichtig: Zum einen arbeitet das Simulationsprogramm bei gleicher Elementzahl schneller, falls das initiale Grobgitter weniger Zellen enthält, dafür aber stärker verfeinert wurde (Datenstrukturierung), andererseits greift die Skalierung der Elementzahl eventuell nicht exakt am Berechnungsaufwand an, wie es von der Definition (2.4) verlangt wird. 6.4 Bewertung der Ergebnisse 6.4.1 Dynamische Lastverteilung \ Grundsätzlich zeigt sich, daß eine adaptive Berechnung mit stark zeitabhängiger Lösungsfunktion ohne dynamische Lastverteilung nicht Berechnung der Skalierung Mittelwert von Anzahl Teilgitter / Prozessoren Elementzahl Zeitschrittdauer [s] 10 542.056 13,43 20 540.675 8,26 40 539.775 6,58 20 1.220.364 14.05 40 1.219.210 8.92 80 1.219.050 7.22 Kombination / Definition Verhältnis von Elementzahl Zeitschrittdauer 10 ➝ 20 t=ulvlw/xky-zm{q|q}~ 2,25 0.96 20 ➝ 40 t ulvlw/x y-zm{(z}~ 2,25 0.93 40 ➝ 80 t ulvlw/x y-zm{2=}~ 2,26 0.99 Tabelle 6.5: Kombination der Meßwerte am kleinen (Zeile 1-3) und großen (Zeile 4-6) Testproblem zur Bestimmung der Skalierbarkeit des Programms bezüglich der Zeitschrittschleife. Es können die Werte für t ulvlw/x y-zm{~{|q}{z}m{f} bestimmt werden. 158 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG effizient durchgeführt werden kann, was auch die Ergebnisse aus anderen Arbeiten zu vergleichbaren Themen bestätigt [5, 22]: Die Abweichungen in der Belastung des Parallelrechners sind schon bei kurzen Simulationen signifikant und wirken sich in praktisch jedem Fall ungünstig auf die Gesamtlaufzeit aus (vgl. Kap. 6.2.2). \ Während Berechnungsphasen mit extrem niedriger Elementzahl sollte auf häufige Umverteilung des Gitters verzichtet werden. Dies wirkt sich auch günstig auf die Laufzeit des Verfeinerungsalgorithmus aus, der in einem großvolumig verteilten Gitter schneller arbeitet, weil nicht so häufig Gebietsgrenzen während der Balancierung überschritten werden (vgl. Kap. 4.5). Als grober Anhaltswert sollte dabei gelten, daß ein Teilgitter entweder mindestens 10.000 Zellen enthält oder leer bleibt. Zu Beginn einer vergleichbaren Simulation (d.h. ca. 8.000 Elemente im ersten Zeitschritt) würde man also nur ein Teilgebiet mit allen Elementen belegen und dann mit ansteigender Elementzahl immer weitere auffüllen. \ Zusätzlich ist ein (zumindest heuristisches) Kriterium zur Festlegung der Schranken für die Steuerung der dynamischen Lastverteilung zuzufügen, damit eine möglichst kurze (optimale) Simulationsdauer ohne Vorkenntnisse des Anwenders realisiert wird. Alle Meßwerte, die in diesem Abschnitt zur Bewertung a-posteriori verwendet werden, stehen dem parallelen Programm schließlich schon zur Laufzeit zur Verfügung, auf dieser Basis sollte sich das Problem befriedigend lösen lassen. \ Es bedarf noch einer Überprüfung des gesamten Programms auf reduzierbare konstante Ausführungszeiten im Berechnungsschritt. Diese Zeiten sind nicht parallelisierbar und geben deshalb eine untere Schranke für die Ausführungsdauer eines Zeitschritts im numerischen Verfahren vor, denn infolge der CFL-Bedingung (1.24) müssen bei gleicher Problemstellung auf einem feineren Gitter (kleinerer Diskretisierungsfehler) mehr Zeitschritte berechnet werden. Eine über viele Skalen der Problemgröße konstante Gesamtausführungszeit (optimale Skalierung des Gesamtproblems) kann nur erreicht werden, wenn die oben beschriebenen konstanten Ausführungszeiten pro Zeitschritt möglichst klein sind. 6.4.2 Beschleunigung Die Beschleunigung wurde in zwei Testfällen ausgehend von einer dynamischen Aufteilung des Gitters in 10 bzw. 20 Teile gemessen. Dabei lag die rechnerische Effizienz (2.3) zwischen 0,5 (50%) und 0,98 (98%). Obwohl diese Werte schon recht gut sind, sollte berücksichtigt werden, daß mit dem gewählten numerischen Verfahren vergleichsweise wenig Berechnungsaufwand verbunden ist. 6.4. BEWERTUNG DER ERGEBNISSE 159 Ebenso großzügig ist die Anpassung der Gitterweite vor jedem Zeitschritt des numerischen Verfahrens - üblicherweise wird hier auf einfachere Lösungen ausgewichen. Andererseits zeigt sich an dieser Stelle, wie wenig die Leistung des Verfeinerungs- bzw. Vergröberungsalgorithmus durch die Erweiterung auf ein verteiltes Gitter degradiert wird. Gerade diese beiden Teile der Gitterweitenanpassung sind anerkanntermaßen harte Punkte in einem Parallelisierungsvorhaben, weil rekursive Algorithmen, die sequentiell sehr einfach und schnell arbeiten, durch iteratives Vorgehen mit globaler Kommunikation ersetzt werden müssen (vgl. Kap. 4.5) [22]. 6.4.3 Skalierung Die Skalierbarkeit des parallelen Simulationsprogramms kann aus technischen Gründen nicht mit der durch die Definition (2.4) möglichen Schärfe bestimmt werden, weil kein Parameter der Simulation existiert, durch dessen Veränderung die Laufzeit auf einem Einprozessorsystem direkt festgelegt werden kann. Selbst die Gesamtelementzahl im Gitter hängt nur indirekt von den Schranken des Verfeinerungskriteriums (1.27) ab. Im untersuchten Bereich, d.h. für Elementzahlen zwischen 540.000 und 1,3 Mio. wird der lokale Ressourcenbedarf nur von den anteiligen Elementzahlen im jeweiligen Teilgitter bestimmt. Dies gilt für den Hauptspeicherbedarf während der Gitterweitenanpassung und Lastverteilung ebenso, wie für den Zeitaufwand. Hierbei ist zu beachten, daß die Berechnung der Partitionierung des Gitters nur von der Anzahl der Grobgitterelemente abhängt und deshalb im Skalierungsexperiment konstant ist. Darin dürfte auch der Grund zu sehen sein, warum die Skalierungswerte wesentlich besser ausfallen als die Beschleunigungswerte, die für große Prozessorzahlen sehr empfindlich gegen konstante, also nicht parallelisierte Anteile der Ausführungszeit sind (Amdahl's Law/Gustafson's Law) [15]. 6.4.4 Zusammenfassung Auf der Grundlage des vorgeschlagenen Entwurfs kann nachweislich ein verteilt paralleles Simulationsprogramm implementiert werden, das in Messungen unter realistischen Voraussetzungen bereits in seiner ersten Version gute Resultate zeigt. Die Strategie, verschiedene Skalen in die Problemstellung einzuführen und für die verteilte Gitterverwaltung nutzbar zu machen, hat sich als lohnend herausgestellt. Im Identifikationsalgorithmus, in der verteilten Gitterweitenanpassung und im Modul zur dynamischen Lastverteilung können nahezu alle Schwierigkeiten bereits auf dem Grobgitter behandelt werden. 160 KAPITEL 6. TESTBEISPIELE, MESSUNGEN UND BEWERTUNG Daraus resultiert die gute Effizienz dieser Zusatzfunktionen, deren Aufwand in ausgeglichenem Verhältnis zum dem des numerischen Verfahrens steht: Die Umverteilung des Gitters benötigt nur die Zeit eines zusätzlichen Berechnungsschritts der numerischen Simulation. Zusammenfassend bleibt festzuhalten, daß die Komponenten, die den Basisentwurf zu einer parallelen Gitterverwaltung für Rechner mit verteiltem Hauptspeicher ausdehnen, weder den Programmentwurf noch das Laufzeitverhalten des danach realisierten Simulationsprogramms dominieren, sie nehmen vielmehr genau den Raum ein, der ihnen bei realistischen Vorgaben an Komplexität und Effizienz eingeräumt werden sollte: Der Nutzen des beschriebenen Programmentwurfs besteht darin, der Integration der konkreten geometrischen und mathematischen Strukturen im Simulationsprogramm den Vorrang gegenüber technischen Detaillösungen eingeräumt zu haben; die vorliegende Implementierung beweist, daß dies auch bei guter Gesamtleistungsfähigkeit möglich ist. 161 Anhang A Abbildungen Abbildung A.1: Ausschnitt aus der Strömungssimulation zum Startzeitpunkt. 162 ANHANG A. ABBILDUNGEN Abbildung A.2: Ausschnitt aus der Strömungssimulation zum Zeitpunkt t=0,3 Abbildung A.3: Ausschnitt aus der Strömungssimulation zum Zeitpunkt t=0,6 163 Abbildung A.4: Ausschnitt aus der Strömungssimulation zum Zeitpunkt t=0,8 Abbildung A.5: Ausschnitt aus der Strömungssimulation zum Zeitpunkt t=1,0 164 ANHANG A. ABBILDUNGEN Abbildung A.6: Ausschnitt aus der Strömungssimulation zum Zeitpunkt t=1,2 Abbildung A.7: Ausschnitt aus der Strömungssimulation zum Zeitpunkt t=1,4 165 Abbildung A.8: Ausschnitt aus der Strömungssimulation zum Zeitpunkt t=1,66 166 ANHANG A. ABBILDUNGEN 167 Anhang B CD-ROM Datenträger Quelldateien, Versionen Im Verzeichnis /RCS auf dem CD-ROM Datenträger sind die Quelldateien enthalten. Das Programm wurde unter Zuhilfenahme des Revision Control Systems (RCS) [38] entwickelt, wodurch sich die Möglichkeit ergibt, einheitlich auf verschiedene Versionen des Programms zugreifen zu können (vgl. Abb. B.1): \ Die Referenzversion, also die Version, mit der sämtliche Ergebnisse der vorliegenden Arbeit erzielt worden sind, kann unter der Versionsnummer 1.100 (bzw. identisch 1.100.1.1) aus den Dateien entnommen werden. Diese Version dient als Beleg für die vorgestellten Ergebnisse. \ An der Stelle der Referenzversion wurde ein Zweig zur Versionspflege angelegt, der jedoch keine inhaltlichen Weiterentwicklungen enthält (Versionen 1.100.1.x). \ Der Hauptzweig enthält inhaltliche Weiterentwicklungen in den Versionen nach der Revisionsnummer 2.1. Die am weitesten entwickelte Version bietet zusätzlich zur Referenzversion (Version 1.100): + Weitere Kommentare und ergänzende Erläuterungen in den Quelldateien. + Ein eigenständiges Tetraederkonzept mit isotropen Verfeinerungsregeln in Analogie zum bestehenden Hexaedergitter. + Überarbeitete Schnittstellen zu den Partitionierungsverfahren aus PARTY 1.1 [30] und Metis 3.0 19 . Hinweis: Das Tetraederkonzept fügt dem ursprünglichen Entwurf, der ausschließlich Hexaederelemente kennt, Tetraeder, Dreiecksflächen und Dreiecksrandelemente mit identischem Funktionsinhalt, d.h. einem angepaßten nume[ rischen Verfahren für die kompressiblen Eulergleichungen, hinzu. 168 ANHANG B. CD-ROM DATENTRÄGER Standard Template Library: Die Version der Standard Template Library (STL) [27] aus dem Jahr 1997 kann im Verzeichnis /stl eingesehen werden. Die ANSI Standardisierung der Programmiersprache C++ hat zu einigen kleineren Änderungen, insbesondere bei den Dateinamen, geführt, die zu berücksichtigen sind, falls die Programme mit einem ANSI konformen C++ Compiler übersetzt werden sollen. Partitionierungsbibliotheken Die Berechnungen zu den vorgestellten Ergebnissen wurden unter Verwendung der Partitionierungsbibliothek PARTY 1.1 [30] durchgeführt (vgl. Kap. 6). Die Urheberrechte für dieses Softwareprodukt liegen bei der Universität Paderborn. Eine vergleichbare Bibliothek, die ohne Lizensierungsverfahren frei verfügbar ist, liegt mit Metis 3.0 [19] vor, weshalb die Schnittstellen zu dieser Bibliothek in die erweiterten Versionen des Zweigs 2.x integriert sind. Visualisierte Strömungssimulation Die Dateien mit der animierten Darstellung der Strömungssimulation (vgl. Kap. 6.1.5) befinden sich im Verzeichnis /movie . Es handelt sich um MPEG1 bzw. QuicktimeTM (Apple) codierte Movies mit einer Auflösung von 728 x 546 bzw. 1152 x 864. Zweig zur Weiterentwicklung Zweig zur Versionspflege Version 2.x Version 1.100.1.x Version 2.1 Referenzversion Vorversionen Version 1.100 Version 1.100.1.1 Version 1.x Abbildung B.1: Zweige und Versionen des parallelen Simulationsprogramms. 169 Verschiedenes Das Verzeichnis /misc enthält weitere Dateien, die zum Test des Simulationsprogramms nötig sind, wie z.B. Gitter- und Parameterdateien. Urheberrechte Keine Einschränkungen. 170 ANHANG B. CD-ROM DATENTRÄGER 171 Anhang C Index der Quelldateien Datei Seite ball.cc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 ball pll.cc . . . . . . . . . . . . . . . . . . . . . . . . . .132 euler.cc . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 euler.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 gitter euler impl.cc . . . . . . . . . . . 118, 119 gitter euler impl.h . . . . . . . . . . . . . . . . . 119 gitter euler pll impl.cc . . . 118, 120, 123 gitter euler pll impl.h . . . . . . . . . 119, 125 gitter geo.cc . . . . . . . . . . . . . . . . . .110, 117 gitter hexa top.h . . . . . . . . . . . . . 111, 112 gitter hexa top pll.h . . . . . . . . . . . . . . . 116 gitter impl.h . . . . . . . . . . . . . 110, 111, 112 gitter mgb.cc . . . . . . . . . . . . . . . . . 110, 117 gitter mgb.h . . . . . . . . . . . . . 110, 117, 124 gitter pll idn.cc . . . . . . . . . . . . . . . . . . . . 116 gitter pll impl.cc . . . . . . . . . 116, 123, 125 gitter pll impl.h . . . . . . . . . . 116, 123, 125 gitter pll ldb.cc . . . . . . . . . . . . . . . 125, 126 gitter pll ldb.h . . . . . . . . . . . . . . . . . . . . . 125 gitter pll mgb.cc . . . . . . . . . . . . . . . . . . . 124 gitter pll sti.cc . . . . . . 115, 118, 123, 124 gitter pll sti.h . . . . . . . 115, 122, 124, 128 gitter sti.cc . . . . . . . . . . . . . . 110, 117, 128 gitter sti.h . . . . . . . . . . . . . . . 110, 117, 128 key.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 main euler.cc . . . . . . . . . . . . . . . . . . . . . 132 main euler pll.cc . . . . . . . . . . . . . . . . . . 132 makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 mapp cube 3d.cc . . . . . . . . . . . . . . . . . 120 mapp cube 3d.h . . . . . . . . . . . . . . . . . . 120 mpAccess.cc . . . . . . . . . . . . . . . . . . . . . . 131 mpAccess.h . . . . . . . . . . . . . . . . . . . . . . . 130 mpAccess MPI.cc . . . . . . . . . . . . . . . . . 131 mpAccess MPI.h . . . . . . . . . . . . . . . . . . 131 myalloc.cc . . . . . . . . . . . . . . . . . . . . . . . . .132 myalloc.h . . . . . . . . . . . . . . . . . . . . . . . . . .132 parallel.h . . . . . . . . . . . . . . . . . . . . . . . . . . 115 serialize.h . . . . . . . . . . . . . . . . . . . . . . . . . 130 swflux.cc . . . . . . . . . . . . . . . . . . . . . . . . . . 119 walk.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 172 ANHANG C. INDEX DER QUELLDATEIEN 173 Literaturverzeichnis [1] A. Aho, J. Hopcroft, J. Ullman: Data Struktures and Algorithms; AddisonWesley (1987) [2] A. Aho, J. Hopcroft, J. Ullman: The Design and Analysis of Computer Algorithms; Addison-Wesley (1974) [3] C. Badura: Implementation einer vorkonditionierten hp-Version der Finiten Elemente Methode in 3D; Diplomarbeit, Universität Freiburg (1999) [4] H. Balzert: Objektorientierte Systemanalyse; Spektrum Akademischer Verlag (1996) [5] P. Bastian: Parallele adaptive Mehrgitterverfahren; Teubner Stuttgart (1996) http://dom.ica3.uni-stuttgart.de/ug/ [6] K. Birken: A Dynamic Data Model for Parallel Adaptive PDE Solvers; Proc. of HPCN Europe (1995) [7] G. Booch, J. Rumbaugh, J. Jacobson: The Unified Modeling Language User Guide; The Rational Software Corp., Addison-Wesley Longman (1998) [8] B. Cockburn, C.-W. Shu: TVB Runge-Kutta Local Projection Discontinuous-Galerkin Finite Element Method For Conservation Laws II: General Framework Mathematics of Computation, Vol.52 (1989) [9] B. Engquist, S. Osher: One - sided Difference Approximations for nonlinear Conservation Laws; Math. Comput. 36 (1981) [10] I. Foster: Designing and Building Parallel Programs; Addison-Wesley (1995), http://www.mcs.anl.gov/dbpp/ [11] M. Fowler: Applying the Standard Object Modeling Language; AddisonWesley Longman (1997) [12] E. Gamma, R. Helm, R. Johnson, J. Vlissides: Design Patterns; AddisonWesley (1995) 174 LITERATURVERZEICHNIS [13] M. Garey, D. Johnson, L. Stockmeyer: Some simplified np-complete graph problems; Theoretical Computer Science (1976) [14] T. Gessner, D. Kröner, B. Schupp, M. Wierse: Finite volume methods for conservation laws and convection dominated diffusion equations; Preprint Universität Freiburg (1996) [15] A. Geiger: Parallelrechner Architektur und Anwendung; Forschungs- und Entwicklungsbericht RUS-19 ISSN 0941-4665 RUS (1995) [16] E. Godlewski, P.-A. Raviart: Numerical Approximation of Hyperbolic Systems of Conservation Laws; Appl. Math. Sc. 118, Springer (1996) [17] C. S. Horstmann, G. Cornell: Core Java 1.1 Vol. II - Advanced Features; Prentice-Hall Computer Books (1997) [18] R.M. Karp, V. Ramachandran: A Survey of parallel Algorithms for Shared Memory Machines; Handbook of Theor. Comp. Science North Holland (1990) [19] G. Karypis, V. Kumar: Metis, A Software Package for Unstructured Partitioning Graphs, Unstructured Meshes, and Computing Fill-Reducing Orderings of Sparse Matrices, Version 3.0.3; Univ. of Minnessota (1997) http://www.cs.umn.edu/k arypis/metis/main.html [20] B. W. Kernighan, S. Lin: An effective heuristic procedure for partitioning graphs; The Bell Systems Technical Journal (1970), 291-308 [21] B. W. Kernighan, D. M. Ritchie: The C Programming Language, Second Edition, ANSI C; Prentice-Hall (1988), 256 [22] R. Kleinrensing: Ein adaptives paralleles Finite-Volumen-Verfahren; Diplomarbeit Universität Bonn (1994) [23] D. Kröner: Numerical Schemes for Conservation Laws; Wiley & Teubner, Stuttgart (1997) [24] D. Kröner, M. Ohlberger: A posteriori Error Estimates for Upwind Finite Volume Schemes for nonlinear Conservation Laws in Multi Dimensions; Preprint 02-98, Universität Freiburg (1998) [25] D. Kröner, M. Rokyta: Convergence of Upwind Finite Volume Schemes for Scalar Conservation Laws in 2D; SIAM J. Num. Anal., Vol.31, No. 2 (1994) [26] Message Passing Interface Forum: MPI: A Message Passing Interface Standard; University of Tennesse (1993,1994) [27] D. R. Musser, A. Saini: STL Tutorial and Reference Guide; AddisonWesley (1996) LITERATURVERZEICHNIS 175 [28] E. F. Van de Velde: Concurrent Scientific Computing; Springer New York (1994) [29] B. Stroustrup: Die C++ Programmiersprache; Addison-Wesley (1992) [30] R. Preis, R. Diekmann: The PARTY Partitioning-Library User Guide – Version 1.1; Preprint, Universität-GH Paderborn (1996) [31] M. Rumpf,A. Schmidt: GRAPE, GRAphics Programming Environment; Report Nr. 8 SFB 256, Universität Bonn (1990) [32] M. Rumpf, A. Schmidt, K. G. Siebert: Functions Defining Arbitrary Meshes Report Nr. 14, SFB 256, Universität Bonn (1994) [33] M. Rumpf, B. Schupp: Visualization of parallel data based on procedural access; Proceedings in Visualization and Mathematics (1997) [34] J. L. Steger, R. F. Warming: Flux Vector Splitting of the Inviscid Gasdynamic Equations with Application to Finite Difference Methods; Journal of Comp. Physics 40 (1981) [35] A. Stroud: Approximate calculation of multiple integrals; Eaglewood-Cliffs (1971) [36] R. Schwörer: Entwicklung und Parallelisierung von Finite-VolumenVerfahren zur Lösung der kompressiblen Navier-Stokes-Gleichungen in 2-D; Diplomarbeit Universität Freiburg (1997) [37] A. S. Tanenbaum: Distributed Operating Systems; Prentice-Hall (1995) [38] W. F. Tichy: RCS - A System for Version Control; Software-Practice & Experience 15 (1985) [39] L. G. Valiant: A Bridging Model for Parallel Computation; Comm. of the ACM (1996) Vol. 33 [40] L. Volkmann: Graphen und Digraphen: Eine Einführung in die Graphentheorie; Springer Wien New York (1991) [41] R. F. Warming, R. M. Beam, B. J. Hyett: Diagonalization and Simultaneous Symmetrization of the Gas Dynamic Matrices; Math. of Comp. 29 (1997) [42] M. Wierse: Higher Order Upwind Schemes on Unstructured Grids for the Compressible Euler Equations in Timedependent Geometries in 3D; Preprint Universität Bonn (1995) Nr. 393 [43] P. R. Woodward, P. Colella: The Numerical Simulation of Two-Dimensional Flow with Strong Shocks; Journal of Computational Physics 54 (1984), 115-173