Konzeption und Realisierung eines zeitgemäßen

Konzeption und Realisierung eines zeitgemäßen
Konzeption und Realisierung
eines zeitgemäßen Programmsystems
zur allgemeinen Tragwerksanalyse
Diplomarbeit
Kathrin Telkamp
1. Prüfer: Prof. Dr.–Ing. Uwe Starossek
Matr.-Nr.: 9952
2. Prüfer: Dipl.-Ing. Lydia Thiesemann
Arbeitsbereich Statik und Dynamik der Baukonstruktionen
Studiengang Bauingenieurwesen und Umweltschutztechnik
Technische Universität Hamburg-Harburg
Hamburg, September 2001
Vorwort
Diese Diplomarbeit mit dem Titel „Konzeption und Realisierung eines zeitgemäßen
Programmsystems zur allgemeinen Tragwerksanalyse“ wurde im Fachbereich Statik und
Dynamik der Baukonstruktionen an der Technischen Universität Hamburg-Harburg im
Rahmen des Studienganges Bauingenieurwesen angefertigt.
Bei der Ausarbeitung wurde ich betreut von Prof. Dr.-Ing Uwe Starossek und Dipl.Ing. Lydia Thiesemann, für deren Unterstützung ich mich an dieser Stelle herzlich
bedanken möchte. Weiterhin gilt mein Dank allen, die meine Arbeit Korrektur gelesen
haben und mir auch sonst auf alle erdenklichen Arten geholfen haben.
Verzeichnisse
I
Inhaltsverzeichnis
ABBILDUNGSVERZEICHNIS.......................................................................................III
TABELLENVERZEICHNIS ...........................................................................................IV
SYMBOLVERZEICHNIS................................................................................................. V
1
EINLEITUNG.............................................................................................................. 1
2
GRUNDLAGEN DER FINITE-ELEMENTE-METHODE.................................... 3
2.1
Allgemeine Formulierung ....................................................................................... 3
2.1.1
Lineare statische Berechnung............................................................................ 3
2.1.2
Kinetische Berechnung...................................................................................... 7
2.1.3
Nichtlineare Berechnungen ............................................................................... 8
2.1.3.1 Theorie 2. Ordnung ................................................................................. 10
2.1.3.2 Physikalisch nichtlineare Berechnung..................................................... 12
2.2
3
Das Weggrößenverfahren für ein Stabwerk ....................................................... 12
SOFTWARE-ENTWURF ........................................................................................ 20
3.1
Verschiedene Entwurfsverfahren......................................................................... 20
3.1.1
Streng hierarchisch strukturiertes Design (prozedural) ................................... 20
3.1.2
Datenorientiertes Design (funktional) ............................................................. 21
3.1.3
Objektorientiertes Design ................................................................................ 21
3.2
4
Vergleich und Auswertung ................................................................................... 22
OBJEKTORIENTIERTE ANALYSE UND DESIGN........................................... 27
4.1
Unified Modeling Language (UML)..................................................................... 27
4.1.1
Ziele der UML ................................................................................................. 27
4.1.2
Bestandteile der UML ..................................................................................... 28
4.2
Konzepte und Definitionen der objektorientierten Programmierung.............. 33
4.2.1
Basisdefinitionen ............................................................................................. 34
4.2.1.1 Objekt ...................................................................................................... 34
4.2.1.2 Klasse ...................................................................................................... 35
4.2.1.3 Methoden................................................................................................. 35
4.2.1.4 Attribute................................................................................................... 36
4.2.2
Datenabstraktion.............................................................................................. 36
4.2.3
Kapselung ........................................................................................................ 37
4.2.4
Modularität ...................................................................................................... 38
4.2.5
Hierarchie (Relationen) ................................................................................... 38
4.2.5.1 Vererbung ................................................................................................ 38
4.2.5.2 Aggregation ............................................................................................. 40
4.2.5.3 Assoziation .............................................................................................. 41
4.2.6
Polymorphie .................................................................................................... 42
4.2.7
Nebenläufigkeit ............................................................................................... 43
II
Verzeichnisse
4.2.8
4.2.9
5
5.1
Persistenz......................................................................................................... 44
Generizität ....................................................................................................... 44
GLOBALES PROGRAMMKONZEPT ..................................................................46
Erläuterung des FEM-Objektmodells ................................................................. 46
5.2
Die Klassen ............................................................................................................. 54
5.2.1
Die Klasse ElementFEM ................................................................................. 54
5.2.2
Die Klasse Node .............................................................................................. 56
5.2.3
Die Klasse Dof ................................................................................................ 56
5.2.4
Die Klasse StructureFEM ............................................................................... 57
5.2.5
Die Klasse ProblemDomain............................................................................ 58
5.2.6
Die Klasse Matrix............................................................................................ 58
5.3
Rechenabläufe........................................................................................................ 59
5.3.1
Statische Berechnung ...................................................................................... 60
5.3.2
Nichtlineare Berechnung................................................................................. 60
5.4
6
Erweiterbarkeit und Wiederverwendung ........................................................... 68
PROGRAMMIERSPRACHEN................................................................................69
6.1
Prozedurale Programmiersprachen .................................................................... 72
6.1.1
Fortran ............................................................................................................. 72
6.1.2
C ...................................................................................................................... 73
6.2
Genuine objektorientierte Programmiersprachen............................................. 74
6.2.1
Smalltalk.......................................................................................................... 74
6.2.2
Eiffel................................................................................................................ 75
6.3
Hybride objektorientierte Programmiersprachen ............................................. 76
6.3.1
Ada .................................................................................................................. 76
6.3.2
C++.................................................................................................................. 77
6.3.3
Java.................................................................................................................. 78
6.4
Vergleich und Auswertung ................................................................................... 79
7
PROTOKOLLE UND DOKUMENTATION..........................................................84
8
BEISPIELPROGRAMM...........................................................................................87
8.1
Dateneingabe.......................................................................................................... 87
8.2
Datenausgabe ......................................................................................................... 91
LITERATURVERZEICHNIS ..........................................................................................92
ANHANG ............................................................................................................................95
A.
Unified Modeling Language (UML 1.4) Notationsübersicht
B.
Quellcode des Programms AllTA
C.
Vergleichsrechnungen
D.
Fiktives Klassenprotokoll der Klasse ElementFEM
III
Verzeichnisse
Abbildungsverzeichnis
Abbildung 2-1: Beliebiger 3D-Körper K ................................................................................... 4
Abbildung 2-2: Vorzeichenkonvention und Nummerierung der globalen Freiheitsgrade ....... 13
Abbildung 2-3: Baustatische Skizze des Balkenelementes ...................................................... 13
Abbildung 2-4: Bestimmung der Festhaltekraftgrößen am Balkenelement ............................. 17
Abbildung 3-1: Datenzugriff in prozeduralen und objektorientierten Programmen (aus [1]) . 24
Abbildung 4-1: Klassen............................................................................................................ 28
Abbildung 4-2: Schnittstellen................................................................................................... 29
Abbildung 4-3: Kollaborationen............................................................................................... 29
Abbildung 4-4: Anwendungsfälle ............................................................................................ 29
Abbildung 4-5: Aktive Klassen ................................................................................................ 29
Abbildung 4-6: Komponenten .................................................................................................. 29
Abbildung 4-7: Knoten............................................................................................................. 30
Abbildung 4-8: Nachrichten ..................................................................................................... 30
Abbildung 4-9: Zustände .......................................................................................................... 30
Abbildung 4-10: Pakete ............................................................................................................ 30
Abbildung 4-11: Notizen .......................................................................................................... 31
Abbildung 4-12: Abhängigkeiten ............................................................................................. 31
Abbildung 4-13: Assoziationen................................................................................................ 31
Abbildung 4-14: Generalisierungen ......................................................................................... 31
Abbildung 4-15: Realisierungen............................................................................................... 31
Abbildung 4-16: Klasse und Objekt (Instanz) am Beispiel eines Balkenelementes ................ 37
Abbildung 4-17: Einfache Vererbungsstruktur ........................................................................ 39
Abbildung 4-18: Mehrfachvererbung....................................................................................... 40
Abbildung 4-19: Aggregation................................................................................................... 41
Abbildung 4-20: Assoziationen................................................................................................ 42
Abbildung 4-21: Generische Klasse ......................................................................................... 45
Abbildung 5-1: Klassendiagramm: Klassen des globalen FEM-Models ................................. 49
Abbildung 5-2: Klassendiagramm: Klassen für die Steuerung der Berechnung...................... 50
Abbildung 5-3: Klassendiagramm: Vererbungshierarchie für die FEM-Objekte .................... 51
Abbildung 5-4: Klassendiagramm: Delegation der Containermethoden an eine generische
Klasse ............................................................................................................. 52
Abbildung 5-5: Klassendiagramm: Die Klasse Matrix ............................................................ 53
Abbildung 5-6: Aktivitätsdiagramm: Statische lineare Berechnung........................................ 62
IV
Verzeichnisse
Abbildung 5-7: Sequenzdiagramm: Statische lineare Berechnung.......................................... 63
Abbildung 5-8: Aktivitätsdiagramm: Berechnung nach Theorie 2. Ordnung.......................... 64
Abbildung 5-9: Sequenzdiagramm: Berechnung eines Iterationsschritts nach Theorie 2.
Ordnung.......................................................................................................... 65
Abbildung 5-10: Aktivitätsdiagramm: Physikalisch nichtlineare Berechnung........................ 66
Abbildung 5-11: Sequenzdiagramm: Berechnung eines Lastschrittes, physikalisch
nichtlineare Berechnung .............................................................................. 67
Abbildung 6-1: Entwicklungslinien der Programmiersprachen............................................... 70
Abbildung 6-2: Objektbasierte, klassenbasierte und objektorientierte Programmiersprachen 71
Abbildung 6-3: Abstraktionslevel in Smalltalk, C++, Fortran, C [32] .................................... 82
Tabellenverzeichnis
Tabelle 4-1: Diagramme der UML........................................................................................... 32
Tabelle 6-1: Objektorientierte Konzepte der verschiedenen Hochsprachen........................... 80
Tabelle 6-2: Eignung für numerische Berechnung: Fortran77, Fortran 90, C, C++ ................ 82
V
Verzeichnisse
Symbolverzeichnis
{x, y, z}
lokale Basis
{X ,Y ,Z}
globale Basis
ϕx, ϕy, ϕz :
Verdrehungen um die lokalen Achsen x, y, z
ϕ X ,ϕY ,ϕ Z :
Verdrehungen um die globalen Achsen X, Y, Z
λ:
skalare Kraftgröße der maximalen Belastung
ρ
(m)
:
Massendichte des Elementes m
l:
Länge
t:
Zeitvariable
qx, qy, qz :
Linienlasten am Stabelement (lokale Basis)
vx, vy, vz :
Verschiebungen in die lokalen Koordinatenrichtungen x, y, z
v X , vY , v Z :
Verschiebungen in die globalen Koordinatenrichtungen X,Y,Z
My, Mz :
Biegemomente am Stabende um die Achsen y und z (lokale Basis)
MT :
Torsionsmoment am Stabende (lokale Basis)
N:
Normalkraft am Stabende (lokale Basis)
Px, Py, Pz :
Einzelkräfte, am Element angreifend (lokale Basis)
Qy, Qz,
Querkräfte am Stabende in y- und z-Richtung (lokale Basis)
S(m) :
Oberfläche des Elementes m
SX, SY, SZ :
Stabendkräfte (globale Basis)
TX, TY, TZ :
Stabendmomente (globale Basis)
V
(m)
:
ε(m) :
(m)
τ
τ
Vektor der Verzerrungen im Element m
:
I(m)
:
f:
f :
Anfangsspannungen im Element m
Element-Randkraftgrößen (globale Basis)
B
f ,f :
0
Vektor der Spannungen im Element m
Element-Randkraftgrößen (lokale Basis)
f:
S
Volumen des Elementes m
Vektor kontinuierlicher Elementlasten (lokale Basis)
Festhaltegrößen (lokale Basis)
VI
Verzeichnisse
k:
Element-Steifigkeitsmatrix bezogen auf alle Element-Freiheitsgrade
(lokale Basis)
k:
Element-Steifigkeitsmatrix bezogen auf alle Element-Freiheitsgrade
(globale Basis)
p0:
Vektor der Linienlasten (lokale Basis)
v:
Vektor der Element-Freiheitsgrade (lokale Basis)
v:
Vektor der Element-Freiheitsgrade (globale Basis)
v(m) :
Verschiebungen im Element m
B(m) :
Verzerrungs-Verschiebungs-Matrix am Element m bezogen auf die
aktiven System-Freiheitsgrade
C(m) :
Elastizitätsmatrix des Elementes m bezogen auf die aktiven SystemFreiheitsgrade
F:
Vektor der auf die Elemente wirkende äußere Kräfte bezogen auf die
aktiven System-Freiheitsgrade. (globale Basis)
Fi :
Vektor konzentrierter Lasten
F* :
Pseudo-Lastvektor, der die Nichtlinearitäten berücksichtigt
F:
normierter Lastvektor der Knotenlasten F
+
F:
Lastinkrement
Fˆ 0 :
Vektor der System-Festeinspannkraftgößen
Freiheitsgrade
Fo:
Vektor der mit den aktiven Freiheitsgraden korrespondierenden
System-Festeinspannkraftgrößen
Fc0 :
Vektor der mit den gefesselten Freiheitsgraden korrespondierenden
System-Festeinspannkraftgrößen
H(m) :
Verschiebungsinterpolationsmatrix des Elementes m bezogen auf die
aktiven System-Freiheitsgrade
K(m) :
Steifigkeitsmatrix des Elementes m (globale Basis) bezogen auf die
aktiven System-Freiheitsgrade
K:
Gesamtsteifigkeitsmatrix bezogen
Freiheitsgrade (globale Basis)
Kg n :
geometrische Steifigkeitsmatrix (abhängig von Vn)
Ktn :
tangentiale Steifigkeitsmatrix im Iterationsschritt n
M:
Gesamtmassenmatrix (globale Basis) bezogen auf die aktiven SystemFreiheitsgrade (globale Basis)
P:
Vektor der äußeren Einzelkräfte, die auf die Knoten der ElementeGruppierung wirken
Pc:
Lagerkraftgrößen
Pˆ :
Vektor der an den Knoten angreifenden äußeren Kraftgrößen
(Knotenlasten und Lagerkräfte) bezogen auf alle Freiheitsgrade
auf
die
bezogen
aktiven
auf
alle
System-
VII
Verzeichnisse
T:
Drehungsmatrix
U:
Vektor der Ungleichgewichtskräfte
V:
Vektor für die globalen Knotenpunktverschiebungen einer ElementeGruppierung bezogen auf die aktiven Freiheitsgrade
ˆ:
V
Vektor für die globalen Knotenpunktverschiebungen einer ElementeGruppierung bezogen auf alle Freiheitsgrade
&& :
V
Vektor der Knotenbeschleunigungen
Vn :
Vektor der absoluten globalen Knotenverschiebungen bezogen auf die
aktiven Freiheitsgrade
Vc :
Vektor der durch Lagerbindung gefesselten Freiheitsgrade
1 Einleitung
1
1
Einleitung
Diese Arbeit diskutiert die Konzeption und Realisierung eines zeitgemäßen Programms
zur allgemeinen Tragwerksanalyse. Dabei geht es zunächst um die Verwirklichung eines
Finite-Elemente-Programms (FEM).
Das
Hauptaugenmerk
liegt
auf
einem
globalen,
modular
aufgebauten
Programmentwurf. Das Design sollte flexibel und leicht an neue Aufgabenstellungen
anzupassen sein. Die Erweiterbarkeit des Programmsystems auf andere numerische
Methoden wie z.B. die Boundary-Element-Methode (BEM) oder die Methode der Finiten
Differenzen (FDM) oder sogar die Berechnung von Mischformen aus diesen numerischen
Methoden soll im Entwurf mitberücksichtigt werden.
Die für das Verständnis notwendigen Grundlagen der Finite-Elemente-Methode werden
zu Beginn der Arbeit in allgemeiner Form vorgestellt. Dabei wird auch auf die Berechnung
nichtlinearer Systeme eingegangen und übliche numerische Verfahrensweisen werden
erläutert.
Für das Design eines komplexen Software-Systems gibt es grundsätzlich kein
Universalrezept. Oft lassen sich mehrere Entwurfsverfahren für die Realisierung eines
Programms einsetzen. Die Entscheidung, mit welchem Design-Konzept sich die
Anforderungen an ein bestimmtes Software-System am besten erfüllen lassen, ist sehr stark
abhängig von den Kriterien, die man zur Beurteilung heranzieht.
Die verschiedenen gebräuchlichen Entwurfsstile für Software werden in Kapitel 3 näher
erläutert und ihre Vor- und Nachteile in Bezug auf das zu entwerfende Programmsystem
diskutiert. In der vorliegenden Arbeit wurde ein objektorientierter Entwurf favorisiert. In
den Kapiteln 4 und 5 werden daher die Begriffe und Konzepte der Objektorientierung
definiert und die Unified Modeling Language (UML) als Notation für objektorientierte
Programmsysteme vorgestellt.
Der Programmentwurf wird in Kapitel 5 vorgestellt. Dabei wird die Architektur mit
Hilfe von Klassendiagrammen erläutert. Berechnungsabläufe werden in Sequenz- und
Aktivitätsdiagrammen dargestellt. Der Entwurf wird beispielhaft in einem kleinen FEMStabwerksprogramm umgesetzt, das in Kapitel 8 beschrieben ist. Der Quellcode für das
Programm ist im Anhang zu finden.
Das Design eines Programmsystems setzt sich gleichermaßen aus den Kenntnissen über
das numerische Verfahren, hier die Methode der Finiten Elemente, die verwendete
Entwurfsmethode und die Erläuterung der grafischen Notation zusammen. Im Rahmen
2
Einleitung
dieser Diplomarbeit können die angesprochenen Themengebiete nur in vereinfachter Form
wiedergegeben werden, die Erläuterungen erheben keinen Anspruch auf Vollständigkeit.
Zudem lassen sich die Bestandteile in den einzelnen Kapiteln nicht vollständig entkoppeln,
daher beziehen sich die einzelnen Abschnitte der Arbeit sehr stark aufeinander. Bei der
Gliederung konnte nicht vollständig vermieden werden, dass Begriffe und Konzepte, die in
einem Absatz bereits benutzt werden, erst zu einem späteren Zeitpunkt genauer definiert
werden. Die entsprechenden Verweise sind angegeben.
2 Grundlagen der Finite-Elemente-Methode
2
3
Grundlagen der Finite-Elemente-Methode
In diesem Abschnitt werden die Gleichungen für die Methode der Finiten Elemente
zunächst in allgemeiner Form vorgestellt. Auf dieser allgemeinen Formulierung beruht der
Entwurf der Programmarchitektur in Kapitel 5. Die Beziehungen für einen beliebig
geformten 3D-Körper werden in Kapitel 2.2 auf ein linear-elastisches, schubstarres
Balkenelement angewendet. Dieses wird für die beispielhafte Implementierung des
Stabwerkprogramms benutzt (vgl. Kapitel 8).
Es liegt nicht im Rahmen der Arbeit alle dargestellten Gleichungen herzuleiten, dafür
wird auf die Literatur verwiesen (Bathe [2], Krätzig [20],[21]). Vielmehr soll nur der
allgemeine Ablauf einer Berechnung nach der Methode der Finiten Elemente und die dafür
benötigten Gleichungen und Matrizen vorgestellt werden.
2.1
Allgemeine Formulierung
Die Berechnung diskreter Systeme beruht im Allgemeinen auf vier Schritten:
•
der Idealisierung des Systems (Elementierung),
•
der Aufstellung der Gleichgewichts- bzw. Bewegungsgleichung,
•
der Ermittlung der Systemantwort und
•
der Interpretation der Ergebnisse.
Im Folgenden wird hauptsächlich auf die Aufstellung der Gleichgewichts- bzw.
Bewegungsgleichung und die Berechnung der Systemantwort mit numerischen Verfahren
eingegangen,
da
diese
Bestandteile
des
eigentlichen
Rechenkerns
eines
FEM-
Programmsystems sind. Die Elementierung und die Interpretation der Ergebnisse sind
Bestandteile eines geeigneten Prä- bzw. Postprozessors und werden programmtechnisch
vom Rechenkern abgekoppelt.
2.1.1
Lineare statische Berechnung
Der in Abbildung 2-1 dargestellte beliebige 3D-Körper K soll sich im Gleichgewicht
befinden. Auf den Körper wirken äußere Lasten: Oberflächenspannungen fS, Volumenkräfte
fB und Einzelkräfte Fi. Sie umfassen alle äußeren eingeprägten und Reaktionslasten und
haben – entsprechend den drei globalen Koordinatenachsen X,Y,Z – jeweils drei
Komponenten.
4
Grundlagen der Finite-Elemente-Methode
X
Y
fSX, f BX
f SY, f BY
Z
FiX
FiY
y
x
z
fSZ, f BZ
FiZ
Abbildung 2-1: Beliebiger 3D-Körper K
Die Lastvektoren haben die Form:
[
= [f
= [F
]
];
];
T
f S = f XS
f YS
f ZS ;
fB
B
X
f YB
f ZB
i
X
FYi
FZi
FS
T
[Gl. 1]
T
Die auf den unbelasteten Zustand des Körpers bezogenen Verschiebungen kennzeichnet
der Verschiebungsvektor V mit
V = [V X
VY
VZ ] .
T
[Gl. 2]
Über die Verzerrungs-Verschiebungs-Beziehungen sind dem Verschiebungsvektor V
die Verzerrungen
ε = [ε XX
ε ZX ]T
[Gl. 3]
τ YY τ ZZ τ XY τ YZ τ ZX ]T
[Gl. 4]
ε YY
ε ZZ
ε XY
ε YZ
zugeordnet, denen die Spannungen
τ = [τ XX
entsprechen.
In der Methode der Finiten Elemente wird der kontinuierliche Körper näherungsweise
als eine Gruppierung diskreter finiter Elemente dargestellt, die in Knotenpunkten auf den
Rändern der Elemente untereinander verbunden sind.
2 Grundlagen der Finite-Elemente-Methode
5
Die in einem passend zu wählenden, lokalen Koordinatensystem x,y,z gemessenen
Verschiebungen innerhalb eines jeden Elementes werden als Funktionen der Verschiebung
der N Knotenpunkte der finiten Elemente angenommen. Damit gilt für die Verschiebungen
des m-ten Elementes:
ˆ
v (m) ( x,y,z ) = H (m) ( x, y, z )V
mit :
v(m) :
[Gl. 5]
Verschiebungen im Element m
x,y,z: lokales Koordinatensystem (KOS)
H(m): Verschiebungsinterpolationsmatrix
ˆ :
V
Vektor für die globalen Verschiebungskomponenten aller
Knotenpunkte der Elemente-Gruppierung
ˆ T = [V V V K V ]
V
1
2
3
n
[Gl. 6]
Die einzelnen Komponenten Vi des Verschiebungsvektors aus Gleichung 6 können
dabei eine Verschiebung in beliebiger Richtung darstellen, die nicht notwendigerweise mit
einer globalen Achse übereinstimmt, und auch eine Drehung kennzeichnen kann.
Die Matrix H(m) ist die Verschiebungsinterpolationsmatrix und enthält die gewählten
Formfunktionen. Das Feld der äußeren Weggrößen wird zunächst durch die - auf die lokale
Basis bezogenen - Verschiebungen beschrieben, für die Polynomansätze des gewünschten
Grades angenommen werden. Die Formfunktionen der Matrix H(m) erhält man durch
Ersetzen der Polynomparameter durch den Vektor der Knotenverschiebungen.
Die Verschiebungen und Verzerrungen innerhalb eines Elementes hängen nur von den
Verschiebungen der Knoten dieses Elementes ab. Damit ergeben sich die ElementVerzerrungen zu:
ˆ
ε (m) ( x,y,z) = B (m) ( x, y, z )V
mit :
ε(m) :
Verzerrungen im Element m
B(m):
Verzerrungs-Verschiebungs-Matrix
[Gl. 7]
Die Zeilen der Verzerrungs-Verschiebungs-Matrix werden durch Differenzieren und
Kombinieren der Zeilen der Matrix H(m) in Gleichung 5 ermittelt.
6
Grundlagen der Finite-Elemente-Methode
Die Spannungen τ(m) in einem finiten Element sind mit den Verzerrungen ε(m) und den
Anfangsspannungen τI(m) des Elementes über
τ (m) = C (m) ε (m ) + τ I(m)
τ(m) :
mit :
[Gl. 8]
Spannungen im Element m
C(m): Elastizitätsmatrix des Elementes
τI(m) : Anfangsspannungen im Element m
verknüpft. Das durch C(m) für jedes Element angegebene Materialgesetz kann ein isotropes
oder anisotropes Material beschreiben und kann sich von Element zu Element ändern.
Über die Methode der virtuellen Verschiebungen (jeweils ein Vi wird gleich 1 gesetzt)
können nun in jedem finiten Element die Gleichgewichtsbedingungen bezüglich der
Knotenpunktverschiebungen der Gruppierung von finiten Elementen aufgestellt werden.
Dabei wird der Verschiebungsverlauf über das Element über eine Funktion angenähert.
Wenn von nun an die Knotenpunktverschiebungen einfach mit V bezeichnet werden
ˆ ≡ V ),
(V
lauten
die
auf
die
Knotenpunktverschiebungen
bezogenen
Gleichgewichtsbedingungen der Element-Gruppierung:
KV = F
mit
[Gl. 9]
F : Last-Vektor mit den auf die Elemente wirkenden Kräften.
F = FB + FS – FI + P
[Gl. 10]
P ist der Vektor der äußeren Einzelkräfte, die auf die Knoten der
Elemente-Gruppierung wirken.
K: Gesamtsteifigkeitsmatrix
V: globaler Vektor der Knotenpunktverschiebungen
Die Komponenten von Gleichung 9 und 10 errechnen sich dabei wie folgt:
K = ∑ K (m ) = ∑
m
∫
B (m)T C (m) B (m) dV ( m )
[Gl. 11]
m V (m)
F B = ∑ F B(m) = ∑
∫
H (m)T f B(m) dV ( m )
[Gl. 12]
F S = ∑ F S(m) = ∑
∫
H S (m)T f S(m) dS ( m )
[Gl. 13]
F I = ∑ F I(m) = ∑
∫
B(m)T τ I(m) dV ( m )
m
m
m
m V (m)
m S (m)
m V (m)
[Gl. 14]
2 Grundlagen der Finite-Elemente-Methode
7
Die in Gleichung 11 vorgeschriebene Summation der Volumenintegrale über die
Elemente entspricht der direkten Addition der Steifigkeitsmatrizen K(m) der Elemente. Sie
liefert die Steifigkeitsmatrix K der gesamten Elemente-Gruppierung. Analog werden die
Kraftvektoren durch direkte Addition der Volumenkraftvektoren der einzelnen Elemente
errechnet. Die Aufstellung der Gleichgewichtsbedingungen in der hier beschriebenen Weise
(Bezug auf den Vektor V der globalen Freiheitsgrade bei der Elementformulierung) enthält
somit die Zusammenfügung von Element-Matrizen zu einer Strukturmatrix. Dieses
Vorgehen wird auch als direkte Steifigkeitsmethode bezeichnet.
In der Praxis werden die finiten Element-Matrizen zunächst in kompakter Form für alle
möglichen Freiheitsgrade des Elementes berechnet (Entkopplung). Für ein Element gilt:
kv = f
mit:
[Gl. 15]
k : Element-Steifigkeitsmatrix
v: Vektor der Element-Freiheitsgrade
f:
durch Knotenverschiebungen hervorgerufene ElementRandkraftgrößen
Die einzelnen Einträge in der Elementmatrix setzen sich dabei aus Randkraftgrößen
zusammen, die aus einer Einheitsverschiebung in Richtung jeweils eines Freiheitsgrades
resultieren. Die Berechnungsvorschriften aus den Gleichungen 11-14 behalten ihre
Gültigkeit, die Element-Matrizen b und h beziehen die Verschiebungen dabei allerdings
nicht mehr auf die globalen, sondern auf die lokalen Freiheitsgrade des Elementes.
Die Freiheitsgrade des Elementes werden über Inzidenzen auf die Freiheitsgrade der
Struktur
bezogen
und
die
entsprechenden Beiträge
der
Elementmatrix
in
die
Gesamtsteifigkeitsmatrix eingelesen.
2.1.2
Kinetische Berechnung
Bei der Erweiterung der erstellten Beziehungen auf dynamische Aufgabenstellungen
gehen Trägheitskräfte mit in die Grundgleichung ein. Diese werden auf die Seite der inneren
Größen des Systems gestellt. Die Systemantwort wird damit zeitabhängig.
&& (t ) + KV (t ) = F(t )
MV
mit:
[Gl. 16]
M:
Gesamtmassenmatrix
K:
Gesamtsteifigkeitsmatrix
V(t):
Vektor der Knotenverschiebungen
Zeitunabhängig
&& (t ) : Vektor der Knotenbeschleunigungen
V
Zeitabhängig
8
Grundlagen der Finite-Elemente-Methode
Die zusätzliche Komponente in Gleichung 16 errechnet sich nach:
M = ∑ M (m) = ∑
m
mit:
∫
ρ ( m ) H (m)T H (m) dV ( m )
[Gl. 17]
m V (m)
ρ(m) : Massendichte des Elementes m
Während Gleichung 8 noch ein lineares Gleichungssystem repräsentiert und daher
direkt gelöst werden kann, beschreibt Gleichung 16 eine Differentialgleichung 2. Ordnung.
Das Gleichgewicht muss für jeden Zeitpunkt t erfüllt werden.
In numerischen Anwendungen wird die Differentialgleichung üblicherweise mit
direkten Integrationsmethoden gelöst. Dabei wird die Bewegungsgleichung in diskreten
Zeitintervallen Δt erfüllt (nicht für einen beliebigen Zeitpunkt). Die Anfangsbedingungen
zum Zeitpunkt t=0 sind bekannt. Von t=0 ausgehend werden für jeden Zeitschritt die
effektiven Lasten zum Zeitpunkt t+Δt extrapoliert, die entsprechenden Verschiebungen zur
Zeit t+Δt berechnet und die Beschleunigung zur Zeit t ermittelt. Bekannte direkte
Integrationsmethoden sind z.B. die zentrale Differenzenmethode (explizites Verfahren), die
Houboltsche oder die Newmark-Methode (implizit).
Ebenso wie die Steifigkeitsmatrix wird auch die Massenmatrix für jedes Element
entsprechend der Element-Freiheitsgrade aufgestellt, und über die Inzidenzen in die
Gesamtmassenmatrix eingelesen [2].
2.1.3
Nichtlineare Berechnungen
Nichtlineares Verhalten von Tragwerken hat eine oder mehrere der folgenden
Ursachen:
•
Geometrische Nichtlinearität; z.B. Theorie 2. Ordnung, d.h. Gleichgewicht am
verformten System
•
Nichtlineares Materialverhalten; z.B. allg. Spannungs-Dehnungs-Diagramm
•
Veränderliche Systeme; z.B. Zugstäbe, die bei Druckbeanspruchung nicht
mitwirken
Alle diese Einflüsse haben gemeinsam, dass der Graph, der das Verhältnis zwischen
Last und Verformung beschreibt, nicht mehr linear verläuft. Die Berechnung erfolgt iterativ
und/oder durch schrittweises Aufbringen der Lasten. Falls in einer statischen,
zeitunabhängigen Rechnung nur die Konfiguration für eine bestimmte Laststellung gesucht
ist, kann die iterative Berechnung auch auf einen Schritt reduziert werden. Aus
2 Grundlagen der Finite-Elemente-Methode
rechentechnischen
Gründen
(z.B.
9
Konvergenz)
kann
allerdings
ebenfalls
eine
Inkrementallösung notwendig werden.
Das gemeinsame Ziel aller numerischen Lösungsverfahren ist, den nichtlinearen LastVerformungspfad nachzufahren. Man definiert für die numerische Berechnung eine
sogenannte Ungleichgewichtskraft U, die die Abweichung der approximierten Lösung vom
wahren Gleichgewicht angibt (für Gleichgewicht gilt: U = 0). Gl. 9 kann damit auf die
folgende Form erweitert werden:
U = -KV + F + F*(V)
mit:
K:
lineare globale Steifigkeitsmatrix
V:
Vektor der globalen Knotenverschiebungen
F:
Vektor der äußeren Lasten
[Gl. 18]
F*: Pseudo-Lastvektor, der die Nichtlinearitäten berücksichtigt
U:
Ungleichgewichtskraft
Der Kraftvektor F der äußeren Lasten kann durch einen skalaren Parameter λ
multipliziert mit dem normierten Vektor F ausgedrückt werden.
F=λ⋅F
[Gl. 19]
Der Pseudo-Lastvektor F* und der Vektor der globalen Knotenverschiebungen werden
ebenfalls als Funktionen von λ aufgefasst. Eine Ableitung nach λ ergibt:
U ′ = −KV ′ + F + (F * (V )) ′
[Gl. 20]
Bei der Ableitung des nichtlinearen Pseudo-Lastvektors gilt die Kettenregel. Die bei der
Ableitung entstehende Matrix wird auch als nichtlineare Steifigkeitsmatrix KNL bezeichnet.
Gleichung 20 wird damit zu:
U ′ = −KV ′ + F + ( −K NL V ′) = −(K + K NL )V ′ + F
[Gl. 21]
Die numerischen Verfahren für die Lösung der nichtlinearen Beziehungen lassen sich in
3 Gruppen teilen:
1. Lösungsverfahren 1. Klasse versuchen für jeden Lastschritt die Gleichgewichtsbedingungen zu erfüllen Æ U = 0
Bekannter Vertreter dieser Klasse ist das Newton-Raphson-Verfahren
2. Lösungsverfahren 2. Klasse minimieren die Ungleichgewichtskraft für jedes
Lastinkrement Æ U′ = 0
Bekannt ist hier die inkrementelle Steifigkeitsmethode.
10
Grundlagen der Finite-Elemente-Methode
3. Selbstkorrigierende Methoden sind Methoden, die Verfahren der 1. und 2. Klasse
verbinden. Die Systemantwort wird korrigiert, wenn sie zu weit vom Gleichgewicht
abweicht.
Die Verwendung eines bestimmten Lösungsalgorithmus ist abhängig von einer Anzahl
von Kriterien wie der Art der Nichtlinearität, dem Einfluss der Nichtlinearität auf die
Systemantwort, dem Konvergenzverhalten, dem Rechenaufwand und der Genauigkeit. Da
eine Diskussion der verschiedenen Verfahren den Rahmen der Arbeit sprengen würde,
werden für die Berechnung nach Theorie 2. Ordnung und für physikalische Nichtlinearitäten
in der Praxis übliche Berechnungsverfahren ausgewählt und vorgestellt. Dabei wird davon
ausgegangen, dass diese Phänomene getrennt voneinander auftreten. Für eine gleichzeitige
Berechnung
von
Theorie
2.
Ordnung
unter
Berücksichtigung
nichtlinearen
Materialverhaltens kann z.B. eine Kombination der vorgestellten Verfahrensweisen
eingesetzt werden.
2.1.3.1
Theorie 2. Ordnung
Geometrisch nichtlineare Tragwerksanalysen berücksichtigen entstehende Deformationen als endliche Größen. Das Gleichgewicht wird an der verformten Konfiguration
formuliert. Auch bei einem weiterhin linear-elastischem Werkstoffverhalten wird somit das
Gesamtproblem nichtlinear. Ein in der Praxis häufig eingesetztes Lösungsverfahren für
geometrische Nichtlinearität ist das Newton-Raphson-Verfahren. Die Gesamtlast wird in
Lastschritten aufgebracht.
+
F=
mit:
λ
M
F = Δλ ⋅ F
+
[Gl. 22]
F:
Lastinkrement
F:
normierter Vektor der Knotenlasten
M:
Anzahl der Lastschritte, Berechnungsschritte m= 1,2...M
λ:
skalare Kraftgröße der maximalen Belastung
Die nichtlineare Steifigkeitsmatrix reduziert sich in diesem Fall auf die geometrische
Steifigkeitsmatrix Kg, die (linear) abhängig von den inneren Schnittgrößen der Elemente ist.
Wie für K muss auch bei der Ableitung von Kg nur ein einziges Element eines spezifischen
Typs betrachtet werden, weil sich die beherrschenden Gleichgewichtsbedingungen einer
Elemente-Gruppierung mit Hilfe der direkten Steifigkeitsmethode aufstellen lassen. Die
2 Grundlagen der Finite-Elemente-Methode
11
geometrische Element-Steifigkeitsmatrix kg wird aus der Taylor-Entwicklung des
Ausdruckes (f*(v))´ bis zum 2. Glied gewonnen (Æ Theorie 2. Ordnung).
Die Iteration für einen Lastschritt (ausgehend von einer bereits bekannten
Konfiguration F0,V0) lässt sich in der Newton-Raphson-Methode wie folgt beschreiben:
U(V) n = (K + K g n ) ⋅ ΔVn +1 = K t n ⋅ ΔVn +1
und
[Gl. 23]
Vn +1 = Vn + ΔVn +1
mit: n:
[Gl. 24]
Kgn:
Iterationsschritt n = 0,1,2...N,
N: Gesamtzahl der Iterationsschritte
geometrische Steifigkeitsmatrix (abhängig von Vn)
Ktn:
tangentiale Steifigkeitsmatrix im Iterationsschritt n
Vn:
Vektor der absoluten globalen Knotenverschiebungen
U(V)n: Ungleichgewichtskraft
Aus Gleichung 23 und 24 wird der Zuwachs der Verschiebung ΔVn +1 für den
jeweiligen Iterationsschritt berechnet. In der Vorbereitung des nächsten Iterationsschrittes
werden die jeweils letzten Näherungswerte für Vn-1 dazu verwendet, um die zugehörigen
Element-Spannungen und Knotenpunktkräfte zu ermitteln.
+
U(V) n = F 0 + F − Fn -1
mit: U(V):
Fn-1:
[Gl. 25]
+
Ungleichgewichtskraft, für n=0 gilt U(V)0 = F .
Aus den aktuellen Knotenverschiebungen
Knotenpunktkräfte (Lastseite)
resultierende
Die Iteration wird solange fortgeführt, bis die Ungleichgewichtskraft U(V)n+1 bzw. der
Zuwachs der Knotenverschiebungen ΔVn +1 für eine Iteration unter eine vorgegebene
Genauigkeitsschranke fällt.
Das Newton-Raphson-Verfahren konvergiert in der Regel sehr schnell. Vor allem
konvergiert es auch bei einem großen Einfluss der Nichtlinearität und liefert eine
vergleichsweise genaue Berechnung. Ein großer Nachteil dieses Lösungsverfahrens ist, dass
es sehr rechenintensiv ist. Für jeden Iterationsschritt wird die tangentiale Steifigkeitsmatrix
neu aufgestellt und invertiert. In einem modifizierten Newton-Raphson-Verfahren wird
daher die tangentiale Steifigkeitsmatrix nur am Beginn eines jeden Lastschrittes aufgestellt
und für die gesamte Iteration konstant gehalten. Das Newton-Raphson-Verfahren ist
beschränkt auf Verfahren, in denen keine Entlastung vorkommt.
12
Grundlagen der Finite-Elemente-Methode
2.1.3.2
Physikalisch nichtlineare Berechnung
Für physikalisch nichtlineare Berechnungen eignen sich die direkten (iterativen)
Näherungsverfahren (U = 0) nicht, da sie um kritische Punkte des Last-Verformungspfades
oszillieren oder sogar divergieren können. Für diese Berechnungen werden zumeist
Verfahren 2. Klasse herangezogen.
Die inkrementelle Steifigkeitsmethode geht in kleinen Lastschritten den LastVerformungspfad nach, wobei für jeden Lastschritt das System als linear angenommen wird.
Der nichtlineare Anteil der tangentialen Steifigkeitsmatrix beinhaltet die plastischen Anteile
der Last-Verformungsbeziehung.
K t = K + K pl
[Gl. 26]
Für jeden Lastschritt wird U(V) minimiert ( U ′ = 0). Die Berechnung für die
Lastschritte erfolgt dabei nach folgenden Formeln:
+
(K + K pl m ) ⋅ ΔVm +1 = Δλ ⋅ F = F
und
Vm +1 = Vm + ΔVm +1
[Gl. 27]
[Gl. 28]
Aus Gleichung 27 wird jeweils ΔVm +1 errechnet. In Abhängigkeit von Vm+1 aus
Gleichung 28 wird dann der plastische Teil der Steifigkeitsmatrix für den nächsten
Lastschritt neu berechnet.
Die Verfahrensweise der inkrementellen Steifigkeitsmethode ist für nichtlineares
Materialverhalten sehr vorteilhaft und einfach umzusetzen. Es wird keine Iteration benötigt
und plastisches Materialverhalten kann problemlos berücksichtigt werden. Ein Nachteil
dieser Methode ist, dass es keine wirkliche Fehlerabschätzung gibt. Da ein Lastschritt auf
dem nächsten aufbaut summieren sich Fehler und die inkrementelle Lösung „driftet“ von der
eigentlichen Lösung weg. Um eine Aussage über den Fehler zu erhalten, sollte das System
mit verschieden großen Lastinkrementen mehrmals durchgerechnet werden.
2.2
Das Weggrößenverfahren für ein Stabwerk
Im Folgenden sollen die Gleichungen und Größen aufgestellt werden, die zur statischen
Berechnung eines räumlichen Stabwerkes nach der FEM benötigt werden. Dazu wird
zunächst die Element-Steifigkeitsmatrix für ein gerades, räumliches und schubstarres
Stabelement angeführt. Auf die Herleitung der Matrix wird an dieser Stelle verzichtet, es
wird auf die Literatur verwiesen (vgl. Krätzig „Tragwerke III“ [21]). Das programmierte
2 Grundlagen der Finite-Elemente-Methode
13
Balkenelement soll die Steifigkeitsmatrix in direkter Form vorhalten. Auf die Aufstellung
der Verschiebungsinterpolationsmatrix und der Verzerrung-Verschiebungsmatrix sowie die
Integration über das Element wird daher nicht weiter eingegangen.
Abbildung 2-2 zeigt das im Folgenden benutzte globale Koordinatensystem und die
Nummerierung der Freiheitsgrade für einen (globalen) Knoten. Verschiebungen sind positiv
in Richtung der Koordinatenachsen, Verdrehungen werden positiv für eine mathematisch
positive Drehrichtung um die entsprechende Achse angenommen.
φ y = V5
φx = V4
X
Y
V x = V1
V y = V2
Z
φz = V6
Vz = V3
Abbildung 2-2: Vorzeichenkonvention und Nummerierung der globalen Freiheitsgrade
Lokale Koordinatenachsen und Freiheitsgrade für das Stabelement werden analog zu
den globalen angenommen. Abbildung 2-3 zeigt die baustatische Skizze für das räumliche,
schubstarre Stabelement der Länge l. Es wird angenommen, dass sämtliche Querschnittsund Materialwerte über die Länge des Elements konstant sind, also:
E, G = konstant und Iy, Iz, IT, A = konstant.
Mz,l
Nl
Qy,l
MT ,l
Mz,r
l
My,l
Qy,r
x
y
Qz,l
r
MT,r
z
My,r
Nr
Qz,r
l
Abbildung 2-3: Baustatische Skizze des Balkenelementes
Die Auswertung der allgemeinen Integralformeln nach Gleichung 11-14 führt
wiederum auf das Gleichungssystem kv = f (Gleichung 15).
14
Grundlagen der Finite-Elemente-Methode
Die lokale Steifigkeitsmatrix für ein schubstarres Balkenelement nach Krätzig [20] hat
die folgende Form:
k
⎡ EA
⎢ l
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
= ⎢⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎣⎢
−
EA
l
0
0
0
0
0
12 EI z
l3
0
0
0
6 EI z
l2
0
0
0
12 EI y
l3
0
−
GI T
l
6 EI y
l2
0
4 EI y
l
0
−
12 EI z
l3
−
0
0
0
0
0
0
0
0
6 EI
− 2z
l
4 EI z
l
EA
l
0
0
0
0
12 EI y
l3
6 EI y
0
6 EI y
l2
0
2 EI y
l
0
0
0
0
0
0
0
0
12 EI y
symmetrisch
−
0
l2
0
0
GI
− T
l
0
12 EI z
l3
0
0
6 EI y
0
l3
GI T
l
l2
0
EI y
l
Die Vektoren v und f
⎤
⎥
6 EI z ⎥
⎥
l2 ⎥
⎥
0 ⎥
⎥
0 ⎥
⎥
⎥
0 ⎥
⎥
2 EI z ⎥
l ⎥
⎥
0 ⎥
⎥
6 EI
− 2z⎥
l ⎥
⎥
0 ⎥
⎥
0 ⎥
⎥
⎥
0 ⎥
⎥
4 EI z ⎥
l ⎦⎥
0
[Gl. 29]
beinhalten die Einträge der auf die lokalen Freiheitsgrade
bezogenen Verschiebungen und Kraftgrößen:
[
f ] = [N
v T = [v1 K v2 ] = vx ,l
f = [ f1 K
T
2
l
v y ,l
vz , l
Qy ,l
Qz , l
ϕ x,l ϕ y ,l ϕ z ,l
M T ,l
M y ,l
vx , r
M z ,l
vy,r
Nr
vz , r
Qy , r
ϕ x, r ϕ y ,r ϕ z , r ]
Qz , r
M T ,r
M y,r
M z,r
Als Formfunktionen zur Herleitung der Elementsteifigkeitsmatrix werden Hermitesche
Interpolationspolynome verwendet.
Für die Transformation der lokalen Freiheitsgrade auf die globalen Freiheitsgrade muss
berücksichtigt werden, dass das Stabelement eine beliebige Lage im Raum haben kann. Es
ist also notwendig, die lokalen Koordinatenachsen des Elementes auf das globale
Koordinatensystem zu transformieren. Dieses geschieht durch eine Drehungsmatrix T, die
durch die Richtungskosinus zwischen den lokalen und den globalen Achsen ausgedrückt
werden.
⎡ cos( x, X ) cos( x, Y ) cos( x, Z ) ⎤
T = ⎢⎢cos( y, X ) cos( y, Y ) cos( y, Z )⎥⎥
⎢⎣ cos( z , X ) cos( z , Y ) cos( z , Z ) ⎥⎦
[Gl. 30]
In dieser Matrix bezeichnet cos(a,B) den Richtungskosinus zwischen der lokalen aAchse und der globalen B-Achse.
]
2 Grundlagen der Finite-Elemente-Methode
15
Es den Richtungscosinus gilt:
cos(a,A) = cos(A,a)
Daher kann die Transponierte der Drehungsmatrix auch wie folgt dargestellt werden:
⎡cos( X , x) cos( X , y ) cos( X , z )⎤
T = ⎢⎢ cos(Y , x) cos(Y , y ) cos(Y , z ) ⎥⎥
⎢⎣ cos( Z , x) cos( Z , y ) cos( Z , z ) ⎥⎦
T
[Gl. 31]
Die Matrix T bezeichnet die Transformation vom globalen in das lokale
Koordinatensystem, dagegen bezieht TT lokale Vektoren auf das globale System.
Gleichung 15 kann mit Hilfe der Drehungsmatrix in das globale Koordinatensystem
überführt werden. Das Gleichungssystem lautet damit
kv = f
[Gl. 32]
mit den globalen Vektoren v und f , die die auf die globalen Achsen bezogenen
Verschiebungen und Kraftgrößen an den Stabenden beinhalten:
v T = [v1
[
K
f = f1 K
T
v2 ] = [v X ,l
]
f 2 = [S X ,l
vY ,l
vZ , l
ϕ X ,l
S Y ,l
S Z ,l
T X ,l
ϕ Y ,l
TY ,l
ϕ Z ,l
TZ ,l
vX ,r
S X ,r
vY , r
S Y ,r
vZ , r
S Z ,r
ϕ X ,r
T X ,r
ϕY , r
TY ,r
TZ ,r ].
Die Berechnungsvorschrift für die Transformation ist wie folgt:
⎡T T
⎢
0
k=⎢
⎢0
⎢
⎣⎢ 0
0
TT
0
0
0
TT
0
0
⎡T T
⎢
0
v=⎢
⎢0
⎢
⎣⎢ 0
0
TT
0
0
0
0
TT
0
0⎤
⎥
0⎥
⋅v
0⎥
⎥
TT ⎦⎥
⎡T T
⎢
0
f =⎢
⎢0
⎢
⎣⎢ 0
0
TT
0
0
0
0
TT
0
0⎤
⎥
0⎥
⋅f
0⎥
⎥
TT ⎦⎥
⎤
⎡T 0 0 0 ⎤
⎥
⎢
⎥
⎥ ⋅k ⋅ ⎢0 T 0 0⎥
⎥
⎢0 0 T 0⎥
⎢
⎥
T⎥
T ⎦⎥
⎣ 0 0 0 T⎦
0
0
0
[Gl. 33]
Um auch Stabelemente mit Stabeinwirkungen (auf den Stab wirkende Kräfte, die nicht
in den Knoten angreifen) berechnen zu können, werden diese über entsprechende
Volleinspannkräfte f0 als Knotenkräfte eingerechnet.
ϕ Z ,r ]
16
Grundlagen der Finite-Elemente-Methode
Für die Berechnung gilt (vgl. Gleichung 12) :
1
f = − ∫ H T p 0 l dξ
0
[Gl. 34]
0
mit: f0:
Festhaltegrößen
HT:
Verschiebungsinterpolationsmatrix (Hermite-Polynome)
ξ:
Auf die Einheitslänge bezogene Laufvariable ξ = x/l
0
p:
Vektor der Linienlasten
p0 = [ qx qy qz]T
Das negative Vorzeichen resultiert daraus, dass f0 die auf die Elementränder
(Stabenden) wirkenden Festeinspanngrößen beschreibt, also zunächst auf der linken Seite
der Gleichung 19 steht.
Da bereits bei der Steifigkeitsmatrix auf die Integration verzichtet wird, soll auch der
Vektor für die Festeinspannkräfte direkt vorgehalten werden. Dafür werden die Linienlasten
auf bestimmte Verläufe und deren Superposition beschränkt. Die Festeinspannkräfte setzen
sich (ohne Berücksichtigung von Lastausmitten oder Verformungen) wie folgt zusammen:
− β x Px
− ( 13 q x ,l + 16 q x ,r )l
⎡ N l0 ⎤ ⎡
⎤ ⎡ − 13 q x l ⎤ ⎡
⎤
⎢ 0 ⎥ ⎢
2
⎥
⎢
⎥
⎢
⎥
1
⎢ Q y ,l ⎥ ⎢− (0,35 ⋅ q y ,l + 0,15 ⋅ q y ,r )l ⎥ ⎢ − 3 q y l ⎥ ⎢(2 β y − 3) β y Py ⎥
⎢ Q z0,l ⎥ ⎢ − (0,35 ⋅ q z ,l + 0,15 ⋅ q z ,r )l ⎥ ⎢ − 13 q z l ⎥ ⎢ (2 β z − 3) β z 2 Pz ⎥
⎢ 0 ⎥ ⎢
⎥ ⎢
⎥ ⎢
⎥
0
0
⎢ M T ,l ⎥ ⎢
⎥ ⎢ 0 ⎥ ⎢
⎥
⎢ M 0 ⎥ ⎢ 1 (1,5 ⋅ q z ,l + q z ,r )l 2 ⎥ ⎢ 1 q z l 2 ⎥ ⎢ α z β z2 Pz ⋅ l ⎥
⎢ y0,l ⎥ ⎢ 301
⎥ ⎢ 151
⎥ ⎢
⎥
2
2
2
⎢ M z ,l ⎥ ⎢ − 30 (1,5 ⋅ q y ,l + q y ,r )l ⎥ ⎢− 15 q y l ⎥ ⎢ − α y β y Py ⋅ l ⎥
0
f =⎢ 0 ⎥=⎢
⎥+⎢ −1q l ⎥+⎢
⎥
− α x Px
− ( 16 q x ,l + 13 q x ,r )l
Nr
3 x
⎢
⎥ ⎢
⎥
⎢
⎥
⎢
⎥
2
⎢ Q y0,r ⎥ ⎢− (0,15 ⋅ q y ,l + 0,35 ⋅ q y ,r )l ⎥ ⎢ − 13 q y l ⎥ ⎢ (2α y − 3)α y Py ⎥
⎢ 0 ⎥ ⎢ − (0,15 ⋅ q + 0,35 ⋅ q )l ⎥ ⎢ − 1 q l ⎥ ⎢ (2α − 3)α 2 P ⎥
z
z
z ⎥
z ,l
z ,r
⎢ Q z ,r ⎥ ⎢
⎥ ⎢ 3 z ⎥ ⎢
0
⎢ M T ,r ⎥ ⎢
⎥ ⎢ 0 ⎥ ⎢
⎥
0
0
⎢ 0 ⎥ ⎢
⎥ ⎢ 1
⎢
⎥
2
2
2⎥
1
⎢ M y ,r ⎥ ⎢ − 30 (q z ,l + 1,5 ⋅ q z ,r )l ⎥ ⎢ − 15 q z l ⎥ ⎢ − α z β z Pz ⋅ l ⎥
⎢ M 0 ⎥ ⎢ 301 (q y ,l + 1,5 ⋅ q y ,r )l 2 ⎥ ⎢ 151 q y l 2 ⎥ ⎢ α y2 β y Py ⋅ l ⎥
⎦
⎦ ⎣
⎦ ⎣
⎣ z ,r ⎦ ⎣
(1)
(2)
[Gl. 35]
(3)
Hierin bezeichnet Anteil (1) linear verlaufende Streckenlasten mit dem Startwert qi,l am
linken Stabende und dem Endwert qi,r am rechten Stabende. Anteil (2) berücksichtigt einen
parabelförmigen Verlauf, bei dem qi den Maximalwert in Stabmitte angibt. Anteil (3)
beschreibt die Festhaltegrößen für eine Last Pi, die in beliebigem Abstand a < l vom linken
2 Grundlagen der Finite-Elemente-Methode
17
Stabende entfernt ist (α = a/l, β = 1 – α). Frei im Raum angreifende Stablasten müssen
zunächst auf die lokalen Stabachsen projiziert werden. Sämtliche Lasten sind positiv entlang
den Stabachsen entsprechend der Vorzeichendefinition. Bei der späteren Auswertung der
Schnittgrößenverläufe und Stabwerksverformungen müssen die örtlichen Stabeinwirkungen
ebenfalls mitbeachtet und ausgewertet werden.
az
My,l0
Pz
qz
My,r0
qx
Nl0
Qz,l0
Nr0
Px
x
ax
Qz,r0
l
z
ay
qy
Py
Mz,l0
Mz,r0
qx
Nl0
Nr0
Px
x
ax
Qy,l0
Qy,r0
y
Abbildung 2-4: Bestimmung der Festhaltekraftgrößen am Balkenelement
Aus Zeitgründen wurden im Beispielprogramm (Kapitel 8) nur konstant verlaufende
Linienlasten berücksichtigt, d.h. Anteil (1) mit qi,l = qi,r.
Für den Vektor der Festeinspanngrößen f0 gilt dieselbe Transformationsvorschrift wie
für den Vektor der Randkraftgrößen f (vgl. Gleichung 33). Die globalen Festeinspanngrößen
f 0 werden mit den globalen steifigkeitsinduzierten Randkraftgrößen zusammengefasst:
f + f 0 = f tot ⇒
Für
die
Berechnung
kv + f 0 = f tot
des
gesamten
[Gl. 36]
Stabwerkes
werden
nun
die
globalen
Randkraftgrößen und Festeinspannkräfte sowie die Koeffizienten der Steifigkeitsmatrix aller
Stabelemente – entsprechend der Inzidenzen – auf die möglichen Systemfreiheitsgrade
18
Grundlagen der Finite-Elemente-Methode
bezogen. Lagerbindungen bleiben bei diesem Schritt noch unberücksichtigt. Man erhält das
Gesamtgleichungssystem der Ordnung N (N = Anzahl der gesamten Systemfreiheitsgrade).
ˆV
ˆ + Fˆ 0 = Fˆ
K
tot
[Gl. 37]
Aus Gleichgewichtsgründen gilt:
Pˆ − Fˆ tot = 0 ⇒
Fˆ tot = Pˆ
[Gl. 38]
mit: Pˆ : Vektor der an den Knoten angreifenden äußeren Kraftgrößen
(Knotenlasten und Lagerkräfte)
Daraus ergibt sich das inhomogene lineare Gleichungssystem
ˆV
ˆ = Pˆ − Fˆ 0
K
[Gl. 39]
Die Nummerierung der Systemfreiheitsgrade erfolgt so, dass zunächst alle aktiven
(freien) und dann die durch Lagerbindungen gefesselten Freiheitsgrade berücksichtigt
werden. Durch eine derartige Umstellung des Gleichungssystemes kann man die Vektoren
der System-Freiheitsgrade, der System-Kraftgrößen wie auch die System-Steifigkeitsmatrix
entsprechend partitionieren.
ˆV
ˆ = Pˆ − Fˆ 0 ⇒ ⎡ K
K
⎢K T
⎣ c
K c ⎤ ⎡ V ⎤ ⎡ P ⎤ ⎡F 0 ⎤
⋅
=
−⎢ ⎥
K cc ⎥⎦ ⎢⎣Vc ⎥⎦ ⎢⎣Pc ⎥⎦ ⎣Fc0 ⎦
[Gl. 40]
mit: V: Vektor der aktiven Freiheitsgrade
Vc: Vektor der durch Lagerbindung gefesselten Freiheitsgrade
P: Vektor der mit den aktiven Freiheitsgraden korrespondierenden
Knotenlasten.
Pc: Lagerkraftgrößen.
Fo: Vektor der mit den aktiven Freiheitsgraden korrespondierenden
System-Festeinspannkraftgrößen
Fc0 : Vektor der mit den gefesselten Freiheitsgraden korrespondierenden
System-Festeinspannkraftgrößen
Für ein Stabwerkssystem sind üblicherweise gegeben:
•
die äußeren Knotenlasten P der aktiven Freiheitsgrade,
•
die Verschiebungsgrößen Vc der gefesselten Freiheitsgrade und
•
die System-Festeinspannkraftgrößen Fo und Fc0 .
2 Grundlagen der Finite-Elemente-Methode
19
Die obere bzw. untere Zeile des partitionierten Gleichungssystems kann nun nach den
unbekannten Größen aufgelöst werden. Es folgt dann für den Vektor V der aktiven
Freiheitsgrade:
KV + K c Vc = P − F 0 ⇒ KV = P − K c Vc − F 0
⇒ V = K −1 (P − K c Vc − F )
[Gl. 41]
Die aktiven Verschiebungsgrößen können durch Lösen des linearen Gleichungssystems
oder durch Multiplikation mit der Invertierten der Matrix K ermittelt werden.
Aus der unteren Seite des partitionierten Gleichungssystems kann der Vektor Pc der
Lagerkraftgrößen ermittelt werden.
K cT V + K cc Vc = Pc − Fc0 ⇒ Pc = K cT V + K cc Vc + Fc0
[Gl. 42]
Damit sind alle unbekannten Größen des Systems bestimmt. In der Nachlaufrechnung
folgt nun
•
die Rücktransformation der globalen System-Verschiebungsgrößen V auf die
lokalen Element-Randverschiebungsgrößen v bzw. v,
•
die Berechnung der Element-Randkraftgrößen f durch Multiplikation von v mit
der Element-Steifigkeitsmatrix k und das Einrechnen der Festeinspanngrößen
•
die Anpassung der Element-Randkraftgrößen an die Vorzeichenkonvention der
Stabstatik (Vorzeichenwechsel am linken Stabende) und
•
die Konstruktion der Schnittgrößenverläufe zwischen den Knoten unter
Beachtung der örtlichen Stabeinwirkungen.
Mit diesen Ergebnissen können die Schnittgrößenverläufe über die einzelnen Elemente
des Stabwerkes sowie die Verformungen des Gesamttragwerkes dargestellt werden.
20
Software-Entwurf
3
Software-Entwurf
3.1
Verschiedene Entwurfsverfahren
In der Praxis nehmen Programme meist einen Umfang an, bei dem die
Überschaubarkeit nicht mehr ohne weiteres gewährleistet ist. Deshalb ist eine Zerlegung der
Gesamtaufgabe in kleinere Teile, die unabhängig voneinander verstanden und bearbeitet
werden können, zweckmäßig. Für diese Zerlegung zur Bewältigung der Komplexität eines
Systems wurden viele verschiedene Design- und Analysemethoden entwickelt. In der
Literatur gibt es unterschiedliche Ansätze die verschiedenen Entwurfsverfahren zu
klassifizieren und zu unterscheiden. Grundsätzlich kann man eine Einteilung der
Designmethoden in drei Kategorien vornehmen:
•
Streng hierarchisch strukturiertes Design
•
Datenorientiertes Design
•
Objektorientiertes Design
Wie bereits erwähnt, gibt es für das Design eines komplexen Software-Systems kein
Universalrezept, und es gibt keine „beste“ Designmethode. Daher ist es nötig, sich zu
überlegen, mit welchem Design-Konzept sich die Anforderungen an ein bestimmtes
Software-System am besten erfüllen lassen [5]. Im Folgenden werden die verschiedenen
Entwurfsverfahren
kurz
vorgestellt
und
ihre
Eignung
für
den
Entwurf
eines
Programmsystems zur allgemeinen Tragwerksanalyse (hauptsächlich FEM) diskutiert.
Die vorgestellten Entwurfsverfahren sind mehr oder weniger eng mit verschiedenen
Programmierstilen und -sprachen verbunden. Auf die Eigenschaften der verschiedenen
Programmiersprachen und ihre Eignung zur Umsetzung eines Entwurfes wird in Kapitel 5
näher eingegangen.
3.1.1
Streng hierarchisch strukturiertes Design (prozedural)
Die unterschiedlichen Varianten des streng hierarchisch strukturierten Designs (auch
Top-Down-Entwurf) basieren auf einer algorithmischen Zerlegung. Dies bedeutet, dass das
Problem in einen Baum aus Teilproblemen aufgeteilt wird, die entlang der Baumtopologie
von der Wurzel aus bearbeitet werden. Die einzelnen Teilprobleme werden im Programm
als Funktionen mit einer Reihe von Funktionsargumenten und einem Rückgabewert
abgebildet. Das streng hierarchisch strukturierte Design ist das am meisten verbreitete und
älteste der drei Entwurfsverfahren [28]. Schätzungen gehen davon aus, dass auf diese Weise
3 Software-Entwurf
21
Probleme bis zu einer Größenordnung von 100.000 Programmzeilen gut bewältigt werden
können [28]. Heutzutage sind die meisten Programmiersprachen prozedural, zwei ihrer
verbreitetsten Vertreter sind Fortran und C.
3.1.2
Datenorientiertes Design (funktional)
Der datenorientierte Entwurf konzentriert sich hauptsächlich auf den Datenfluss
innerhalb eines Problems. In einem ersten Schritt werden die einzelnen Informationsquellen
und –senken einer Anwendung ermittelt. Danach werden Untersuchungen über die
Datenumsätze zwischen den gefundenen Anwendungskomponenten durchgeführt. Mittels
der gewonnenen Erkenntnisse über die Informationsflüsse gelangt man zu einer
Programmstruktur. Ein wesentlicher Nachteil der Methode besteht darin, dass dieser
Übergang nicht unmittelbar möglich ist, d.h. es existiert keine eindeutige und vollständige
Umsetzungsmöglichkeit der Datenflüsse in Programmstrukturen. Allerdings können mit
dieser Methode auch komplexe Systeme bewältigt werden. Das Verfahren wird besonders
zum Entwurf von Informations-Managementsystemen (z.B. Flugbuchungssystemen)
eingesetzt, in denen Datenflüsse gegenüber anderen Komponenten dominieren und bei
denen zeitkritischen Ereignissen kaum Beachtung geschenkt werden muss. Aufgrund der
Einbußen in der Ausführungsgeschwindigkeit ist das datenorientierte Design unüblich für
intensive numerische Berechnungen, es wurde jedoch bereits für FE-Programme eingesetzt
[28]. Eine verbreitete funktionelle Programmiersprache ist z.B. Lisp.
3.1.3
Objektorientiertes Design
Objektorientierte
Repräsentationen
sind
ein
Hybrid.
Objektorientierte
Entwurfsverfahren versuchen Anwendungen durch eine Sammlung von miteinander
kommunizierenden, hierarchischen Objekten abzubilden. Jedes Objekt ist die Instanz einer
Klasse und stellt eine jeweils abgeschlossene Einheit mit gekapselten Informationsbestand
und darauf operierenden Algorithmen dar. Diese Algorithmen sind für andere Objekte durch
feste Schnittstellen zugänglich [10]. Die Klasse ist wiederum ein Element in einer
Klassenhierarchie. Der fundamentale Baustein im objektorientierten Design ist also das
Objekt, nicht die Funktion oder die Datenstruktur [5]. Das Abstraktionslevel eines Objektes
ist im Vergleich zu dem eines Algorithmus ungleich höher. Das objektorientierte Design
bietet sich an für Programmsysteme, bei den Daten und Funktionen gleichviel Bedeutung
zukommt. Die Entwicklung von Software auf der Grundlage objektorientierter Verfahren ist
vergleichsweise neu, besonders wenn ihre Verwendung in großen, industriellen Projekten
22
Software-Entwurf
betrachtet wird. In den letzen Jahren wurden diese Verfahren vermehrt auch im
ingenieurwissenschaftlichen Bereich propagiert, u.a. für die Realisierung von FEMProgrammen
(z.B.
Dubois-Pelerin
et
al.
[11]+[12]).
Populäre
Vertreter
von
objektorientierten Programmiersprachen sind Smalltalk und C++.
3.2
Vergleich und Auswertung
Grundsätzlich sind alle drei Entwurfsverfahren für ein Programmsystem zur
Tragwerksanalyse
denkbar
und
bereits
verwendet
worden.
Jedes
dieser
Programmierparadigmen hat seine Vor- und Nachteile. Je nachdem welche Gewichtung man
den einzelnen Kriterien zur Auswahl des Entwurfsverfahren gibt und welche Ansprüche
man an das „fertige“ Software-System stellt, wird man unterschiedliche Design-Methoden
wählen. Im Folgenden soll die Eignung der vorgestellten Verfahren für den Entwurf eines
Programmsystems zur Tragwerksanalyse verglichen werden. Es wird vor allem auf das
prozedurale Design - das übliche Verfahren für numerische Programme – und auf das
objektorientierte Paradigma eingegangen.
Für das zu erarbeitende Programmsystem soll vor allem die Portabilität und die
Erweiterbarkeit im Vordergrund stehen, es wird ein globaler, modular aufgebauter
Programmentwurf gefordert. Die Portabilität eines Programms ist hauptsächlich abhängig
von der Wahl der Programmiersprache und daher nur indirekt von dem gewählten
Entwurfsverfahren abhängig. Dagegen ist die Erweiterbarkeit eines Programmsystems
etwas, das schon beim Design der Architektur berücksichtigt werden muss. Damit ein
Entwurf ausbaubar ist, muss die bestehende Programmarchitektur modular aufgebaut sein
und klar definierte Schnittstellen bereithalten. Außerdem sollte die Architektur logisch
strukturiert und für jeden Benutzer einfach zu verstehen sein. Dieses lässt sich vor allem
durch zwei Mittel erreichen: eine durchgehende Dokumentation der Architektur und des
Programmcodes und eine sich selbst erklärende und durchschaubare Aufteilung des
komplexen Systems in logische Untereinheiten.
Das „sich-selbst-Erklären“ eines Programmsystems wird vor allem durch den
objektorientierten Entwurf gefördert, denn:
„Das beste Modell eines Problemfeldes ist das Problemfeld selbst.“ [28]
Der Mensch betrachtet seine Umwelt als eine Sammlung von Personen, Gegenständen
usw., die bestimmte Eigenschaften haben, und sich durch bestimmte gegenseitige
Interaktionen auszeichnen. Aus diesen Überlegungen folgt, dass der einfachste Weg eine
Anwendung zu entwerfen darin besteht, deren natürliche oder abstrakte Konzepte durch die
3 Software-Entwurf
23
Imitation der menschlichen Begriffsbildung zu ermitteln [28]. Für ein FEMProgrammsystem zur Tragwerksanalyse ergibt sich z.B. eine Einteilung in Objekte wie etwa
Element, Knoten und Material. Diese Einteilung ist logisch nachvollziehbar und wird durch
das Problemfeld bestimmt, dass heißt sie ist weitgehend unabhängig vom umsetzenden
Programmierer.
Die Schwierigkeit bei konventionellen (prozeduralen) Programmen ist, dass die
Unterteilung in die verschiedenen Algorithmen zum großen Teil willkürlich gewählt werden
kann. Zusätzlich ist ein streng sequentieller Top-Down-Entwurf meist nicht direkt
umsetzbar. Einzelne Algorithmen werden durch Schleifen und GoTo – Anweisungen
ineinander verschachtelt. Dadurch wird das Programmsystem schnell unüberschaubar, und
ohne weitgehende Dokumentation nicht mehr nachvollziehbar.
Ein weiterer großer Unterschied zwischen einem konventionellen und einem
objektorientierten Programm besteht in der Behandlung und Speicherung der Daten. In
einem konventionellen (hierarchisch strukturierten) Programm kann fast jede Funktion auf
alle Daten zugreifen und diese manipulieren, die Daten sind passiv [1]. Das birgt große
Nachteile, da durch die zwangsläufige Zuordnung einer Datenstruktur zu mehreren
Funktionen ihre Beschreibung über die Systemstruktur verstreut wird. Im Lebenszyklus
eines Systems sind die Funktionen im Allgemeinen die sich am häufigsten ändernden Teile
der Software. Sind aufgrund veränderter Anforderungen Modifikationen der Datenstruktur
nicht zu umgehen, ziehen diese durch die Verflechtung der Daten mit den Funktionen nur
schwer zu übersehende Änderungen verschiedenster Systemteile nach sich. Oft ist die
komplette Überarbeitung der funktionsorientierten Systemstruktur notwendig. Der
Softwareentwickler hat die mühsame Aufgabe, durch alle Funktionen hindurch die
Konsistenz des Programms nach Änderungen zu sichern [9].
In einem objektorientierten Programm werden die Daten gekapselt, ausgehend von der
Prämisse, dass die Datenstruktur der stabilere Teil eines Programms ist. Man spricht von
aktiven Daten, da sich Daten immer in Objekten manifestieren und diese nur die Ausführung
spezifischer Methoden zulassen. Da alle Datenmanipulationen durch das Objekt selbst
erfolgen, ist unmittelbar klar, wo die Fehlerquelle liegt, falls Dateninkonsistenz auftritt.
Fehlersuche und –behebung ist auf ein einziges Objekt beschränkt.
24
Software-Entwurf
Hauptprogramm
Dateneingabe
(Elemente, Knoten,
Lasten)
Gesamtsteifigkeitsmatrix
erstellen
Aufstellen des
Lastvektors
Berechnung des Systems
Daten
Zugriff auf Daten in einem konventionellen Programm
Element
Gesamtsystem
Knoten
Kapselung der Daten in einem objektorientierten Programm
Abbildung 3-1: Datenzugriff in prozeduralen und objektorientierten Programmen (aus [1])
In einem Programm zur Tragwerksanalyse kann eine Änderung der Datenstruktur z.B.
in der Umstellung der Abspeicherung einer Matrix als Bandmatrix oder Skyline-Matrix
bestehen. Jede Funktion, die auf eine Matrix zugreift (Einlesen der Elementmatrizen, Lösen
des Gleichungssystems etc.), muss nun abgeändert werden, um die neue Datenstruktur
verarbeiten zu können. In einem objektorientierten Programm wird eine Matrix durch eine
eigene Klasse implementiert. Auf die Matrixelemente kann nur mit den von der MatrixKlasse zur Verfügung gestellten Methoden zugegriffen werden. Eine Änderung der
Speicherung der Matrixelemente wirkt sich daher nur in der Implementierung der Methoden
aus, die Schnittstelle der Klasse an sich bleibt konstant.
Das Konzept der Polymorphie (vgl. Kapitel 4.2.6) bietet darüber hinaus die
Möglichkeit, Methoden bereits bestehender Klassen zu erweitern, ohne das die bereits
3 Software-Entwurf
25
vorhandene Implementierung verändert werden muss. Derselbe Methodenaufruf kann z.B.
bei der Übergabe unterschiedlicher Parameter (Typ, Anzahl etc.) unterschiedliche Aktionen
hervorrufen.
Das Objekt ist also eine geschlossene Informationseinheit. Derart strukturiertes Wissen
erhöht die Modularität und folglich auch die Transparenz und Wiederverwendbarkeit der
Repräsentation [10]. Durch die objektorientierte Vorgehensweise verspricht man sich, den
Entwicklungsprozess von Programmen mit einer Größe von weit über 100.000 Zeilen
beherrschbar zu machen. Systeme dieser Größe sind im Bereich der Tragwerksanalyse
durchaus üblich [28].
Die Konzepte der objektorientierten Programmierung beinhalten also viele vorteilhafte
Strukturen, die in einem konventionellen Programm nur schwer umsetzbar sind. Software
wird wiederverwendbar, Schnittstellen werden konsistenter und es entstehen geringere
Wartungskosten. Zusätzlich kann durch die häufigere Verwendung und damit durch das
häufigere Testen dieser Softwarekomponenten mit einer geringeren Fehlerträchtigkeit
gerechnet werden.
Ein großer Nachteil ist, dass die Ausführungszeit objektorientierter Programme
gegenüber streng hierarchisch strukturierten ansteigt. Durch das Botschaften-Konzept und
eventuell mehrfach indirektes Aufrufen von Methoden entsteht ein Overhead an
zusätzlichen Operationen. Der zusätzliche interne Verwaltungsaufwand für den Zugriff auf
Methoden ist nicht zu vernachlässigen. Das ist für rechenintensive Programme ein nicht zu
unterschätzender Nachteil [9].
Weiterhin steigt der Programmumfang sowohl des Quelltextes als auch des übersetzten
Programms an. Durch Hierarchisierung (vgl. Kapitel 4.2.5) steigt die Komplexität des
Programms. Allerdings kann man festhalten, dass die Komplexität z.B. einer
Vererbungsstruktur deutlich einfacher handhabbar ist als die Komplexität von hierarchisch
strukturierten Funktionen oder Prozeduren.
Trotz der im Vergleich zu den prozeduralen Ansätzen unbestreitbar erhöhten
Flexibilität wird immer wieder festgestellt, dass in vielen Situationen die erwartete und
erwünschte Flexibilität nicht erreicht werden kann. So sind beispielsweise Erweiterungen in
den Klassenhierarchien, die nicht bereits in der Anfangsphase des Entwurfs berücksichtigt
wurden, nur mit großem Aufwand durchzuführen. Eine zu allgemeine Konzeption von
Beginn an führt jedoch zu unübersichtlichen und laufzeitineffizienten Programmen.
Gleichzeitig steigt das vom Entwickler erwartete Wissen über Programmstruktur und –
hierarchie überproportional an. Das Kernproblem der Anwendung objektorientierter
26
Software-Entwurf
Techniken für numerische Simulationen liegt demzufolge in der angemessenen
programmtechnischen Darstellung der Abhängigkeiten zwischen den Algorithmen und der
zugehörigen Datenstruktur. Chudoba [8] propagiert in seinem Artikel den Einsatz
generischer Techniken (algorithmusorientierter Ansatz), die dieses Problem lösen können.
Er beschreibt den Einsatz von metaobjects, mit deren Hilfe z.B. die Instantiierung der
Objekte oder die Festlegung der Übergabe- und Rückgabeparameter von Funktionen zur
Laufzeit und von der Auswertung getrennt stattfinden kann. Somit werden z.B. alle Matrizen
einer Berechnung mit den korrekten Dimensionen instanziiert, bevor die eigentliche
Berechnung
stattfindet.
Dieser
Ansatz
erhöht
allerdings
die
Komplexität
des
Programmsystems wieder ungemein.
Im
Folgenden
wird
der
objektorientierte
Ansatz
für
den
Entwurf
eines
Programmsystems gewählt. Dieser bietet für ein Programmsystem zur Tragwerksanalyse
viele
Vorteile
gegenüber
dem
steng
hierarchisch
strukturierten
Design.
Die
Programmarchitektur wird übersichtlicher und leichter verständlich. Eine Erweiterung oder
Anpassung eines bestehenden Programms für spezielle Aufgabenstellungen wird durch das
dezentralisierte Konzept unterstützt. Das Einfügen von neuen Klasen wird möglich.
Bestehende Klassen können in einem anderen Kontext wieder- und weiterverwendet werden
ohne ihre Implementierung zu kennen, da die Schnittstellen konstant bleiben. Die
Datenverwaltung wird übersichtlich, da jedes Objekt (z.B. Finites Element) seine eigenen
Daten speichert und verwaltet.
4 Objektorientierte Analyse und Design
4
27
Objektorientierte Analyse und Design
Als objektorientierte Analyse (OOA) wird der Prozess bezeichnet, der die Daten,
Prozesse und Steuerung eines objektorientierten Programms bestimmt. Die Daten
entsprechen den Objekten bzw. Klassen und deren Struktur. Prozesse beschreiben das lokale
Verhalten von Methoden, die Steuerung legt das globale Verhalten fest. Die Analyse ist
zunächst unabhängig von einer bestimmten Programmiersprache.
Dagegen legt der objektorientierte Entwurf (OOD) die Objekte und deren Attribute fest.
Er bestimmt weiterhin die Sichtbarkeit der Objekte untereinander und die Schnittstellen.
In der Praxis ist eine strenge Trennung zwischen objektorientierter Analyse und
objektorientiertem Entwurf kaum einzuhalten. Beide Prozesse werden unter dem Begriff
objektorientierte Analyse und Design (OOAD) zusammengefasst.
Den
neuesten
Stand
der
Entwicklung
objektorientierter
Analyse-
und
Entwurfsmethoden stellt die Unified Modeling Language (UML) dar. Mehrere
Protagonisten namhafter Techniken (Booch, Rumbaugh und Jacobson) arbeiten inzwischen
zusammen und haben sich der Entwicklung der UML verschrieben [9]. In Kapitel 4.1 wird
zunächst die UML als Notation für objektorientierte Strukturen vorgestellt. Die Konzepte
der Objektorientierung werden in Kapitel 4.2 dargestellt und an Beispielen erläutert, die
bereits dem Problemfeld der FEM entstammen und in UML notiert sind.
4.1
Unified Modeling Language (UML)
4.1.1
Ziele der UML
UML ist eine Sprache zur Spezifikation, Visualisierung, Konstruktion und
Dokumentation von Softwaresystemen. Ihr Ziel ist insbesondere die Unterstützung
objektorientierter und komponentenbasierter Systeme. Weitere Ziele beim Entwurf waren
1. eine ausdrucksstarke visuelle Notation von Modellen zu geben,
2. die Erweiterbarkeit und Spezialisierbarkeit der Sprache selbst zu erreichen,
3. die Unabhängigkeit von Programmiersprachen,
4. eine formale Basis für die Modellierung zu schaffen,
5. Chancen
für
eine
Vergrößerung
des
Marktes
für
Werkzeuge
in
der
objektorientierten Analyse und Entwurf sowie
6. die Unterstützung von Frameworks (Anwendungs-„Rahmen“), Mustern und
Komponenten.
28
Objektorientierte Analyse und Design
Dabei will UML die Notation und deren Semantik beschreiben, nicht jedoch
bestimmen, mit welchem Prozess dieses Ziel erreicht wird.
Neben den Prozessen deckt UML Programmiersprachen und Werkzeuge ausdrücklich
nicht ab. Da es sich um einen Formalismus handelt, wird davon ausgegangen, dass die
Transformation eines entsprechenden Modells in eine beliebige objektorientierte
Programmiersprache möglich ist [9]. Programmiersprachen für die Umsetzung des
Entwurfes aus Kapitel 5 werden ausführlich in Kapitel 6 diskutiert.
4.1.2
Bestandteile der UML
Im Folgenden werden die Kernkonzepte der UML zusammen mit ihrer grafischen
Notation kurz vorgestellt. Für die Beschreibung des Konzeptes für ein Programmsystem zur
Tragwerksanalyse werden nicht alle Bestandteile der UML benötigt, der Vollständigkeit
halber werden aber alle kurz vorgestellt. Es werden dabei die Darstellungen verwendet, wie
sie von Booch, Rumbaugh und Jacobson 1999 in „Das UML-Benutzerhandbuch“ [6]
festgelegt werden. Begriffe aus der Objektorientierung wie Objekt, Klasse, Attribute,
Methoden, Hierarchie etc. werden in Kapitel 4.2 noch grundlegend definiert, hier soll
zunächst die Vorstellung der grafischen Notation stattfinden. Eine Kurzübersicht über die
Notationen in der UML (aus [26]) wird zusätzlich in den Anhang gestellt.
Das Vokabular der UML umfasst drei Arten von Bestandteilen: Dinge, Beziehungen
und Diagramme.
Dinge sind die Abstraktionen des Modells, man unterscheidet zwischen den statischen
und dynamischen Bestandteilen, Gruppierungen und Kommentaren.
•
Strukturelemente sind die statischen Teile eines Modells und repräsentieren
konzeptionelle oder physische Elemente. Dazu zählen
o Klassen
ElementFEM
stiffnessMatrix
massMatrix
...
computeStiffnessMatrix()
computeMassMatrix()
assembleStiffnessMatrix()
...
Æ Name der Klasse
Attribute der Klasse
Methoden der Klasse
Abbildung 4-1: Klassen
4 Objektorientierte Analyse und Design
29
o Schnittstellen
| Interface
Abbildung 4-2: Schnittstellen
o Kollaborationen (Interaktionen mit strukturellen und verhaltensorientierten
Dimensionen)
Verantwortlichkeitskette
Abbildung 4-3: Kollaborationen
o Anwendungsfälle
(Beschreibung
einer
Menge
aufeinanderfolgender
Aktionen, die ein beobachtbares Ergebnis hervorbringt)
Auftrag erteilen
Abbildung 4-4: Anwendungsfälle
o aktive Klassen (Klasse deren Objekte Steuerungsaktivitäten in Gang setzen
können)
EreignisManager
...
throw()
dismiss()
...
Abbildung 4-5: Aktive Klassen
o Komponenten (physisches Paket von logischen Elementen wie z.B. Klassen,
Schnittstellen und Kollaborationen).
Profilbibliothek
Abbildung 4-6: Komponenten
30
Objektorientierte Analyse und Design
o Knoten (Ein zur Laufzeit vorhandenes physisches Element, das eine
Rechnerresource repräsentiert und im Allgemeinen einen Speicher und oft
auch Rechenkapazität besitzt.)
Server
Abbildung 4-7: Knoten
•
Verhaltensweisen sind die dynamischen Bestandteile eines Modells, mit zwei
Hauptarten
o Interaktion (Verhaltensweise, die eine Menge von Nachrichten umfasst,
welche von einer Menge von Objekten in einem bestimmten Kontext zum
Erreichen eines bestimmten Zweckes ausgetauscht werden.)
Anzeigen()
Abbildung 4-8: Nachrichten
o Automat (Spezifikation der Folge von Zuständen eines Objektes oder einer
Schnittstelle)
Warten
Abbildung 4-9: Zustände
•
Gruppierungen (Pakete zur Organisation)
Geschäftsregeln
Abbildung 4-10: Pakete
4 Objektorientierte Analyse und Design
•
31
Kommentare (Notizen)
Notiz
Abbildung 4-11: Notizen
In der UML gibt es vier Arten von Beziehungen:
•
Abhängigkeit (semantische Beziehung zwischen zwei Gegenständen, wobei eine
Änderung des unabhängigen Gegenstandes die Semantik des abhängigen
Gegenstandes beeinflusst.)
Abbildung 4-12: Abhängigkeiten
•
Assoziation (Strukturbeziehung, die eine Menge von Objektbeziehungen beschreibt.
Sie kann gerichtet sein, eine Beschriftung, Multiplizitäten (mögliche Anzahl der
beteiligten Objekte), Rollennamen u.ä. enthalten.)
1..*
Element
1
Struktur
Abbildung 4-13: Assoziationen
•
Generalisierung (Beziehung zwischen dem Allgemeinen und dem Speziellen)
Abbildung 4-14: Generalisierungen
•
Realisierung (z.B. zwischen Schnittstelle und ausführender Stelle)
Abbildung 4-15: Realisierungen
32
Objektorientierte Analyse und Design
Diagramme sind die verschiedenen Sichtweisen einer Architektur. Man unterscheidet
zwischen Diagrammen, die die statischen und die dynamischen Sichtweisen eines Systems
darstellen.
Strukturdiagramme
(statische Sichtweise)
Verhaltensdiagramme
(dynamische Sichtweise)
1. Klassendiagramm
1. Anwendungsfalldiagramm
2. Objektdiagramm
2. Sequenzdiagramm
3. Komponentendiagramm
3. Kollaborationsdiagramm
4. Einsatzdiagramm
4. Zustandsdiagramm
5. Aktivitätsdiagramm
Tabelle 4-1: Diagramme der UML
Diese neun Arten von Diagrammen definieren die UML. Dasselbe Ding kann in einem
System mehrfach in demselben oder in verschiedenen Diagrammen auftreten. Jedes
Diagramm bietet eine Sicht auf die Elemente, aus denen das System besteht [6].
Strukturdiagramme
•
Ein Klassendiagramm zeigt eine Menge von Klassen, Schnittstellen und Kollaborationen
sowie deren Beziehungen, es ist der häufigste Diagrammtyp. Klassendiagramme stellen
die statische Entwurfssicht eines Systems dar. Enthalten sie aktive Klassen, stellen sie
die statische Prozesssicht eines Systems dar.
•
Ein Objektdiagramm zeigt eine Menge von Objekten und ihre Beziehungen. Es
repräsentiert statische Momentaufnahmen der Instanzen von Gegenständen aus
Klassendiagrammen und stellt damit wie die Klassendiagramme die statische Entwurfsoder Prozesssicht eines Systems dar, allerdings aus der Perspektive tatsächlicher oder
prototypischer Fälle.
•
Ein Komponentendiagramm zeigt die Organisation und die Abhängigkeiten einer Menge
von Komponenten. Solche Diagramme stellen die statische Implementierungssicht eines
Systems dar. Sie hängen insofern mit Klassendiagrammen zusammen, als eine
Komponente sich üblicherweise auf eine oder mehrere Klassen, Schnittstellen oder
Kollaborationen abbilden lässt.
•
Einsatzdiagramme zeigen die Konfiguration der im Prozess befindlichen Knoten zur
Laufzeit sowie der auf ihnen existierenden Komponenten. Solche Diagramme stellen die
4 Objektorientierte Analyse und Design
statische
Einsatzsicht
einer
33
Architektur
dar.
Sie
hängen
insofern
mit
Komponentendiagrammen zusammen, als ein Knoten üblicherweise eine oder mehrere
Komponenten einschließt.
Verhaltensdiagramme
•
Ein Anwendungsfalldiagramm organisiert die Verhaltensweisen eines Systems. Es zeigt
eine Menge von Anwendungsfällen sowie Akteuren und ihren Beziehungen.
Anwendungsfalldiagramme stellen die statische Anwendungsfallsicht eines Systems dar.
•
Sequenz- und Kollaborationsdiagramme sind Interaktionsdiagramme. Sie zeigen eine
Interaktion, die aus einer Menge von Objekten und deren Beziehungen einschließlich der
unter ihnen versendeten Nachrichten besteht. Interaktionsdiagramme stellen die
dynamische Sicht eines Systems dar.
Beim Sequenzdiagramm steht die zeitliche
Abfolge der Nachrichten im Vordergrund, beim Kollaborationsdiagramm die strukturelle
Organisation der Objekte.
•
Ein Zustandsdiagramm zeigt einen aus Zuständen, Zustandsübergängen, Ereignissen und
Aktivitäten bestehenden Automaten. Besondere Bedeutung kommt ihm beim
Modellieren des Verhaltens einer Schnittstelle, Klasse oder Kollaboration zu. Das nach
Ereignissen geordnete Verhalten eines Objektes steht im Vordergrund. Ein
Aktivitätsdiagramm ist ein Sonderfall des Zustandsdiagramms, der den Fluss von einer
Aktivität zur anderen innerhalb eines Systems zeigt.
4.2
Konzepte und Definitionen der objektorientierten Programmierung
Um das Prinzip der Objektorientierung zu verstehen, müssen zunächst Definitionen für
einige Begriffe gegeben werden. Im folgenden Abschnitt werden die wichtigsten Begriffe
und Konzepte des objektorientierten Designs näher erläutert. Die Definitionen sind in der
Literatur oft nicht einheitlich. Die jüngste Literatur bezieht sich zunehmend auf die
Objektdefinition, die auch der UML zugrunde liegt. Diese Definition wird auch im
Folgenden zugrundegelegt.
Soweit notwendig soll die Anwendung der Konzepte der objektorientierten
Programmierung anhand von Beispielen für die Anwendung auf die Methode der finiten
Elemente erläutert werden. Die Notation der Beispiele orientiert sich an der bereits
vorgestellten grafischen Darstellung der UML.
34
Objektorientierte Analyse und Design
Zunächst werden die Begriffe Objekt, Klasse, Methode und Attribut definiert. Dann
werden die Hauptelemente des Objektmodells vorgestellt. Diese sind nach Booch [5]:
•
Abstraktion
•
Kapselung
•
Modularität
•
Hierarchie
Hauptelement bedeutet, dass ein Modell, in dem eines dieser Elemente fehlt, nicht im
engeren Sinne objektorientiert ist. Dazu gibt es drei weniger wichtige Konzepte, die nicht
speziell objektorientiert sind:
•
Typisierung
•
Nebenläufigkeit
•
Persistenz
Statt der Typisierung wird das (allgemeinere) Konzept der Polymorphie erläutert,
zusätzlich wird auf die Generizität eingegangen.
4.2.1
Basisdefinitionen
4.2.1.1
Objekt
Ein Objekt abstrahiert einen Teil des Problembereichs. Es repräsentiert eine
Gruppierung von Informationen, sowie die Beschreibung, wie diese Informationen
behandelt werden sollen. Es repräsentiert beispielsweise ein Ding, eine Person, einen
Begriff, einen Vorgang, einen Zusammenhang, ein Ereignis, eine Beziehung, ein abstraktes
Konzept oder ein Ergebnis. Booch [5] definiert ein Objekt folgendermaßen:
•
Ein Objekt hat einen Status (Zustand, Daten), es weist ein wohldefiniertes
Verhalten auf (Operationen, Methoden) und es besitzt eine eindeutige
Objektidentität.
•
Ein Objekt kapselt seine Informationen (Daten) als Attribute und bietet
Interaktionen als Dienste (Operationen, Methoden) an.
Ein Objekt ist in der programmtechnischen Umsetzung immer die Instanz einer Klasse.
Als aktive Objekte bezeichnet man Objekte, die einen Prozess oder Thread1 besitzen und
Kontrollaktivitäten initiieren können .
1
Ein Prozess ist ein schwergewichtiger Kontrollfluss, der nebenläufig mit anderen Prozessen ausgeführt
werden kann. Ein Thread ist ein leichtgewichtiger Kontrollfluss, der nebenläufig mit anderen Threads im
gleichen Prozess ausgeführt werden kann.
4 Objektorientierte Analyse und Design
4.2.1.2
35
Klasse
Unter der Klasse versteht man eine Beschreibung für alle Objekte, die dieselbe Struktur
aufweisen. Eine Klasse spezifiziert demnach die gemeinsamen Eigenschaften und das
gemeinsame Verhalten der von ihr erzeugten Objekte (Instanz). Eine Klassenbeschreibung
umfasst:
•
den Namen der Klasse
•
den internern Aufbau der Objekte dieser Klasse
•
eine Beschreibung aller Methoden, die auf Objekte dieser Klasse angewendet werden
können.
Eine Klasse implementiert eine oder mehrere Schnittstellen. Dazu gehören
insbesondere alle Methoden, die öffentlich (d.h. von anderen Klassen oder Funktionen)
aufgerufen
werden
können.
Die
Implementierungen
dieser
Methoden,
d.h.
die
zugrundliegenden Algorithmen, sollten privat bleiben und nur innerhalb der Klasse sichtbar
sein. Klassen repräsentieren somit einen Bauplan, der angibt, wie die Objekte aufgebaut sind
und welches Verhalten die Objekte besitzen werden, die zu dieser Klasse gehören [1]. Jedes
Objekt, das nach dem Bauplan der Klasse erstellt wird, wird Instanz dieser Klasse genannt.
Die Begriffe Objekt und Instanz werden synonym verwendet. Jede Instanz besitzt
spezifische Informationen, die sie von anderen Instanzen derselben Klasse unterscheidet.
Um ein Objekt eindeutig mit einer Nachricht ansprechen zu können, ist jedes Objekt
singulär und durch einen Namen von anderen Objekten unterschieden. Die Anzahl der
Instanzen einer Klasse ist nicht statisch und kann zur Laufzeit variieren [10].
Wenn eine Vererbungshierarchie aufgebaut wird (vgl. Kapitel 4.2.5), werden in diese
Hierarchie auch Klassen eingefügt, die nur der Strukturierung der verschiedenen Klassen
dienen. Von dieser Klasse ist also nicht beabsichtigt, Instanzen zu bilden. Sie werden als
abstrakte Klassen bezeichnet. Ihr Gegenstück sind konkrete Klassen [9]. Eine aktive Klasse
ist eine Klasse, deren Objekte aktive Objekte sind.
4.2.1.3
Methoden
Methoden bezeichnen Funktionen, die von einem Objekt ausgeführt werden. Die
Begriffe Methode, Operation und Dienst werden synonym verwendet und beziehen sich auf
den Definitionscode der Methode [1]. Methoden werden aktiviert, wenn dem Objekt eine
Nachricht gesendet wird. Jedes Objekt besitzt eine Liste, das Protokoll, in der die
Nachrichten beschrieben sind, auf die das Objekt durch Auswahl einer geeigneten Methode
36
Objektorientierte Analyse und Design
antworten kann. Die Sichtbarkeit einer Methode gibt an, ob sie von anderen Klasse benutzt
werden kann.
Die Sichtbarkeit einer Methode wird in der UML mit den Symbolen +,# und –
gekennzeichnet, die wie folgt definiert sind:
+ public (öffentlich)
Jede andere Klasse, die mit dieser Klasse in einer
Beziehung steht, und für die diese Klasse sichtbar ist (vgl.
Kapitel 4.2.5), kann dieses Merkmal nutzen.
# protected (geschützt)
Jede Spezialisierung der Klasse kann dieses Merkmal
nutzen
– private (privat)
Nur die Klasse selbst kann dieses Merkmal nutzen.
Existenzielle Methoden einer Klasse sind der Konstruktor und der Destruktor. Ein
Konstruktor wird bei der Erzeugung eines Objektes einer Klasse implizit aufgerufen und
initialisiert das Objekt. Der Destruktor wird implizit bei der Zerstörung des Objektes
aufgerufen. Seine Aufgabe ist es, die durch das Objekt belegten Ressourcen wieder
freizugeben.
Virtuelle Methodentabellen (VMT) sind eine Möglichkeit, Zugriffe auf die Methoden
einer Klasse auch bei mehrfacher Instantiierung zu verwalten. Sie erlauben sowohl die
Behandlung statischer als auch dynamischer Methoden. Anstatt mit jedem Objekt eine
Kopie der darauf anzuwendenden Methode zu erstellen (speicherplatzintensiv) wird die
Methode einer Klasse an einer Stelle angelegt und die Instanzen der Klassen enthalten nur
einen Verweis auf diese Stelle [9]. Virtuelle Methodentabellen sind Bestandteile mancher
Programmiersprachen und werden beim Kompilieren angelegt.
4.2.1.4
Attribute
Attribute bezeichnen Eigenschaften von Objekten, die in Form von Daten gespeichert
werden. Die Daten sollten in der Regel nicht öffentlich, sondern in der Klasse gekapselt
sein. Allerdings kann es ausnahmsweise auch sinnvoll sein, bestimmte Attribute öffentlich
zu machen. Die Sichtbarkeit von Attributen wird wie bei Methoden über die Symbole +
(public), # (protected) und – (private) gekennzeichnet. Attribute können selbst wieder
komplexe Datenstrukturen bzw. Objekte sein [1].
4.2.2
Datenabstraktion
Hierunter versteht man das Prinzip, nur die auf ein Objekt anwendbaren Operationen
nach außen sichtbar zu machen. Die tatsächliche innere Realisierung der Operationen und
4 Objektorientierte Analyse und Design
37
die innere Struktur des Objektes werden verborgen, d.h. man betrachtet abstrakt die
eigentliche Semantik und lässt die tatsächliche Implementierung außer acht [9]. Das
konkrete Ergebnis des Abstraktionsprozesses ist die Schnittstelle, also die Liste der
öffentlich verwendbaren Methoden einer Klasse [28].
4.2.3
Kapselung
Im Inneren eines Objektes befinden sich Informationen und Mechanismen, die das vom
Objekt erwartete Verhalten bewirken. Durch das Prinzip der Kapselung werden feste
Klassenschnittstellen garantiert, um die Integrität und Konsistenz von Instanzen zu sichern.
Der Zugriff anderer Objekte auf innere Komponenten eines Objekts ist nur über die
Schnittstelle erlaubt.
In der Regel kann die Abschirmung der privaten Komponenten einer Klasse durch
besondere Sprachmittel gewährleistet werden. Die Einführung der Kapselung sorgt für eine
maximale interne Flexibilität der Klassen: Solange die durch den Abstraktionsprozess
gewonnene
Schnittstelle
einer
Klasse
unverändert
bleibt,
kann
ihre
interne
Informationsrepräsentation und -verarbeitung gemäß den jeweiligen Erfordernissen ohne
Einführung von Seiteneffekten modifiziert werden. Als Konsequenzen bilden die Konzepte
der Abstraktion und der Kapselung ein Paar: Die Abstraktion liefert die Schnittstelle einer
Klasse, die Kapselung verhindert deren Umgehung [28].
Beam3D
- length : double
- profileID : int
# number : int
# numberOfNodes : int
# materialID : int
# stiffnessMatrix : DoubelMatrix
# rotationMatrix : DoubleMatrix
# elementLoadVector : DoubleMatrix
# locationMatrix : IntVector
# integrationPointArray
...
# computeStiffnessMatrix()
# computElementLoadVector(int loadcase)
# computeLocationArray()
# computeLength()
+ assembleStiffnessMatrix()
+ assembleElementLoadVector(int loadcase)
+ giveLocationArray()
+ giveInternalForce()
...
Balken15:Beam3D
number = 15
materialID = 3
elementLoadVector = [...]
integrationPointArray = [...]
...
Abbildung 4-16: Klasse und Objekt (Instanz) am Beispiel eines Balkenelementes
38
Objektorientierte Analyse und Design
4.2.4
Modularität
Module dienen als physikalische "Behälter", in denen die Klassen und Objekte
deklariert werden. Das bedeutet, dass alle logisch miteinander in enger Beziehung stehenden
Klassen und Objekte in einem Modul untergebracht werden. Anderen Modulen werden nur
die Elemente über eine Schnittstelle preisgegeben, die für diese von absoluter
Notwendigkeit sind. Das allgemeine Ziel der Zerlegung in Module ist die Verringerung der
Software-Kosten, weil Module unabhängig voneinander entworfen, getestet und gewartet
werden können. Die Struktur jedes Moduls sollte so einfach sein, dass es vollständig
verstanden werden kann. Es sollte möglich sein, die Implementierung von Modulen zu
verändern, ohne die Implementierung der anderen Module zu beeinflussen. Der Aufwand,
eine Designänderung durchzuführen, sollte in einem vernünftigen Verhältnis zu der
Wahrscheinlichkeit stehen, dass eine Änderung notwendig wird [5].
4.2.5
Hierarchie (Relationen)
Eine wichtige Rolle in der Strukturierung objektorientierter Programme spielen
Relationen. Sie drücken Beziehungen zwischen Klassen bzw. Objekten aus.
Definition (Relationen): Unter einer Relation versteht man das Bilden von
Zusammenhängen (Beziehungen in Anwendungsmodellen; in der Objektorientierung
beziehen sich Relationen auf Objekte und Klassen.
Relationen lassen sich in drei Klassen unterteilen:
•
die Vererbung als Spezialisierung bzw. Generalisierung
•
die Aggregation, als Teil-Ganzes-Beziehung und
•
die Assoziation als allgemeinster Fall
Im Folgenden werden diese Relationen im Einzelnen dargestellt.
4.2.5.1
Vererbung
Definition (Vererbung): Vererbung ist der Mechanismus, nach dem Objekte einer
Klasse Zugriff auf Daten und Methoden einer bereits früher definierten Klasse bekommen,
ohne dass diese neu definiert werden müssen.
Vererbung ist eines der mächtigsten Konzepte des objektorientierten Programmierens.
Der Begriff der Vererbung ist zentral, wenn es um die Wiederverwendung von Software
geht. Klassen werden miteinander in Beziehung gesetzt. Dies führt dazu, dass neue Klassen
auf bereits vorhandenen Klassen und ihrer Funktionalität aufbauen können.
4 Objektorientierte Analyse und Design
39
Point
IntegrationPoint
Node
Abbildung 4-17: Einfache Vererbungsstruktur
In Abbildung 4-17 wird eine einfache Vererbungsbeziehung dargestellt. Die Beziehung
der Klassen untereinander ist wie folgt:
•
Point
ist
(abstrakte)
Oberklasse
oder
Elternklasse
von
Node
und
IntegrationPoint. Die Elternklasse ist die direkte Vorgängerklasse, von der eine
Klasse erbt. Natürlich kann der Prozess der Vererbung auch mehrfach
ausgeführt werden.
•
Node ist Unterklasse oder Kindklasse oder abgeleitete Klasse von Point Eine
Kindklasse ist die Erweiterung bzw. Spezialisierung einer anderen Klasse.
•
Eine abgeleitete Klasse erbt alle öffentlichen oder geschützten Daten und
Methoden der Elternklasse, ohne sie explizit nochmals aufzuführen. Sie greift
dennoch auf diese Attribute zu. Die Klassen Node und IntegrationPoint können
also alle Punktoperationen durchführen, die in Point definiert werden.
•
Die Beziehungen der Klassen zueinander werden in der UML in
Klassendiagrammen festgehalten, die erbende Klasse ist mit der vererbenden
Klasse durch eine Generalisierung verbunden (siehe Abbildung 4-14 ), wobei
der Pfeil in Richtung der Generalisierung, also der Elternklasse zeigt.
Die Vererbung bewirkt, dass Instanzen einer Kindklasse überall da verwendet werden
können, wo Instanzen der Elternklasse gefordert sind.
Neben der Vererbung gibt es auch noch den Begriff Mehrfachvererbung.
Definition (Mehrfachvererbung): Mehrfachvererbung ist die Eigenschaft, die einer
Klasse das Erben von mehr als einer Elternklasse erlaubt.
Abbildung 4-18 zeigt das Klassendiagramm einer Mehrfachvererbung. Die Klasse Node
erbt alle öffentlichen und geschützten Attribute und Methoden ihrer beiden Mutterklassen
Point und Component. Das heißt, dass die Klasse Node, wenn sie z.B. die Nachrichten
giveNumber() oder giveCoordinates() erhält, mit der Ausführung der in Klasse Component
40
Objektorientierte Analyse und Design
bzw. Point implementierten Methode reagiert. Diese Methoden müssen in Node weder
deklariert noch neu definiert werden.
Point
Component
# dimension : int
# coordinates : Matrix
...
# myStructure
# number : int
...
+ giveCoordinates()
+ operator[]
...
+ giveNumber()
+ instanciateYourself()
...
Node
Abbildung 4-18: Mehrfachvererbung
Ein Problem bei der Mehrfachvererbung ist, dass in Elternklassen Attribute mit gleicher
Bezeichnung auftreten können, z.B. wenn zwei Elternklassen ihrerseits Kindklasse einer
gemeinsamen Elternklasse (also der „Großelternklasse“) sind. Dadurch sind Attribute
doppelt vorhanden, aber eigentlich identisch. Dieses Problem wird in verschiedenen
Programmiersprachen unterschiedlich gelöst, in manchen ist die Mehrfachvererbung nicht
erlaubt. Allgemein wird die Kindklasse dann als Erweiterung der Großelternklasse
betrachtet, d.h. sie erhält die Eigenschaften beider Elternklassen [9].
4.2.5.2
Aggregation
Definition (Aggregation): Eine Aggregation besteht dann, wenn ein Objekt (Ganzes)
sich aus anderen Objekten (Teilen) zusammensetzt.
Hierbei ist wichtig, dass die Bestandteile wesentlich für den Aufbau des Ganzen sind,
ansonsten handelt es sich um eine Assoziation [9]. Eine Aggregation kann beschrieben
werden als:
2
•
das Ganze und seine Teile
•
der Behälter (Container2) und sein Inhalt
•
die Kollektion und ihre Mitglieder
Container sind Listen im weiteren Sinn. Sie können Einträge über Schlüssel (keys) verwalten. Einträge in
einen Container können neben einfachen Datentypen auch komplexe Objekte selbstdefinierter Klassen sein.
4 Objektorientierte Analyse und Design
41
Durch Angabe der Anzahl (Kardinalitäten) der an einer Aggregation beteiligten
Objekte lässt sich die Beziehung näher kennzeichnen. Eine Aggregation wird in der UML
mit einer Raute gekennzeichnet. Innerhalb der Aggregation kann es den Fall der
existentiellen Abhängigkeit geben. Man spricht von Komposition. Der existenziell
abhängige Teil ist an das Ganze gebunden, so dass eine Destruktion des Ganzen auch den
abhängigen Teil zerstört. Eine Komposition wird durch eine gefüllte Raute gekennzeichnet.
Abbildung 4-19 zeigt eine Aggregations- und eine Kompositionsbeziehung. Die Klasse
ElementContainer ist existentiell abhängig von der Klasse StructurFEM. Die Destruktion
einer Instanz von StructureFEM löst auch die Destruktion des in ihr enthaltenen Containers
aus. Die Beziehung zwischen ElementConainer und Element FEM entspricht der Beziehung
zwischen Behälter und Inhalt.
StructureFEM
enthält X 1
ElementFEMContainer
enthält X
*
ElementFEM
Abbildung 4-19: Aggregation
4.2.5.3
Assoziation
Die Assoziation ist die allgemeinste Beziehung zwischen Klassen. Sie entsteht immer
dann, wenn Objekte mit einer generellen, eventuell zusätzlich attributierten Relation
verbunden werden.
Definition (Assoziation): Eine Assoziation setzt zwei oder mehr Klassen miteinander
in eine (attributierte) Beziehung.
Im Gegensatz zur Aggregation handelt es sich bei der Assoziation um einen viel
unabhängigeren Zusammenhang, der wieder lösbar ist. Zusätzlich hat die Assoziation noch
eine Stelligkeit oder Multiplizität. Diese bezeichnen die Anzahl der an der Beziehung
beteiligten Objekte [9]. Assoziationen werden in Abbildung 4-20 gezeigt. Die obere
Darstellung zeigt die Beziehung der Klassen StructureFEM und ProblemDomain, mit einer
Spezifizierung: der Art der Relation (ProblemDomain berechnet das Tragwerk in
StructureFEM). Die untere Beziehung ist eine qualifizierte und gerichtete Assoziation
zwischen Knoten und Element. Das Attribut besagt, dass der Knoten auf ein Element über
das Attribut number zugreifen kann. Da die Beziehung gerichtet ist, hat zwar Node über
diese Assoziation Zugriff auf ElementFEM aber nicht andersherum. Die Multiplizität gibt
42
Objektorientierte Analyse und Design
an, dass die Identifikation eindeutig ist, d.h. dass jede Identifikationsnummer number nur
einer einzigen Instanz des Objektes ElementFEM entspricht.
StructureFEM
*
W berechnet
1
ProblemDomain
1
Node
number
ElementFEM
Abbildung 4-20: Assoziationen
4.2.6
Polymorphie
Polymorphie ist eines der wichtigsten Konzepte der objektorientierten Programmierung.
Das Vererbungsprinzip sowie die dynamische Typisierung einiger Programmiersprachen
oder das Interface-Konzept in Java bilden die Basis zur Polymorphie. Polymorphie bedeutet,
dass eine Operation sich (in unterschiedlichen Klassen) unterschiedlich verhalten kann. Es
gibt zwei Arten der Polymorphie: statische Polymorphie und dynamische Polymorphie.
Definition (Statischer Polymorphismus):
(1) Die Eigenschaft einer Funktion für verschiedene Parametersätze mit gleichem
Namen definiert zu sein (Überladung).
Dieser Aspekt der Polymorphie besteht in der Variation der Schnittstelle gleichnamiger
Operationen.
(2) Polymorphismus ist die Eigenschaft eines Operators, sich auf Instanzen
verschiedener Klassen während der Laufzeit zu beziehen bzw. Polymorphismus ist die
Fähigkeit mehrerer Klassen von Objekten, auf die gleiche Botschaft in unterschiedlicher Art
und Weise zu reagieren.
Diese Art des statischen Polymorphismus ist bereits aus der prozeduralen Welt bekannt,
nämlich in Gestalt von Operatoren wie + oder -. Diese generischen Operationen sind sowohl
auf ganze Zahlen als auch auf gebrochene Zahlen anwendbar. Objektorientierte
Programmiersprachen bieten die Möglichkeit, diese Operatoren auch für selbstdefinierte
Datentypen bzw. Klassen zu verwenden. Dazu gehört z.B. die Definition des Operators * für
die Matrixmulitplikation. Genaugenommen sind Operatoren Methoden mit besonderen
4 Objektorientierte Analyse und Design
43
Namen. Daher kann der gleiche Effekt auch bei ganz gewöhnlichen Operationen
herbeigeführt werden.
Ein Beispiel für statische Polymorphie ist der Aufruf an ein Element seinen Lastvektor
zu
berechnen.
Dieses
kann
für
ein
statisches
Problem
durch
die
Methode
computeLoadVector() geschehen. Die Methode braucht keinen weiteren Parameter, da der
Lastvektor zeitunabhängig ist. Für eine Modalanalyse allerdings muss der Lastvektor zu
einem bestimmten Zeitpunkt t bestimmt werden, da dieser eine Funktion von der Zeit sein
kann. Die Methode kann damit durch computeLoadVector(time) überladen werden. Das
Programm entscheidet dann zur Laufzeit, welche der beiden Methoden ausgeführt wird.
Definition (Dynamischer Polymorphismus): Polymorphismus ist die Eigenschaft von
Variablen, verschiedene Typen annehmen zu können.
Voraussetzung für die dynamische Polymorphie ist die sogenannte späte Bindung (vgl.
Typbindung in Kapitel 5). Bei der späten Bindung wird der genaue Speicherort einer
Operation erst dann ermittelt, wenn der Aufruf stattfindet, d.h. eine entsprechende Nachricht
an das Objekt gesendet wird. Die Zuordnung der Nachricht zu der empfangenden Operation
geschieht also nicht während der Programmübersetzung sondern dynamisch zur Laufzeit des
Programms. Ob diese Eigenschaft verwendet werden kann, ist letztendlich davon abhängig,
ob die Programmiersprache, mit der der Entwurf realisiert werden soll, die späte Bindung
unterstützt (vgl. Kapitel 6: Programmiersprachen) [9].
Polymorphie hat den Vorteil, dass sie dem Programmierer mehr Freiheiten lässt und
von Routineaufgaben entlastet. Der Nachteil besteht darin, dass die Typbestimmung und –
validierung zur Laufzeit einen beträchtlichen Zusatzaufwand darstellt. Darüber hinaus
werden Fehler, die aus Typverletzungen resultieren, erst zur Laufzeit erkannt. Für
berechnungsintensive Anwendungen wie die FEM ist es daher günstig, eine vorwiegend
statische Typbindung zu verwenden, wenn eine dynamische Bindung die Laufzeiteffizienz
mehr beeinträchtigt, als das programmiertechnische Vorteile daraus resultieren [28].
4.2.7
Nebenläufigkeit
Objektorientierte Programme bestehen aus Objekten, die durch den Austausch von
Botschaften deren Ablauf steuern. Dabei ist die Reihenfolge des Botschaftenaustausches im
Allgemeinen durch die Ordnung im Programmtext vorgegeben. Etliche Botschaften sind
allerdings voneinander unabhängig und könnten theoretisch auch auf parallelen Prozessoren
bearbeitet werden. Obwohl aufgrund des numerischen Aufwands gerade im Bereich der
FEM parallel arbeitende Systeme von großem Interesse sind, befinden sich die meisten
44
Objektorientierte Analyse und Design
Ansätze noch im Forschungsstadium. Zusätzlich kann kaum eine der verbreiteten
Hochsprachen echte Parallelkonstrukte (Nebenläufigkeit auf verschiedenen Prozessoren)
vorweisen [28]. Auf diesen Aspekt wird im Programmentwurf nicht weiter eingegangen.
4.2.8
Persistenz
Aus verschiedenen Gründen ist es manchmal notwendig und wünschenswert, ein
Programm an einer bestimmten Stelle zu unterbrechen und es später an dieser Stelle wieder
aufsetzen zu lassen. Dazu müssen die während der Laufzeit berechneten Daten (Objekte und
Verbindungen) geeignet gespeichert werden [9].
Definition (Persistenz) Persistenz ist die Eigenschaft von Objekten, über die Laufzeit
des Programms hinaus in ihrer Identität, ihrem Zustand und ihrer Beschreibung zu
existieren.
Für den Bereich der FEM hat das Konzept der Persistenz eine sehr untergeordnete
Bedeutung. Obwohl die persistente Speicherung von FE-Daten mit den Mitteln der
verwendeten Programmiersprache wünschenswert wäre, scheitert sie an der Tatsache, dass
kaum eine Programmiersprache echte Datenpersistenz bietet. Die Benutzung von
(objektorientierten) Datenbanken ist für FE-Massendaten wenig geeignet, da FEProgrammsysteme selten die für Datenbanken typischen selektiven Abfragen und
Einfügungen benutzen. Maßgeblich sind hier Operationen, die sich durch große
Datenumsätze innerhalb kurzer Zeit auszeichnen, z.B. beim Abfragen der Modelldaten oder
beim Zurückschreiben der Berechnungsergebnisse [28].
4.2.9
Generizität
Die Generizität ist kein notwendiges Konzept der Objektorientierung.
Definition (Generizität): Generizität ist die Fähigkeit, Klassen durch einen Typ zu
parametrisieren.
Da Klassen die Implementierung von abstrakten Datentypen sind, können sie auch
generische Parameter haben. Klassen mit einem generischen Parameter erzeugen also
Klassen von Klassen von Objekten. Verallgemeinert kann der Begriff der Generizität auch
auf Funktionen, Prozeduren bzw. Methoden und deren Parameter angewendet werden. Noch
interessanter wird die Anwendung der generischen Parameter, wenn der Parameter der
generischen Klasse selbst Klasse und Elternklasse von anderen Klassen ist. Damit können
dann in einem Stapel Elemente unterschiedlicher Typen abgelegt werden, wenn diese
4 Objektorientierte Analyse und Design
45
Kindklassen einer Elternklasse sind, die die Eigenschaft hat, auf einem Stapel abgelegt
werden zu können. Die oben erwähnte Polymorphie ist ebenfalls eine Form der Generizität.
Abbildung 2-1 zeigt eine generische Klasse. In diesem Fall ist dies ein Container, in
dem alle Objekte, die Instanzen der Klasse Component oder einer ihrer Kindklassen sind,
abgelegt werden können.
T {T=Component}
Container
addComponent(Component)
deleteComponent(Component)
Abbildung 4-21: Generische Klasse
Trotz der Mächtigkeit generischer Konstrukte sind generische Klassen in kaum einer
Sprache zugelassen [9].
46
5
Globales Programmkonzept
Globales Programmkonzept
Der Entwurf des globalen Programmkonzepts erfolgte auf der Basis der
Objektorientierung. In Kapitel 5.1 wird zunächst die (statische) Strukturbeschreibung
vorgestellt. In Kapitel 5.2 werden die Grundklassen dieses Modells mit ihren wichtigsten
Attributen und Methoden vorgestellt. Der Ablauf der Berechnung wird dann in Kapitel 5.3
beispielhaft für eine statische Berechnung, eine Berechnung mit Theorie 2. Ordnung und
eine Berechnung mit physikalischer Nichtlinearität beschrieben. Die Eingabe bzw. Ausgabe
im Prä- und Postprozessor wird aus Zeitgründen nicht bearbeitet.
Die Methoden in den Klassen werden nur anhand ihrer Schnittstelle und ihrer
Verantwortlichkeiten beschrieben. Die Implementation des Entwurfes, d.h. die explizite
Darstellung der in einer Methode enthaltenen Datenmanipulation, ist nicht Bestandteil der
Ausführung.
5.1
Erläuterung des FEM-Objektmodells
Bei den wichtigsten Abstraktionen des Anwendungsgebiets handelt es sich um die
grundlegende Theorie in Form der Kontinuumsmechanik und die FEM als Werkzeug zur
Lösung der resultierenden Gleichungen. Die zentralen Abstraktionen sind einerseits der
Körpers selbst, andererseits Teilgebiete in Form der Finiten Elemente. Das zentrale
Klassendiagramm mit der Beschreibung der Abhängigkeiten der verschiedenen Klassen
untereinander wird in Abbildung 5-1 dargestellt.
Elemente und Knoten sowie die Lasten auf die Struktur und das Material stellen
Objektklassen dar. Alle Bestandteile des Modells erben von einer gemeinsamen
Mutterklasse: Component. (Abbildung 5-3) Durch diese Oberklasse wird sichergestellt, dass
jedes Objekt bei seiner Instanziierung ein Identifikationsnummer (Attribut number)
bekommt und einer Struktur (Klasse Structure) zugeordnet wird. Die Klasse Structure
repräsentiert das Abbild des zu berechnenden Tragwerks. In ihr werden die Instanzen der
Elemente, Knoten und Lastfälle verwaltet. Die Klasse Structure ist ebenfalls eine abstrakte
Klasse, die durch ihre jeweilige Kindklasse vertreten wird. Für eine Berechnung mit der
Methode der Finiten Elemente ist dies die Klasse StructureFEM. Diese Klasse stellt (vor der
Berechnung) sicher, das alle notwendigen Daten vorhanden sind, um die Berechnung
durchzuführen. Jede FEM-Struktur besteht aus mindestens zwei Knoten, einem Element und
5 Globales Programmkonzept
47
einem Lastfall. Alle Komponenten werden in parametrisierten Container-Klassen in
StructureFEM abgelegt und von der Struktur verwaltet.
Die Klasse ElementFEM ist ebenfalls eine abstrakte Klasse und wird nur durch ihre
Kindklassen vertreten, die verschiedene Elementtypen implementieren (z.B. Balkenelemente). Das Element wird ebenso wie die Gesamtstruktur (bei der Instantiierung) über
Identifikationsnummern mit seinen zugehörigen Knoten verbunden. Genauso wird jedem
Element ein Materialgesetz zugeordnet, das über die Identifikationsnummer assoziiert wird.
Für die Analyse von Stabwerken ist es zusätzlich nützlich eine Klasse für Querschnitte
anzulegen, durch die auf eine Bibliothek von üblichen Querschnitten (z.B. Stahlprofile)
zugegriffen werden kann. Auf die Klasse Profile wird in Stabelementen – analog zu den
Materialgesetzen - über ein Attribut zugegriffen, das die Identifikationsnummer des Profiles
enthält.
Dem Element kommt von jeher die zentrale Rolle innerhalb eines FEMProgrammsystems zu, da es alle Information für die zu lösenden differentiellen Gleichungen
enthält. Diese zentrale Rolle des Elementes wird auch in einem objektorientierten Ansatz
beibehalten.
Sie
wird
tatsächlich
noch
bestärkt,
da
alle
Attribute
und
alle
Berechnungsvorschriften in der Klasse gekapselt sind. Allerdings profitiert die ElementKlasse ebenfalls von der hierarchischen Strukturierung der Objekte und delegiert einige
wichtige Aufgaben wie das Management der Unbekannten an Knoten (Klasse Node) und
Freiheitsgrad (Klasse Dof). Bei seiner Instantiierung erstellt ein Element die für seine
Berechnung notwendigen Integrationspunkte (Klasse IntegrationPoint).
Die Klassen Node und IntegrationPoint sind beide von ihrer Datenstruktur her Punkte
im Raum oder in der Ebene. Daher werden sie beide als Kindklasse einer abstrakten
Mutterklasse Point erstellt, die die wichtigsten Attribute und Methoden für das Management
der Koordinaten vererbt (vgl. Abbildung 4-17, Abbildung 4-18 und Abbildung 5-3)
Für das Verwalten der Freiheitsgrade legt jeder Knoten Instanzen der Klasse Dof
(Degree of Freedom) an: Der Zugriff auf die Freiheitsgrade (Ändern, Ausgeben usw.)
geschieht nur durch die Klasse Node. Jede Instanz von Dof beinhaltet jeweils einen
möglichen Freiheitsgrad des Knotens. Dof speichert als Attribut seinen Zustand (isBound als
Boolean) und die Gleichungsnummer, mit der der Freiheitsgrad in das Gesamtsystem
eingeht (Attribut equationNumber). Die Verwaltung der Freiheitsgrade in dem
Softwaresystem ist also dezentralisiert. Dof kann eine oder mehrere Unbekannte haben (z.B.
Knotenverschiebung und –beschleunigung).
48
Globales Programmkonzept
Die Klasse ProblemDomain ist eine abstrakte Mutterklasse, die durch Instanzen ihrer
Kindklassen vertreten wird (vgl. Abbildung 5-2). Diese übernehmen die konkrete
Ablaufsteuerung einer Berechnung für eine beliebige Berechnungsmethode. Die Unterklasse
StaticalAnalysisFEM führt die statische Berechnung des in StructureFEM dargestellten
Systems durch, NLStaticalAnalysisFEM eine nichtlineare statische Berechnung und
ModalAnalysisFEM eine zeitabhängige Analyse. Die verschiedenen Lösungsmethoden für
die nichtlineare oder zeitabhängige Berechnung werden wiederum als Unterklassen
implementiert.
Die Lasten, die auf das Tragwerk wirken, werden in der Klasse Loadcase (ebenfalls
durch einen Container) verwaltet. Als Klassen werden Knotenlasten (NodalLoad) und auf
das Element wirkende Lasten unterschieden (ElementLoad). Elementlasten werden noch
einmal genauer aufgeteilt in Oberflächenlasten und Körperlasten, da sich die Integration
über diese Lasten voneinander unterscheidet (vgl. Kapitel 2.1.1, Gleichungen 11 und 12).
Die Zusammenstellung der Lasten wird von den Klassen ElementFEM
bzw. Node
übernommen.
In Abbildung 5-1 bis Abbildung 5-4 werden die Klassendiagramme des
Programmentwurfes vorgestellt. Diese Diagramme zeigen jeweils nur einen Ausschnitt des
Entwurfes und die Klassen werden nur mit den für das jeweilige Diagramm notwendigen
Attributen, Methoden oder Verantwortlichkeiten dargestellt.
5 Globales Programmkonzept
Abbildung 5-1: Klassendiagramm: Klassen des globalen FEM-Models
49
50
Globales Programmkonzept
Abbildung 5-2: Klassendiagramm: Klassen für die Steuerung der Berechnung
5 Globales Programmkonzept
Abbildung 5-3: Klassendiagramm: Vererbungshierarchie für die FEM-Objekte
51
52
Globales Programmkonzept
Abbildung 5-4: Klassendiagramm: Delegation der Containermethoden an eine generische Klasse
5 Globales Programmkonzept
Abbildung 5-5: Klassendiagramm: Die Klasse Matrix
53
54
Globales Programmkonzept
5.2
Die Klassen
In diesem Kapitel werden die grundlegenden Klassen mitsamt Methoden und Attributen
beschrieben: Das Element (ElementFEM Kapitel 5.2.1), der Knoten (Node Kapitel 5.2.2),
der Freiheitsgrad (Dof Kapitel 5.2.3), die „verwaltenden“ Klassen StructureFEM (Kapitel
5.2.4) und ProblemDomain (Kapitel 5.2.5) und die Klasse Matrix (Kapitel 5.2.6) für die
numerische Berechnung. Es wird Aufbau und Verantwortlichkeiten der Klassen
ausgearbeitet. Dabei wird auf die Implementation der vorgestellten Methoden nicht
eingegangen, da diese für den globalen Programmentwurf und den Berechnungsablauf nicht
entscheidend ist und stark von der Wahl der Programmiersprache abhängt.
Die Attribut- und Methodenliste ist nicht vollständig. Es wird in dieser Ausführung nur
auf diejenigen Attribute und Methoden eingegangen, die für die statische Berechnung eines
Tragwerks benötigt werden. Für eine nichtlineare Berechnung müssen die Klassen
entsprechend erweitert werden. In den Sequenzdiagrammen in Kapitel 5.3 werden die
wichtigsten für eine nichtlineare Berechnung benötigten Attribute und Methoden umrissen.
Zudem kann es bei der Implementierung des Systems durchaus notwendig werden
weitere Attribute und Methoden einzufügen.
Bei dem in Kapitel 8 vorgestellten Beispielprogramm werden einige Methoden, die in
diesem Kapitel mit aufgeführt werden, nicht implementiert. So hält das dort verwendete
Balkenelement seine Steifigkeitsmatrix direkt vor, so dass auf eine Integration über das
Volumen des Elementes verzichtet werden kann. Da diese Methoden aber für das allgemeine
Programmkonzept von Bedeutung sind, werden sie in den folgenden Abschnitten
beschrieben.
5.2.1
Die Klasse ElementFEM
Die Instanzen der Klasse ElementFEM bzw. ihrer Kindklassen müssen folgende
Aufgaben erfüllen:
•
Berechnung der Element-Steifigkeitsmatrix k
•
Berechnung der Element-Massenmatrix m
•
Berechnung des Vektors der Elementlasten f S + f B
•
Das Einlesen seiner Daten in das globale Gleichungssystem
•
Identifikation und Management der Knoten und des Materialgesetzes
5 Globales Programmkonzept
55
Die Steifigkeitsmatrix k wird in der Methode computeStiffnessMatrix() erstellt. Jede
Instanz eines Elementes führt diese Methode aus, wenn es eine entsprechende Nachricht
bekommt. In dieser Methode integriert das Element numerisch (z.B. Gauss-Integration)
seine Steifigkeitsmatrix und gibt diese zurück. Diese Integration ist theoretisch gültig für
jedes Element, wird daher in der Mutterklasse implementiert. Die Matrizen b und h bzw. das
Volumen (Oberfläche) über das integriert wird, sind dagegen abhängig vom jeweiligen
Elementtyp. Die Erstellung dieser Matrizen mit den Methoden
-
giveVolume(IntegrationPoint)
-
giveBMatrixAt(IntegrationPoint) und
-
giveHMatrixAt(IntegrationPoint)
wird in der Mutterklasse als abstrakt definiert und muss in den Kindklassen
implementiert werden. Falls die Kindklassen die Element-Steifigkeitsmatrix auf einem
andern Weg berechnen, kann die Methode computeStiffnessMatrix() auch überschrieben
werden (Polymorphie). Die Massenmatrix wird analog zur Steifigkeitsmatrix erstellt. Auf
die Dichte in der Klasse Material wird dabei über ein Attribut materialID zugegriffen, das
den Integrationspunkten (in integrationPointContainer) zugeordnet wird (abgeleitete
Assoziation).
Ein
Element
erstellt
seinen
Lastvektor
fS +f B
wenn
es
die
Nachricht
computeElementLoadVector(loadcase) bekommt. Über die Assoziation mit einem Lastfall
(Loadcase) sucht es alle Beiträge von Elementlasten die auf es bezogen sind und ermittelt
den entsprechenden Lastvektor (vgl. Gleichungen 11-13). Dabei ruft es seine eigenen
Methoden computeBodyForceVector(Loadcase) und computeSurfaceLoadVector(Loadcase)
auf.
Das Einlesen der Elementmatrizen bzw. der Lastvektoren geschieht auf Anforderung
von der Klasse StructureFEM. Diese ruft (je nach Bedarf) die Methoden
-
assembleStiffnessMatrix(loadcase),
-
assembleMassMatrix(loadcase) und
-
assembleElementLoadVector(loadcase)
des Elementes auf. Das Element benötigt dabei das Attribut locationArray, in dem die
Inzidenzen gespeichert sind, die seine lokalen Freiheitsgrade auf die globalen beziehen.
Dieser Vektor wird gebildet, indem das Element die locationArrays seiner Knoten
aneinanderhängt. Das Element sendet seine Beiträge mit den entsprechenden Informationen
zu den globalen Matrizen und Vektoren in der Klasse StructureFEM zurück, wo die Anteile
56
Globales Programmkonzept
der Elementmatrizen dann
- entsprechend der Inzidenzen – in die globalen Matrizen
einsortiert werden.
Wenn das Element eine „assemble“-Nachricht bekommt, prüft es zunächst, ob das
entsprechende Attribut bereits berechnet wurde, d.h. ungleich NULL ist. Falls dies der Fall
ist, wird lediglich über ein an sich selbst gerichtetes „give“ das vorhandene Attribut
ausgegeben. Wenn das Attribut nicht vorhanden ist, schickt sich die Klasse selber die
Nachricht „compute“ um das Attribut zu errechnen. Dieses Vorgehen wird auch als „NonAnticipation-Method“ bezeichnet, das heißt der Aufruf „assemble“ wird unabhängig vom
Zustand des Objektes ausgeführt [11][12]. Dieses Vorgehen birgt Vorteile z.B. für die
nichtlineare Berechnung von Tragwerken (vgl. Kapitel 5.3).
5.2.2
Die Klasse Node
Die Klasse Node kapselt alle Knotendaten. Ein Element kann auf Knotendaten nur über
die Methoden der Klasse zugreifen. Eine Instanz der Klasse Node hat folgende Funktion:
•
Management der Koordinaten
•
Management der Freiheitsgrade
•
Berechnung und Einlesen des Vektors der Knotenlasten fi
Jede Instanz der Klasse Node besitzt ein Attribut namens dofContainer, in dem es die
Freiheitsgrade (also die Instanzen von Dof an sich) speichert. Jeder Knoten hat eine
Methode getDofs(), die er bei seiner Instantiierung ausführt.
Wie Elemente sind auch Knoten (konzentrierten) Lasten ausgesetzt. Diese werden über
die
Klasse
NodalLoad
assoziiert.
Wenn
der
Knoten
die
Nachricht
computeNodalLoadVector(Loadcase) erhält, liest er die dem Lastfall entsprechenden Daten
ein und erstellt den Knotenlastvektor nodalLoadVector.
Analog
zur
Elementklasse
sendet
der
Knoten
auf
die
Aufforderung
assembleNodalLoadVector(Loadcase) hin seinen Beitrag zusammen mit den Informationen
über die Gleichungsnummer (aus locationArray) zum globalen Lastvektor der Klasse
StructureFEM.
5.2.3
Die Klasse Dof
Ein Freiheitsgrad ist Attribut eines Knotens. Durch die Betrachtungsweise als
eigenständiges Objekt können einige Aufgaben vom Knoten zum Freiheitsgrad delegiert
werden. Eine Instanz der Klasse Dof hat folgende Verantwortlichkeiten:
•
Management der Unbekannten
5 Globales Programmkonzept
•
Nummerierung der Gleichungen
•
Speicherung des Lagerzustandes
57
Die Klasse Dof besitzt ein Attribut unknowns, in dem die Unbekannten über einen
Schlüssel verwaltet werden. Auf die Anweisung giveUnknown(key) gibt Dof die unter
diesem Schlüssel gespeicherte Größe aus. Ein Key ist eine Variable vom Typ String, z.B.
Verschiebung. Erhält der Freiheitsgrad die Nachricht setUnknown(key,value), dann wird der
übergebende Wert an die entsprechende Stelle geschrieben.
Ein gutes Beispiel für die Dezentralisierung des Entwurfs ist auch die Nummerierung
der Freiheitsgrade. Jeder Dof enthält ein Attribut equationNumber. Diese Nummer
entspricht der Gleichungsnummer, mit der Kräfte und Verformungen in Richtung dieses
Freiheitsgrades in das Gesamtsystem eingehen. Wenn der Freiheitsgrad die Nachricht
giveEquationNumber() erhält, wird das Attribut zurückgegeben. Falls equationNumber noch
leer ist, führt der Freiheitsgrad die Methode getEquationNumber() durch. Falls der
Freiheitsgrad gebunden ist (Attribut isbound = true), wird eine Null geschrieben, ansonsten
gibt die Methode die aktuelle Dimension des Gleichungssystems + 1 zurück.
5.2.4
Die Klasse StructureFEM
Die Klasse StructureFEM verwaltet alle Informationen und Methoden, die für die
Berechnung eines Tragwerkes notwendig sind. Die Verantwortlichkeiten lassen sich wie
folgt zusammenfassen:
•
Input/Output der Systemdaten
•
Management der Komponenten
•
Lösung des Gleichungssystems
StructureFEM stellt das Interface des FEM-Programmsystems zum Benutzer dar. Eine
Instanz der Klasse repräsentiert das gesamte Tragwerk, das berechnet werden soll. Über
Container-Klassen werden alle Knoten, Elemente, Lastfälle und Materialien verwaltet. Die
Klasse StructureFEM hält über diese Container-Klassen alle Methoden bereit, um
Komponenten zu erstellen und zu verwalten (vgl. Abbildung 5-4).
Die Lösung des Gleichungssystems wird ebenfalls über StructureFEM initiiert. Die
Ablaufsteuerung der Berechnung wird allerdings an eine Instanz der Klasse ProblemDomain
delegiert. StructureFEM besitzt als Attribute alle globalen Matrizen und Vektoren und stellt
über verschiedene Methoden den Zugriff zu diesen Matrizen her (vgl. Sequenzdiagramme,
Abbildung 5-7, Abbildung 5-9 und Abbildung 5-11). Für das Aufstellen des linearen
58
Globales Programmkonzept
Gleichungssystems
werden
z.B.
die
Methoden
assembleGlobalStiffnessMatrix(),
assembleGlobalLoadVector(Loadcase) und solveSystem() bereitgestellt.
Die Nachricht assembleGlobalStiffnessMatrix() veranlasst StructureFEM an alle
Elemente den Aufruf assembleStiffnessMatrix() zu senden. Analog erfolgt für den Aufruf
assembleGlobalLoadVector(Loadcase) das Zusammensetzen der Element-Lastvektoren und
der Knoten-Lastvektoren.
5.2.5
Die Klasse ProblemDomain
Die Instanzen der Kindklassen von ProblemDomain haben nur eine einzige
Verantworlichkeit: die Ablaufsteuerung der Berechnung. Die Klasse hat keine Attribute die
das Tragwerk betreffen und keine Methode außer solve(). Die Assoziation mit Structure ist
die einzige Verbindung, die ProblemDomain mit den Komponenten des FEM-Models hat.
Jede Kindklasse (bzw. „Enkelklasse“) von ProblemDomain hat eine eigene Methode
solve() implementiert. Für die Kindklasse StaticalAnalysisFEM besteht die Methode aus nur
drei Nachrichten, die an StructureFEM gesendet werden: assembleGlobalStiffnessMatrix(),
assembleGlobalLoadVector() und solveSystem() (vgl. Kapitel 5.2.4).
5.2.6
Die Klasse Matrix
Die Klasse Matrix ist die wichtigste mathematische Klasse im Objektmodell. Ihre
Aufgaben beschränken sich auf
•
die Verwaltung und Strukturierung der Matrixelemente
•
Methoden zur Matrizenmanipulation
Die Verwaltung und Strukturierung der Matrixelemente wird in der Implementation der
von der Klasse bereitgestellten Methoden versteckt. Die (Mutter-)klasse Matrix speichert
Elemente in einem zweidimensionalen Feld. Da diese Art der Datenverwaltung oft sehr
langsam ist, können spezialisierte Unterklassen zu Matrix erstellt werden, wie z.B.
BandMatrix oder SkylineMatrix. Diese übernehmen die Schnittstellen ihrer Mutterklasse und
überschreiben die von Matrix implementierten Methoden zur Speicherverwaltung. Damit
kann zu jedem Zeitpunkt eine Umstellung auf eine Kindklasse von Matrix geschehen. Da
die Kindklasse ihre Mutterklasse „vertreten“ kann, muss lediglich bei der Instantiierung der
neue Matrixtyp spezifiziert werden. Alle übrigen an Matrix gerichteten Methodenaufrufe
werden über die gemeinsame Schnittstelle über die Mutterklasse an die Kindklasse
weitergegeben (vgl. Kapitel 3.2 und 4.2.6).
5 Globales Programmkonzept
59
Die öffentlichen Methoden der Klasse Matrix sind zum Großteil über (überladene)
Operatoren definiert, z.B. der Operator “ * “ für Matrixmultiplikationen oder der Operator “
+ “ für Matrixadditionen. Auf die Nachricht giveSize() gibt die Klasse die aktuelle
Dimension der (System-)Matrix zurück3. Die Methode transpose() transponiert die Matrix,
die Methode solveSystem() löst das lineare Gleichungssystem.
5.3
Rechenabläufe
In den nächsten Kapiteln werden die Berechnungsabläufe in einem objektorientierten
FEM-Programm dargestellt. Die gegebenen Abläufe behandeln die Lösung des linearen
Gleichungssystems sowie die iterativen und inkrementellen Methoden, die in Kapitel 2.1.3
(Nichtlineare Berechnungen) vorgestellt wurden.
Für die Darstellung wurden Aktivitätsdiagramme und Sequenzdiagramme erstellt.
Bei Aktivitätsdiagrammen liegt der Schwerpunkt auf dem Fluss der Aktivitäten im
Ablauf der Berechnung. Sie sind also vergleichbar mit Flussdiagrammen in der
sequentiellen Programmierung. Die Aktivitäten werden allerdings in sogenannten
„Schwimmbahnen“ angeordnet. Diese Schwimmbahnen legen die Zuständigkeiten für die
jeweiligen Aktivitäten fest, die Verantwortlichkeitsbereiche werden durch eine oder mehrere
Klassen implementiert. In den folgenden Diagrammen werden die Diagramme in die
Verantwortlichkeitsbereiche
•
Berechnungssteuerung (Klassen StructureFEM und ProblemDomain),
•
Elemente (Klasse ElementFEM bzw. Kindklassen) und
•
Knoten (Klasse Node)
unterteilt.
Transitionen werden als Ereignispfeile ohne explizite Ereignisbeschreibung notiert.
Eingehende Transitionen lösen eine Aktivität aus, bei Abschluss der Aktivität werden neue
Transitionen ausgelöst. Über die sogenannten „splitting“-Linien können theoretisch Abläufe
geteilt und synchronisiert werden, parallel laufende Aktivitätspfade können nacheinander,
gleichzeitig oder abwechselnd ausgeführt werden. In den folgenden Diagrammen werden
„splitting“-Linien nur benutzt, um Schleifen zu beschreiben (*for each ...all).
Bei Sequenzdiagrammen steht der Nachrichtenfluss zwischen den Objekten im
Vordergrund. Die Objekte werden durch gestrichelte senkrechte Linien dargestellt. Der
3
Die Steifigkeits- und Massen-Matrizen in der FEM sind quadratisch, daher entspricht die Anzahl der Spalten
der Anzahl der Reihen. Bei Vektoren (nur eine Spalte) spiegelt die Anzahl der Reihen die Dimension des
Gleichungssystems wieder.
60
Globales Programmkonzept
Objektname steht über der Linie. Die Überlagerung der gestrichelten Lebenslinien durch
breite senkrechte Balken symbolisiert den Steuerungsfokus. Der Steuerungsfokus gibt an,
welches Objekt gerade aktiv ist. Mit einem Sternchen vor der Nachricht soll das mehrfache
Senden einer Nachricht symbolisiert werden. Die Instanzen der Klassen ElementFEM und
Node werden ebenfalls nur durch ein Sternchen benannt, das bedeutet, dass die Nachricht an
mehrere (oder alle) Objekte dieser Klasse gesendet wird [26].
Bei den Methodenaufrufen werden in den Diagrammen kaum Parameter angegeben.
Die meisten Aufrufe bleiben in der Tat parameterlos. Teilweise werden Parameter allerdings
auch ausgelassen (z.B. Loadcase), wenn sie für den Nachrichtenaustausch innerhalb des
dargestellten Bereiches nicht entscheidend sind.
Allgemein wird die Beschreibung der Abläufe auf einem hohen Abstraktionslevel
gehalten,
damit
die
Diagramme
übersichtlich
bleiben.
Für
eine
vollständige
(Implementations-) Darstellung wären noch weitere Diagramme erforderlich, die einzelne
Teilbereiche näher beleuchten.
5.3.1
Statische Berechnung
Der Ablauf einer statische Berechnung wird in Abbildung 5-6 und Abbildung 5-7
dargestellt. Der Aktivitätsfluss ist bis auf die Schleifen über Element und Knoten linear. Die
Berechnungskontrolle verbleibt überwiegend bei den Instanzen der Klassen ProblemDomain
und StructureFEM. Aus dem Sequenzdiagramm wird deutlich, dass die mathematischen
Operationen (Lösung des Geleichungssystems) in StructureFEM stattfinden. Das bedeutet,
dass ProblemDomain zwar die Berechnung steuert, aber keine Kenntnisse über die Inhalte
der Systemgleichungen hat. Zudem verbleibt der unterste Kontrollfokus bei StructureFEM
als Schnittstelle zum Benutzer. Die Berechnung wird durch die Nachricht solve() an
ProblemDomain ausgelöst.
5.3.2
Nichtlineare Berechnung
Die Berechnung nach der Theorie 2. Ordnung erfolgt nach dem Newton-RaphsonVerfahren (Kapitel 2.1.3.1). Das Diagramm in Abbildung 5-8 zeigt den allgemeinen Ablauf
einer solchen Berechnung. Im Sequenzdiagramm (Abbildung 5-9) wird der Austausch der
Nachrichten zwischen den Objekten für einen Iterationsschritt dargestellt.
Für ein physikalisch nichtlineares System wurde bereits die inkrementelle
Steifigkeitsmethode vorgestellt (Kapitel 2.1.3.2). Abbildung 5-10 zeigt den allgemeinen
5 Globales Programmkonzept
61
Ablauf der Berechnung. Das Sequenzdiagramm (Abbildung 5-11) stellt den Austausch der
Nachrichten für ein Lastinkrement dar.
Die Berechnung der nichtlinearen (tangentialen) Steifigkeitsmatrizen geschieht auf
Elementebene. Das Zusammensetzen dieser Matrizen zur globalen Steifigkeitsmatrix erfolgt
auf dem bereits geschilderten Weg (Kapitel 5.2.1). Er unterscheidet sich nicht von der
Erstellung der linearen globalen Steifigkeitsmatrix.
Es wird auffallen, dass für die nichtlinearen Berechnungen kaum zusätzliche
Methodenaufrufe implementiert werden müssen. Dieses liegt vor allem an der bereits
vorgestellten „Non-Anticipation-Method“. Die Errechnung der Element-Steifigkeitsmatrix
findet theoretisch immer unter Berücksichtigung der Vorverformungen und des
Materialzustandes statt. Da diese zu Beginn der statischen Berechnung gleich NULL sind,
gehen
diese
Einflüsse
in
die
lineare
Steifigkeitsmatrix
nicht
ein
(Ausnahme:
Vorverformungen). Die Steifigkeitsmatrix wird nur einmal erstellt und bleibt dann konstant.
Für eine nichtlineare Berechnung wird allerdings zu Beginn eines neuen Lastschrittes die
Nachricht „update“ an das Element gesandt. Daraufhin löscht das Element seine bereits
errechnete Matrix. Auf die Nachricht „assemble“ reagiert es also mit einer Neuberechnung
der Matrix unter Einbeziehung der zu diesem Zeitpunkt aktuellen Verformungen bzw. des
aktuellen Materialzustandes.
62
Globales Programmkonzept
Abbildung 5-6: Aktivitätsdiagramm: Statische lineare Berechnung
5 Globales Programmkonzept
Abbildung 5-7: Sequenzdiagramm: Statische lineare Berechnung
63
64
Globales Programmkonzept
Abbildung 5-8: Aktivitätsdiagramm: Berechnung nach Theorie 2. Ordnung
5 Globales Programmkonzept
Abbildung 5-9: Sequenzdiagramm: Berechnung eines Iterationsschritts nach Theorie
2. Ordnung
65
66
Globales Programmkonzept
Abbildung 5-10: Aktivitätsdiagramm: Physikalisch nichtlineare Berechnung
5 Globales Programmkonzept
Abbildung 5-11: Sequenzdiagramm: Berechnung eines Lastschrittes, physikalisch
nichtlineare Berechnung
67
68
5.4
Globales Programmkonzept
Erweiterbarkeit und Wiederverwendung
Die Programmstruktur ist so angelegt, das eine Erweiterung des Programmsystems
erleichtert wird. Diese Erweiterbarkeit betrifft sowohl die Ausweitung der Berechnung nach
der Methode der Finiten Elemente als auch die Ausdehnung auf weitere Analyseverfahren.
Die Ausweitung der FEM kann durch verschiedene Erweiterungen in der
Klassenhierarchie geschehen. Die meisten Vererbungshierarchien in Abbildung 5-1 bis
Abbildung 5-4 sind mit dem Zusatz {incomplete} bezeichnet. Das heißt, dass im Laufe des
Lebenszyklus des Programms die Erweiterung der Vererbungsstruktur um zusätzliche
Kindklassen erwartet wird. Dieses wird in einem FEM-Programmsystem vor allem die
Klasse ElementFEM betreffen. Aber auch für ProblemDomain können weitere Kindklassen
(oder Enkelklassen) eingefügt werden, die weitere nichtlineare Berechnungsverfahren
implementieren.
In den Namen der Klassen Element, Structure und ProblemDomain ist jeweils der
Zusatz FEM vermerkt. Dieser ist notwendig, um bei einer Ausdehnung des Softwaresystems
den Namensraum für gleichwertige Komponenten eines anderen Analyseverfahrens
offenzuhalten. So werden z.B. für eine Berechnung nach der Methode der BoundaryElemente (BEM) die Klassen ElementBEM, StructureBEM und ProblemDomain in das
Objektmodell miteingefügt werden. Klassen wie Matrix, Node, Dof, IntegrationPoint, Load
und Loadcase sind zunächst unabhängig vom Berechnungsverfahren und können in einer
Berechnung für die Methode der Boundary-Elemente wieder verwendet werden.
An dieser Stelle wird der Vorteil des objektorientierten Entwurfes für ein
Programmsystem zur Tragwerksanalyse deutlich. Erweiterungen für andere Elementtypen
oder Berechnungsmethoden erfordern lediglich die Erweiterung der Klassenhierarchien. Die
Schnittstellen bleiben in den meisten Fällen konstant oder werden höchstens um zusätzliche
Funktionen erweitert. Wenn eine Klasse eine Methode anders als die Mutterklasse
implementiert (z.B. wenn die Steifigkeitsmatrix im Element in direkter Form vorliegt und
nicht durch Integration ermittelt wird) , kann die entsprechende Methode in der Kindklasse
einfach überschrieben werden. Bei der Erweiterung auf weitere Analyseverfahren kann auf
bereits bestehende Klassen zurückgegriffen werden, der Programmieraufwand verringert
sich also.
6 Programmiersprachen
6
69
Programmiersprachen
Im Folgenden soll die Implementierung des FEM-Softwaresystems mit verschiedenen
Hochsprachen diskutiert werden. Als Kriterien bei der Auswahl einer Programmiersprache
werden dabei
•
die Unterstützung des objektorientierten Programmierens,
•
die erreichbare Laufzeiteffizienz,
•
die Portabilität und
•
die Verbreitung
der einzelnen Sprachen verglichen und bewertet. Dazu werden die folgenden
Hochsprachen kurz vorgestellt und auf ihre Eignung zur Realisierung des zu erarbeiteten
FE-Programms untersucht:
1.
Prozedurale Programmiersprachen:
FORTRAN und C
2.
Genuine objektorientierte Programmiersprachen:
Smalltalk und Eiffel
3.
Hybride objektorientierte Programmiersprachen:
Ada, C++ und Java
Genuine objektorientierte Programmiersprachen sind Neuentwicklungen, die einen
generellen Bruch mit den anderen bekannten Programmierstilen vollzogen haben und damit
ausschließlich objektorientierte Programmierung erzwingen. Neben den genannten genuinen
Programmiersprachen würden sich noch eine Reihe anderer rein objektorientierter Sprachen
wie Sather, Beta, und Dylan anbieten. Sie zeichnen sich durch sehr moderne und konsistente
Sprachmodelle aus, sind aber zum gegenwärtigen Zeitpunkt kaum verbreitet und werden
darum nicht mit aufgenommen [28]
Neben den genuinen existieren aber auch hybride – um objektorientierte Konzepte
erweiterte – Programmiersprachen, die den oben formulierten Kriterien zur Realisierung
objektorientierter Software genügen, aber zusätzlich konventionelle Konzepte der Sprache
beibehalten, aus denen sie hervorgegangen sind. Zu dieser Klasse gehört z.B. C++ als
Erweiterung der Sprache C [13]. Die Entwicklungslinien von Programmiersprachen werden
in Abbildung 6-1 dargestellt. Die erste objektorientierte Programmiersprache war Simula.
Diese hat die Entwicklung aller objektbasierten und –orientierten Programmiersprachen sehr
stark beeinflusst.
70
Programmiersprachen
Lambda Kalkül
Assembler
Logikkalküle
Fortran
1960
Lisp
Algol 60
Basic
PL/1
Fortran IV
Simula 67
Algol 68
1970
Pascal
Smalltalk-72
g
Prolog
Smalltalk-74
g
Smalltalk-76
1980
Flavors
Smalltalk-78
Fortran 77
C
Loops
Smalltalk-80
C mit Klassen
Common Lisp
Ada
g
Objective C
Common Loops
C++ 1.xx
New Flavors
Eiffel
Object Pascal
Turbo Pascal
CLOS
C++ 2.xx
Prolog++
1990
Fortran 90
C++ 3.xx
Java
C++ 4.xx
Ada 95
Objektbasierte
g
Sprache
Fortran 95
funktional
prozedural
Objektorientierte
Sprache
logisch
Abbildung 6-1: Entwicklungslinien der Programmiersprachen
Unterstützung eines objektorientierten Programmierstils
Objektorientierte Programmiersprachen werden genauer in objektbasierte, klassenbasierte und objektorientierte Sprachen unterteilt. Die Begriffsbestimmungen sind in der
Literatur
allerdings
nicht
eindeutig.
Folgende
Unterscheidungen
werden
nach
Bannert/Weizel [1] angegeben:
Objektbasiert: Sprachen heißen objektbasiert, wenn Objekte Daten und Methoden
kapseln können und eine Objektidentität haben [1]. Das Abstraktionsprinzip wird nur
dadurch unterstützt, dass Objekte erzeugt werden, die durch Nachrichten miteinander
kommunizieren und Methoden ausführen. Dadurch werden Manipulationen des Zustands
der Objekte vorgenommen [13].
6 Programmiersprachen
71
Klassenbasiert: Sprachen heißen klassenbasiert, wenn sie objektbasiert sind und jedes
Objekt zu einer Klasse gehört, wobei diese Klassen aber keine Oberklassen haben.
Objektorientiert: Sprachen, die klassenbasiert sind, zusätzlich Vererbung zwischen
Klassen
ermöglichen
und
Polymorphie
zulassen,
heißen
objektorientiert
[1].
Objektorientierte Sprachen zeichnen sich durch ihre weitreichenden Fähigkeiten aus, neue
Typen einzuführen und deren Eigenschaften realitätsnah abzubilden. Diese Eigenschaften
umfassen im wesentlichen das Verhalten von Abstraktionen sowie die Repräsentation von
Beziehungen zwischen Abstraktionen [28].
+ Vererbung
+ Polymorphie
+ Klassen
objektbasiert
klassenbasiert
z.B. Ada
objektorientiert
z.B. Eiffel, Smalltalk
Abbildung 6-2: Objektbasierte, klassenbasierte und objektorientierte Programmiersprachen
Typbindung
Das wesentliche Charakteristikum der objektorientierten Programmierung ist die
Fähigkeit, Objekte zu verwenden, die zur Laufzeit möglicherweise Objektwerte aus
verschiedenen Objektklassen annehmen können. Dadurch kann die konkrete Zuordnung der
Methodenimplementierung zu einer Nachricht an ein solches polymorphes Objekt erst zur
Laufzeit durch die Klassenzugehörigkeit des zugeordneten Objektwertes bestimmt werden.
Eine notwendige Voraussetzung für diese Eigenschaft ist die Möglichkeit, gleich benannte
Methoden in verschiedenen Klassen unterschiedlich zu implementieren. Da in getypten
Programmiersprachen Polymorphie auf abgeleitete Klassen eingeschränkt ist, muss die
Möglichkeit der Klassenkonstruktion durch Ableiten ebenfalls gegeben sein (mit Vererbung
und ggf. Redefinition von Methoden) [13].
Programmiersprachen werden entsprechend der Rolle, die die Typisierung dort spielt,
in zwei Klassen unterschieden: statisch und dynamisch getypte Sprachen. In statisch
getypten Programmiersprachen (FORTRAN, C++) wird den Variablen ein Typ in einer
expliziten Deklaration zugewiesen und festgelegt, wie der Wert einer Variablen interpretiert
und manipuliert werden kann. Bei der sogenannten dynamischen Typisierung wird die
Typinformation nicht mit der Variablendeklaration abgelegt, sondern der Wert einer
Variablen enthält seine Typinformationen. Funktionen können nun so programmiert werden,
dass sie abhängig von der Typisierung ihrer Argumente unterschiedliche Aktionen
durchführen können.
72
Programmiersprachen
Bei dem Vergleich der beiden Typisierungsarten stehen Effizienz und Fehlererkennung
der statischen Typisierung auf der einen Seite der Flexibilität der Programmentwicklung
durch dynamische Typisierung auf der anderen Seite gegenüber. Der Vorteil bei der
Verwendung von Polymorphie liegt auf der Hand: der Programmierer muss nicht mehr die
gesamte verwendete Typmenge übersehen und hat somit größere Freiheiten bei der
Codierung. Wenn neue Typen eingeführt werden, müssen nicht mehr alle Typisierungen von
Identifikatoren überprüft werden, soweit sich der Programmierer sicher ist, dass in Folge
einer Zuweisung dieser Variable mit Objekten der neuen Typen auch die darauf
operierenden Funktionen ausführbar sind. Funktionen können, abhängig von der
Typzugehörigkeit der Werte ihrer Argumente, verschieden reagieren, bzw. verschiedene
Objekte können auf die gleiche Nachricht (d.h. gleichen Methodenaufrufwunsch)
verschieden reagieren [13].
Im Folgenden werden die oben genannten Programmiersprachen vorgestellt.
6.1
Prozedurale Programmiersprachen
6.1.1
Fortran
Fortran (FORmula TRANslation) ist die erste höhere Programmiersprache. Sie wurde
zwischen 1954 und 1957 von einem IBM-Team für wissenschaftliche und algebraische
Programmierung entwickelt. Das Hauptanliegen war, die umständliche und fehleranfällige
Programmierung in Assembler zu vereinfachen. Da Computer damals vor allem zur
Unterstützung
mathematischer
Berechnungen
herangezogen
wurden,
sind
die
Sprachelemente stark an der Formelschreibweise der Mathematik orientiert. Die Nachfolger
sind noch heute bei wissenschaftlichen Anwendungen, bei denen Berechnungen im
Vordergrund stehen, dominierend. FEM-Programmsysteme oder damit verbundene
Algorithmen in Fortran werden von den verschiedensten Autoren vorgestellt (Bathe [2],
Krätzig [20]). Das Überleben von Fortran liegt zumindest teilweise daran, dass seine
Compiler immer noch zu den effizientesten gehören, die verfügbar sind, da sie sehr
schnellen Code erzeugen.
Dies war auch eines der wichtigsten Ziele der ursprünglichen Entwicklungsbemühungen, da man zu der Zeit annahm, dass das Schreiben von Programmen in „höheren“
Sprachen im Vergleich zu Assemblersprachen oder direkt erzeugtem Maschinencode zu
ineffizient sei.
6 Programmiersprachen
73
Fortran wurde in der Version Fortran IV 1966 international genormt (ISO), und
überarbeitete Standards wurden 1977 (Fortran 77) bzw. 1991/92 (Fortran90) verabschiedet.
Betrachtet man Fortran nach Kriterien, die heute eine „gute“ Programmiersprache
ausmachen, so sind die frühen Versionen eher als unzureichend einzustufen. Die
Möglichkeiten der Datenvereinbarung waren beschränkt, Ablaufsteuerung war nur teilweise
möglich. Mit dem Fortran90-Standard wurde die Sprache erheblich verändert und um
moderne Konzepte erweitert, die zu einer deutlichen Verbesserung führten. So wurde ein
Modulkonzept realisiert, Steuerkonstrukte erhöhen die Lesbarkeit der Fortran-Programme
und für Matrizenrechnung sind Sprachelemente vorgesehen. Datentypen, Operationen und
rekursive Prozeduren können vom Benutzer definiert werden. Viele frühere Restriktionen
(z.B. die Länge der Variablennamen) wurden aufgehoben oder verändert.
Wie bereits erwähnt, steht Fortran in direkter Relation zu den Top-Down
Entwurfsverfahren. Fundamentale Abstraktionseinheit ist das Unterprogramm. Ein
objektorientiertes Programmsystem wie es in Kapitel 5 vorgestellt wurde, ist mit Fortran nur
schwer und mit großem Aufwand zu realisieren. Um die Laufzeiteffizienz von Fortran auch
für moderne Architekturen nutzen zu können, wurde 1992 eine Arbeitsgruppe gegründet, die
einen neuen Sprachstandard erarbeiten soll, die unter anderem objektorientierte
Erweiterungen und Sprachelemente für Parallelverarbeitung enthalten wird [22]. Der
aktuelle Stand ist Fortran95 (ISO-Norm 1997), das allerdings nur eine minimale Änderung
zu Fortran90 darstellt. Die nächste Revision (Fortran 2000) wird voraussichtlich 2004
veröffentlicht. Diese wird unter anderem ein ausgedehntes Exception handling beinhalten,
eine verbesserte Interaktion mit C, das Erstellen von Datentypen z.B. für parametrisierte
Typen,
High
performance
numerische
Berechnungen
und
Konzepte
für
die
Objektorientierung [25]. Daher kann man vielleicht bald auch für Programmsysteme wie
dem oben beschriebenen die hohe Effizienz dieser Sprache nutzen, ohne auf die Vorteile der
objektorientierten Programmierung verzichten zu müssen.
6.1.2
C
C wurde Anfang der 70er Jahre von Dennis Ritchie an den Bell Laboratories in New
Jersey (USA) entwickelt. Ziel der Entwicklung war es, eine möglichst einfache und
effiziente
Programmiersprache
zu
schaffen.
Als
Ergebnis
entstand
eine
relativ
maschinennahe Sprache, die die Effizienz von Assemblersprachen und wichtige Konzepte
höherer Programmiersprachen wie Algol und Pascal in sich vereint. Der Sprachumfang von
C ist eher klein. So gibt es keine Operationen, die direkt zusammengesetzte Objekte wie
74
Programmiersprachen
Arrays, Records oder Zeichenketten als Ganzes verarbeiten. Des weiteren besitzt C keine
Anweisungen für die Ein-/Ausgabe oder eingebaute Zugriffstechniken für Dateien. All diese
Operationen werden durch explizit aufzurufende Funktionen realisiert, die in umfangreichen
Bibliotheken zur Verfügung stehen. Auffallend sind die im Sprachumfang enthaltenen
Operationen für die Bitmanipulation, wie sie von maschinenorientierten Sprachen her
bekannt sind.
Obwohl C ursprünglich für die Systemprogrammierung verwendet wurde (z.B. Unix),
stellt C eine allgemeine höhere Programmiersprache dar. Die Gründe für die weite
Verbreitung liegen einerseits in der Effizienz, vor allem aber in der Portabilität der CProgramme. Compiler für C sind auf fast allen modernen Rechnern und Betriebssystemen
verfügbar. 1990 wurde C international standardisiert, allerdings gibt es im Vergleich zu
anderen Programmiersprachen sowieso kaum C-Dialekte, soweit der engere Sprachkern
betrachtet wird.
Die in C verwendeten Kontrollstrukturen sind einfach. Sie reichen dennoch aus, um
wohlstrukturierte Programme zu erstellen. Darüber hinaus erlaubt C die getrennte
Übersetzung von Programmteilen, so dass die modulare Entwicklung größerer
Programmsysteme unterstützt wird. Im Gegensatz zu anderen Programmiersprachen legt C
dem Programmierer nur wenig Restriktionen auf. Zum Beispiel existiert kein strenges
Typkonzept. Allerdings besteht gerade aufgrund dieser hohen Flexibilität und der
zahlreichen Freiheitsgrade die Gefahr, dass Programme schnell unleserlich und in hohem
Maße unverständlich werden [22].
6.2
Genuine objektorientierte Programmiersprachen
6.2.1
Smalltalk
Smalltalk wurde seit den 70er Jahren am Xerox PARC (Palo Alto Research Center)
entwickelt. Zusätzlich zu den Eigenschaften anderer Sprachen beinhaltet Smalltalk auch eine
Entwicklungsumgebung. Innerhalb dieser Umgebung, die Vorläuferin für alle heute
bekannten grafischen Benutzungsoberflächen ist, stehen Grundklassen, ein symbolischer
Debugger und der volle Zugriff auf alle vorhandenen Klassen zur Verfügung [9].
Smalltalk kennt im Prinzip nur einen Typ, nämlich den Typ Objekt, das heißt alle
Konstrukte werden als Objekte und ihre Typen als Klasse interpretiert [1]. Das bedeutet,
dass auch Klassen ihrerseits Objekte sind. Alle Daten innerhalb von Klassen sind geschützt,
6 Programmiersprachen
75
es können nur Methoden exportiert werden. Attribute werden nur in neueren Versionen
mehrfach vererbt.
Smalltalk
zeichnet
sich
durch
eine
durchgehend
dynamische
Typ-
und
Methodenbindung aus. Generische Klassen sind nicht notwendig, da die Sprache typenlos
ist. Sie erlaubt polymorphe Zugriffe und eine automatische Speicherbereinigung.
Nebenläufigkeit wird nicht unterstützt.
Smalltalk ist eine Sprache, bei deren Entwicklung auf Portabilität hohen Wert gelegt
wurde, sie wird sowohl interpretiert als auch compiliert. Der Smalltalk-Code wird zunächst
in einen Byte-Code übersetzt und dann durch eine Smalltalk Virtual Machine interpretiert.
Die Stärke von Smalltalk ist eine Entwicklungsumgebung, die extrem gut für schnelle
Prototypenentwicklung geeignet ist. Als Nachteil wird gesehen, dass diese Umgebung
relativ
geschlossen
ist.
Eine
Anbindung
bestehender
Programme
aus
anderen
Programmiersprachen ist nur schwer zu erreichen [9].
6.2.2
Eiffel
Die Programmiersprache Eiffel wurde mit dem Ziel der Robustheit, Korrektheit,
Portierbarkeit und Effizienz entworfen. Aus Effizienzgründen dient als Zwischensprache bei
der Übersetzung die Sprache C. Im Gegensatz zu Smalltalk werden Klassen und Objekte
unterschieden. Klassen entsprechen, wie oben definiert, der Implementierung abstrakter
Datentypen. Durch die Unterscheidung zwischen der Klasse als Typ und einem Objekt als
Laufzeitelement wird eine statische Typ- und Methodenbindung eingeführt. Sie erlaubt
weniger Laufzeitfehler und erwirkt eine größere Effizienz der Programme. Methoden und
Daten der Klassen werden explizit zugänglich gemacht.
Herausragende
Eigenschaften
von
Eiffel
sind
generische
Klassen
und
die
Zusicherungen über Objekte in Form von Vor- und Nachbedingungen sowie Invarianten.
Diese Zusicherungen dienen dem Nachweis der Korrektheit von Programmen und werden
auch an Kindklassen vererbt. Mehrfache Vererbungen sind gestattet. Konflikte in mehrfach
geerbten Attributen werden durch Umbenennung gelöst. Weiterhin erlaubt die Sprache
polymorphe Zugriffe und stellt eine automatische Speicherverwaltung zur Verfügung.
Nebenläufigkeit ist nicht möglich. Die Persistenz von Objekten wird nur über eine
Bibliotheksfunktion realisiert und ist daher noch nicht zufriedenstellend gelöst. Trotz der
vermeintlich großen Vorteile durch die Zusicherung von Bedingungen und der effizienten
Umsetzung durch die Zwischensprache C wird Eiffel für den Einsatz in kommerziellen
76
Programmiersprachen
Anwendungen eher schlecht beurteilt. Für Ausbildungszwecke wird sie inzwischen
erfolgreich eingesetzt [9].
6.3
Hybride objektorientierte Programmiersprachen
6.3.1
Ada
Ada
geht
auf
eine
internationale
Ausschreibung
des
amerikanischen
Verteidigungsministeriums zurück, das die Entwicklung einer einzigen, gemeinsamen,
höheren Programmiersprache für die Softwareentwicklung propagierte; sie ist seit 1983
verfügbar. Unmittelbare Vorfahren von Ada sind u.a. Pascal und Simula [5]. Von Ada
existieren keine Dialekte, da Ada bereits genormt wurde, bevor Ada-Übersetzer entwickelt
werden konnten. Zusätzlich ist der Name Ada® als eingetragenes Warenzeichen des
amerikanischen Verteidigungsministeriums geschützt. Ada entstand in der „Blütezeit“ des
Software
Engineering
und
kommt
daher
den
Anforderungen
an
eine
gute
Programmiersprache sehr nahe. Der Einsatzbereich deckt nicht nur die traditionelle
Datenverarbeitung ab, sondern auch andere Anforderungen, wie z.B. aus der
Prozesssteuerung und aus dem militärischen Bereich.
Entsprechend ihren Designern wurde Ada unter Berücksichtigung der Gesichtspunkte
Zuverlässigkeit, Wartbarkeit und Effizienz von Programmen entworfen. Vor allem die
Herstellung umfangreicher Programmsysteme, die im Allgemeinen arbeitsteilig in Teams
erfolgt, sollte vereinfacht werden. Aus diesem Grund ist ein ausgefeiltes Modulkonzept
(Packages) realisiert, das die Zerlegung komplexer Systeme, die Spezifikation der Module
und die getrennte Entwicklung und Übersetzung derselben unterstützt. In Verbindung mit
dem Modulkonzept ist es möglich eigene strukturierte Datentypen einzuführen (abstrakte
Datentypen).
Ada gehört zu den objektbasierten Programmiersprachen, das heißt Daten und
Methoden werden in den Objekten gekapselt. Ada ist eine extrem typenstrenge Sprache,
Polymorphie ist nicht möglich. Auch Vererbung ist durch die Objektbasiertheit kein
Element des ursprünglichen Konzepts von Ada. Persistenz von Objekten wird nicht
unterstützt. Dafür sind in Ada generische Konstrukte zugelassen [5].
1995 wurde Ada erneut genormt. In dem neueren Standard sind aktuelle Entwicklungen
berücksichtigt. Sprachelemente für die objektorientierte Programmierung wurden erweitert
oder neu aufgenommen (z.B.Vererbung) sowie die bestehenden Konzepte für Datentypen
6 Programmiersprachen
77
und Parallelverarbeitung weiter ausgebaut und stabilisiert [22]. Ada95 hat sich damit von
einer objektbasierten zu einer objektorientierten Sprache entwickelt.
6.3.2
C++
C++ ist eine hybride Programmiersprache. Im Prinzip ist C++ die Erweiterung der
Sprache C um objektorientierte Konzepte mit dem Entwurfsziel der Portabilität und der
Effizienz. Das Ergebnis ist ein Kompromiss zwischen dem objektorientierten Ideal und
Pragmatismus.
Wesentliche Merkmale sind das Überladen von Operatoren, so dass z.B. mit Objekten
wie mit ganzen Zahlen „gerechnet“ werden kann. Der Zugriff auf Attribute von Objekten
kann gesteuert werden. Eine spezielle Deklaration kann Klassen gegenseitig oder anderen
Funktionen zugänglich machen. Eine automatische Speicherplatzverwaltung ist allerdings
nicht vorgesehen [9].
Der bedeutendste Vorzug von C++ ist die Flexibilität zwischen hardwarenahen
Funktionen und den abstrakten, objektorientierten Konzepten sowie die weite Verbreitung
der Sprache (ca. 80% des Marktes für objektorientierte Sprachen). Letzteres liegt nicht
zuletzt an der Aufwärtskompatibilität zu C. Bestehende, in C implementierte Systeme
können um C++-Software erweitert werden. Diese Aufwärtskompatibilität ist andererseits
auch das wesentlichste Problem von C++. Objektorientiertes Programmieren kann durch die
nach wie vor möglichen konventionellen Konzepte umgangen werden. Untersuchungen von
AT&T, die C++ ursprünglich erstellten, zeigen, dass nur etwa jedes zehnte Programm, das
in C++ geschrieben wird, überhaupt auf Klassen und damit auf ein Grundkonstrukt der
Objektorientierung in C++ zurückgreift [9].
Ein Problem ergibt sich auch aus dem Zwang, die grundlegenden Mechanismen der
Sprache C zu erlernen, um die objektorientierten Konzepte von C++ anwenden zu können
[13]. Die Vorzüge der objektorientierten Programmierung können durch die Verwendung
bestimmter Optimierungsmöglichkeiten im Programm eingeschränkt werden. Hinzu kommt,
dass einige objektorientierte Konzepte nicht unterstützt oder nur simuliert werden
(dynamischer Polymorphismus) [1]. Hier bietet eine genuine Sprache wie Eiffel oder
Smalltalk sicher reichere Konzepte. Um z.B. polymorphe Variablen zu realisieren, muss also
auf jeden Fall der Speicherbereich von der Variablen abgekoppelt werden. Hierzu werden
sogenannte Zeigertypen benutzt: eine Variable nimmt jetzt nur einen Verweis auf ein Objekt
(also auf dessen Speicherbereich) aus. Wird an das durch die Variable so referenzierte
Objekt eine Nachricht gesendet, werden zur Laufzeit – wie in dynamisch getypten Sprachen
78
Programmiersprachen
– Typinformationen vom Wert der Variablen eingeholt und die passende Methode
aufgerufen. Deswegen nennt man dieses auch das dynamische Binden einer Methode an eine
Nachricht. Die Effizienznachteile bestehen hier aber auch [13].
C++-Compiler sind ebenfalls weit verbreitet. Eine Einbindung von Programmcode in
Fortran oder C ist möglich. Speziell für das Arbeiten mit dem in C implementierten
Betriebssystem Unix ergibt sich der Vorteil des leichten Zugangs zu den umfangreichen
Betriebssystembibliotheken über die C-Schnittstelle.
Ebenso wie C-Code gilt C++-Code als sehr effizient und portabel [13]. Die
Grundsprache C++ ist wie C grundsätzlich plattformunabhängig. Zu dieser Grundsprache
gehören allerdings nur Konsolenbefehle. Sobald eine Oberfläche einbezogen wird, ist ein
Umstieg von einem Betriebssystem zu einem anderen schwierig. Dieses Problem wird durch
Eigenkreationen wie z.B. die MicrosoftFoundationClasses (MFC) weiter verschärft.
In den letzten Jahren wurde neben der Sprache auch eine Klassenbibliothek normiert,
welche die wichtigsten Anforderungen der objektorientierten Programmierung unterstützen
soll. Diese Klassenblibliothek (STL – „standard template library“) ist inzwischen
Bestandteil aller wichtigen Entwicklungsumgebungen [9].
6.3.3
Java
Java wurde unter dem Gesichtspunkt der Sicherheit, Robustheit und der portablen
Anwendbarkeit in heterogenen Rechnernetzen entwickelt. Dadurch ist sie heute zu einem
Synonym für eine Programmiersprache „für das Internet“ geworden. Die Entwicklung
erfolgte ab 1990 und führte 1993 zu einer ersten Veröffentlichung als Programmiersprache,
die im Rahmen von HTML-Seiten interpretiert werden kann.
Java ist einerseits Programmiersprache und stellt andererseits eine Klassenbibliothek
zur Verfügung. Die Klassenbibliothek von Java enthält Klassen für die Erstellung von
Applikationen, also beispielsweise einfache Oberflächenelemente, Klassen für die
Kommunikation,
zur
Ausnahmebehandlung
sowie
für
die
Grafik-
und
Netzwerkprogrammierung.
Als Programmiersprache lehnt sie sich stark an C++ an. Viele der Konstrukte dieser
Sprache wurden jedoch aus Sicherheitsgründen modifiziert bzw. eliminiert. Hierzu gehört
die Abschaffung von Verweisen („pointer“), die immer eine Quelle der Unsicherheit bei der
Programmierung darstellen. Funktionen außerhalb von Klassen sind nicht erlaubt, so dass
keine Verwirrung darüber entstehen kann, ob ein Aufruf sich auf eine Methode oder auf eine
Funktion bezieht.
6 Programmiersprachen
79
„Offene“ Klassen, also die in C++ vorhandenen Strukturen, sind, ebenso wie
automatische Typkonvertierungen, nicht Bestandteil der Sprache. Mehrfachvererbung ist
ebenfalls nicht möglich, allerdings bietet Java eine automatische Speicherplatzverwaltung
[9].
Da die Sprache ein besonderes Ausführungsmodell verwendet, werden alle Datentypen
zunächst plattformunabhängig definiert, d.h. in Größe und Interpretation vereinheitlicht.
Über einen Compiler wird der Java-Code in einen portablen Byte-Code übersetzt (ähnlich zu
Pascal), der bei der Ausführung auf einem beliebigen Rechner durch eine dort vorhandene
generische Java Virtual Machine interpretiert wird. Dieses beinhaltet einen Verlust an
Laufzeiteffizienz gegenüber fertig kompilierten Programmsystemen und ist daher für FEMProgramme
ungeeignet.
Allerdings
gibt
es
bereits
verschiedene
Ansätze
die
Laufzeiteffizienz von Java zu steigern: Zum einen wird an der Entwicklung besonderer
Mikroprozessoren gearbeitet, deren Befehlssatz dem Java Byte-Code entspricht. Zum
anderen existieren bereits Systeme, die den Programmcode während der Ausführung des
Programms übersetzen (Just-in-time-compilation). Daher kann man vielleicht bald auch für
FEM-Programmsysteme die Portabilität dieser Sprache nutzen, ohne hohe Verluste in der
Laufzeiteffizienz in Kauf nehmen zu müssen [28]
6.4
Vergleich und Auswertung
Ein wichtiges Kriterium für die Wahl einer Programmiersprache für den
Programmentwurf aus Kapitel 5 ist die Menge der Sprachelemente, die sie für eine
objektorientierte Programmierung zur Verfügung stellt.
Die Objektorientierung ist letztendlich ein Programmierstil und nicht abhängig von der
Sprache in der sie umgesetzt wird, allerdings beruht die Topologie der meisten
Programmiersprachen mehr oder weniger auf den Konzepten eines bestimmten
Programmierstiles (vgl. Kapitel 3). Programmiersprachen die ebenfalls objektorientiert
arbeiten, unterstützen einen objektorientierten Entwurf wesentlich besser als konventionelle
Programmiersprachen wie z.B. Fortran, die als fundamentale Abstraktionseinheit
Unterprogramme verwendet und in direkter Relation zu einem prozedurorientierten
Programmierstil und den angesprochenen Top-Down Entwurfsverfahren steht [28]. Eine
Realisierung des Entwurfes in Fortran würde letztendlich nur Abstraktionen auf einem
wesentlich niedrigeren Level als für eine objektorientierte Programmierung notwendig
zulassen.
Damit
könnten
die
oben
genannten
Vorteile
einer
objektorientierten
80
Programmiersprachen
Programmierung (Modularität, Wiederverwendbarkeit, Übersichtlichkeit usw.) nicht genutzt
werden.
Um alle Vorteile der objektorientieren Programmierung zu nutzen, bietet sich eine
(genuine) objektorientierte Programmiersprache an. Eine Kurzübersicht über die
Sprachelemente, die die verschiedenen objektorientierten Sprachen zur Verfügung stellen,
gibt die Tabelle 6-1. In diesem Fall wäre Smalltalk die Sprache der Wahl, da sie insgesamt
eine saubere objektorientierte Programmierung erzwingt und ausreichend Konzepte zur
Verfügung stellt. Ein einfaches objektorientiertes FEM-Programm in Smalltalk wurde
bereits 1992 von Dubois-Pélerin und Zimmermann [12] vorgestellt.
Smalltalk
Eiffel
Ada(83)
C++
Java
+
+
+
+
+
+
-
+
+
-
+
+
+
+
+
+
+
+
+
-, +
-, +
-, +
-, #, +
-, #, +
-, +
-, +
Modularität
-
Unit
Package
Datei
Package
Vererbung
+
+
-
+
+
Mehrfachvererbung
-
+
-
+
-
Ja (einfach)
+
-
+
+
d
s
s
s/d
s/d
indirekt
-
+
indirekt
+
Persistenz
-
-
-
-
-
Generizität
-
+
+
+
-
Abstraktion
Instanzvariable
Instanzmethode
Klassenvariable
Klassenmethode
Kapselung
Variablen
Methoden
- private, # protected, + public
Polymorphismus
Typbindung
s: statisch , d: dynamisch
Nebenläufigkeit
Tabelle 6-1: Objektorientierte Konzepte der verschiedenen Hochsprachen
Legt man bei der Wahl der Programmiersprache das Hauptaugenmerk auf die zu
erreichende numerische Effizienz, dann werden objektorientierte Sprachen gegenüber den
prozeduralen eher schlecht beurteilt. Die prozedurale Programmierung lehnt sich an die
Organisation der Operationen und Daten im Computer selber an, ist also bei der Ausführung
effizienter als eine objektorientierte Programmstruktur. Die hohen Abstraktionsebenen
(Kapselung, Hierarchie) gehen auf Kosten der Rechengeschwindigkeit. Bei einer
Implementierung in Smalltalk beeinträchtigen zusätzlich die dynamische Typisierung und
6 Programmiersprachen
81
die Interpretation des Programmcodes (anstatt Kompilierung) die Laufzeiteffizienz. Die
Entwicklungsumgebung ermöglicht zwar das schnelle Erstellen eines Prototyps, verhindert
aber das Einbinden vorhandener Algorithmen z.B. aus Fortran oder C. Insgesamt wird eine
Implementierung eines FEM-Programmes für praktische Anwendungen in Smalltalk
ungünstig beurteilt [11].
Tabelle 6-2 (aus [19] und [25]) vergleicht Geschwindigkeit und Strukturen der
Programmiersprachen C, C++ und Fortran77 bzw. 95 für numerische Berechnungen.
Fortran77 und Fortran95 dominieren dabei mit ihren hochoptimierten Compilern in Bezug
auf die erreichbare Effizienz. C hat weiterhin den gravierenden Nachteil, dass dynamische
Matrizen langsam und unhandlich sind und keine weitergehenden Strukturen für numerische
Berechnungen vorhanden sind. Außerdem ist das Erreichen einer guten Laufzeiteffizienz
unter anderem vom Programmierstil (und damit von der Erfahrung des Programmierers)
abhängig.
Für ein Optimum an numerischer Effizienz wird man also auf einen prozeduralen
Programmierstil und eine Programmiersprache wie Fortran zurückgreifen. FEM-Programme
in Fortran sind weit verbreitet und werden von den verschiedensten Autoren vorgestellt. Ein
Entwurf wie er in Kapitel 5 vorgestellt wird, kann in Fortran allerdings bis jetzt nicht
verwirklicht werden. Es bleibt abzuwarten, ob der neue Standard 2004 genügend Konstrukte
für objektorientierte Programmierung enthält, um eine solche Programmstruktur zu
verwirklichen.
Eine Programmierung mit einer hybriden objektorientierten Programmiersprache, z. B.
C++,
kann einen guten Kompromiss zwischen den Vorzügen einer objektorientierten
Programmierung und einer guten Laufzeiteffizienz bieten (vgl. Tabelle 6-2: Eignung für
numerische Berechnung: Fortran77, Fortran 90, C, C++). Wichtig für die Wahl von C++ ist,
dass C++ alle wesentlichen Vorzüge der objektorientierten Programmierung sicherstellt,
durch seine Verwandtschaft mit C aber eine relativ hohe Geschwindigkeit erreichen kann.
Ein effizienter Programmcode in C++ wird durch den umfassenden Gebrauch der Konzepte
einer objektorientierten Programmierung und der Optimierung für einige wenige
zeitkritische Operationen erreicht. Für diese Optimierung wird auf die niedrigen
Abstraktionsgrade
(“low-level“-Konstrukte)
der
prozeduralen
Programmierung
zurückgegriffen, die C++ von C geerbt hat (vgl. Abbildung 6-3). Es findet also eine
Vermischung eines objektorientierten Entwurfs mit prozeduralen Programmiertechniken
statt.
82
Programmiersprachen
Besonderheiten
•
C
dynamische Matrizen langsam (indirekte
Adressierung) oder unhandlich
weit verbreitet bei SystemProgrammierern
keine besonderen Abstraktionen für
Numerik
Parametrisierung von Klassen mittels
Templates
Überladen von Operatoren
komplexe Zahlen, schnelle Vektoren
kleine Bibliothek für Numerik
die Sprache für objektorientierte
Numerik
Potenzierungsoperator: A**B
komplexe Zahlen
überladene Standardfunktionen
lange die Sprache für numerische
Anwendungen
große vorhandene Basis an Programmen
und Bibliotheken
programmiertechnisch veraltet
Matrixfunktionen
abstrakte Datentypen incl. Operatoren
portable Standardtypen incl. komplexer
Zahlen
(fast) kompatibel zu Fortran77 und 90
(alte Programme, Bibliotheken)
•
•
•
C++
•
•
•
•
Fortran77
•
•
•
•
•
Fortran95
Geschwindigkeit
•
•
•
•
•
•
Compiler-Optimierung auf
höherer Ebene oft nicht effektiv
schneller Code möglich durch
Handoptimierung (``hardwarenah'')
•
•
fast wie C (mit guten Compilern
und optimierter
Programmierung)
•
•
Matrixoperationen sehr schnell
hochoptimierende Compiler
verfügbar
•
so schnell wie FORTRAN77
Tabelle 6-2: Eignung für numerische Berechnung: Fortran77, Fortran 90, C, C++
Ein Nachteil dieses Vorgehens ist, dass einige Vorteile der Objektorientierung (klare
Strukturierung sowie Datenkapselung und Abstraktion) abgeschwächt werden. Zusätzlich
hängt der Erfolg der Optimierung für rechenintensive Prozesse wie bei C weitgehend vom
Programmierstil ab. Eine effiziente Implementation in C++ erfordert also erfahrene
Programmierer.
Abstraktion
Sprachelemente
hoch
Datenkapselung
Klassenvererbung
mittel
Einfache
Datenstrukturen
Sprachen
C/
Fortran 95
C++
Fortran77
Standardprozeduren
niedrig
Zeiger
Abbildung 6-3: Abstraktionslevel in Smalltalk, C++, Fortran, C [32]
Smalltalk
6 Programmiersprachen
83
Dubois-Pélerin et al. stellen in ihrem Artikel [12] Vergleichsrechnungen zwischen zwei
FEM-Programmen an. Das eine ist in Fortran (prozedural) geschrieben, das andere in C++
(objektorientiert); beide Programme haben einen vergleichbaren Umfang.
Die Aufstellung der Systemmatrizen für ein Referenzproblem findet im FortranProgramm wie erwartet wesentlich schneller statt (ca. 30%). Im objektorientierten
Programm wird die Aufstellung der Systemmatrizen an die Elemente delegiert, was eine
Vielzahl von gesendeten Methodenaufrufen bedingt. Dieser Overhead an Nachrichten
verlangsamt die Aufstellung der Matrizen. Im Gegenzug bewältigt das C++-Programm die
Lösung des Gleichungssystems zügiger (ca. 20%).
Insgesamt gibt es Einbußen in der Gesamtlaufzeit des Berechnungskernes bei einer
Implementierung eines FEM-Programms in C++. Dem gegenüber stehen nach wie vor die
bereits genannten Vorteile der objektorientierten Programmierung in C++ (Wartung des
Programms, Erweiterbarkeit, vereinfachte Fehlersuche und –korrektur etc.) [32].
Für das folgende Beispiel wird C++ als Programmiersprache gewählt. C++ stellt alle
notwendigen objektorientierten Konzepte zur Verfügung, um den in Kapitel 5 vorgestellten
Entwurf zu verwirklichen. Es können alle Vorteile, die sich aus einer objektorientierten
Programmstruktur ergeben, genutzt werden. Zusätzlich bietet die Sprache die Möglichkeit,
für rechenintensive Prozesse auf prozedurale Strukturen zurückzugreifen. Bereits
vorhandene Algorithmen in C oder Fortran können in das Programm eingebunden werden.
Zudem ist C++ (z.B. im Vergleich zu Ada) eine weit verbreitete Sprache und Compiler
stehen für nahezu jedes Betriebssystem zur Verfügung.
84
Protokolle und Dokumentation
7
Protokolle und Dokumentation
Das Endergebnis eines Entwurfsprozesses ist ein Dokument, das aus verschiedenen
Diagrammen der UML besteht und das gesamte System vollständig beschreibt. Diese
Beschreibung ist die Basis für die Implementierung. Dazu müssen die bisher erhaltenen
Ergebnisse verfeinert und auf Konsistenz geprüft werden. Für alle Klassen wird das genaue
Verhalten festgelegt. Anschließend werden alle Klassen und Teilsysteme auf Formularen
festgehalten. Die Dokumentation des Entwurfs besteht aus
•
den statischen Entwurfssichten (Klassendiagramme u.a.),
•
den dynamischen Entwurfssichten (Aktivitätsdiagramme, Sequenzdiagramme u.a.)
und
•
der Spezifikation der Klassen.
Für jede Klasse wird ein eigenes Protokoll erstellt. In diesem Protokoll werden die
Attribute und Methoden der Klasse vollständig beschrieben. Es sind alle Spezifikationen
enthalten, die in den UML-Diagrammen beschrieben werden.
Die Informationen, die dieses Protokoll enthalten soll, sind wie folgt gegliedert:
1.
Klasse: (abstrakt/konkret)
2.
Elternklasse(n):
3.
Kindklasse(n):
4.
Spezifiziert in Diagrammen:
5.
Verantwortlichkeit:
6.
Wird assoziiert von Klasse:
7.
Assoziiert Klasse:
8.
Attribute
9.
8.1.
Privat
8.2.
Geschützt
8.3.
Öffentlich
Methoden
9.1.
Privat
9.2.
Geschützt
9.3.
Öffentlich
Bei der Verwirklichung eines Entwurfes in C++ kann dieses Protokoll direkt in die
Implementierung übernommen werden. Die einzelnen Methoden der Klassen werden in
7 Protokolle und Dokumentation
85
einer Datei (*.cpp) unabhängig von der Klassendefinition implementiert. Sie sind nur über
die entsprechende Header-Datei (*.hpp) zugänglich, die diese Methode für die Klasse
definiert. Die Header-Dateien bilden also auch die Schnittstelle einer Klasse zu den anderen
Klassen. Die Header werden analog zum erarbeiteten Protokoll strukturiert. Dies ermöglicht
einen schnellen Übergang vom Entwurf zur Implementation. Die Informationen werden
dabei als Kommentar an den Anfang der Datei gestellt oder als Notiz an die entsprechende
Stelle in den Code gesetzt.
Für eine Programmierung in arbeitsteiligen Teams ist es zudem notwendig, in der
Header-Datei die Information über die vorliegende Version, das letzte Bearbeitungsdatum
und den Bearbeiter zu vermerken. Dieses ist besonders wichtig, wenn bei Klassen während
der Implementation noch Schnittstellen verändert werden. Für jede Versionsänderung sollte
zusätzlich ein neues schriftliches Klassenprotokoll erstellt werden, das explizit die
vorgenommenen Änderungen beschreibt.
Zur Dokumentation des Programmcodes gehört auch eine konsistente Namensgebung
für Attribute und Methoden, sowie der Klassen. Es gilt:
•
Für konzeptionell gleiche Methoden werden gleiche Methodennamen benutzt
•
Für konzeptionell gleiche Attribute werden gleiche Attributnamen benutzt
•
Attributnamen bestehen (soweit möglich) aus
o der Bedeutung des Attributes im „realen“ Problemfeld oder aus dem
Namen des Objektes, das es referenziert
o den Datentyp bzw. der Klasse des Attributs (falls nicht trivial)
o dem Präfix is oder has falls es ein Boolean ist
•
Methodennamen bestehen (soweit möglich) aus
o der Aktion, die die Methode ausführt (Berechnung, Einlesen, Auslesen
u.ä.). Hier wurde verwendet:
get :
Abfragen von Attributen assoziierter Klassen starten
(oder Auslesen aus Datenfile)
give:
Das Ausgeben eigener Attribute
compute: Berechnung von Attributen
assemble: Einlesen lokaler Attribute zu einem Gesamtsystem
(FEM-spezifisch)
solve:
Lösen eines Gleichungssystems
o das Attribut auf das es vornehmlich zugreift
86
Protokolle und Dokumentation
•
Attribute, Variablen und Methodennamen beginnen mit einem Kleinbuchstaben
•
Klassennamen beschreiben
o das Objekt des „realen“ Problemfeldes, das sie darstellen oder
o die Aufgabe, die sie im Entwurf wahrnehmen
•
Klassennamen beginnen mit einem Großbuchstaben
•
Es werden möglichst keine oder nur allgemein übliche Abkürzungen benutzt
Die Einhaltung dieser Benennungsregeln erleichtert das Nachvollziehen von fremden
Entwürfen. Besonders die Einführung von Abkürzungen sollte vermieden werden. Diese
erleichtern zwar zunächst die Arbeit (z.B. weniger Schreibarbeit, weniger Schreibfehler),
sind aber für andere Programmierer oder Anwender nur schwer nachzuvollziehen.
Die Dokumentation der Methoden in der Implementierungsdatei (*.cpp) erfolgt
Methode für Methode. Hierbei wird die Information
•
Version-Nr.:
•
Letzte Bearbeitung am:
•
Bearbeiter:
festgelegt und wenn vom Gesamtdokument abweichend auch für einzelne Methoden notiert.
Beispiele für die Umsetzung dieser Regeln finden sich in der Dokumentation des
Beispielprogramms in Kapitel 8. Zusätzlich findet sich im Anhang ein exemplarisches
Klassenprotokoll. Dort wird die Aufgabe der Klasse, ihre Einbindung in die
Klassenhierarchie und ihre Schnittstelle beschrieben. Zusätzlich wird anhand der
Dokumentation einer fiktiven Schnittstellenerweiterung bzw. Implementationsänderung die
Versionskontrolle dargestellt.
8 Beispielprogramm
8
87
Beispielprogramm
Das erarbeitete Beispielprogramm AllTA (Allgemeine Tragwerks-Analyse) setzt - in
vereinfachter Form - den in den Kapitel 5 vorgestellten Programmentwurf in der
Programmiersprache C++ um. Die Klassenhierarchie des Programms ist soweit ausgebaut,
dass ein dreidimensionales Stabwerk mit der Methode der finiten Elemente berechnet
werden kann. Als Elementtyp ist mit der Klasse Beam3D ein räumliches schubstarres
Balkenelement implementiert
Der Aufbau der Hierarchie ist entsprechend dem Entwurf sehr offen gehalten. Eine
Erweiterung des Programmsystems um weitere Elementtypen oder Methoden der
Berechnung ist mit begrenztem Programmieraufwand möglich.
Zur Überprüfung des Programms wurden vier ebene Rahmen mit unterschiedlichen
Belastungen und Systemangaben mit AllTA berechnet. Die Ergebnisse wurden dann mit
dem zum Vergleich herangezogenen Stabwerksprogramm 4H-NISI der pcae-GmbH
kontrolliert. Die errechneten Knotenverschiebungen und –verdrehungen, sowie die
Schnittgrößenverläufe über die Stabelemente stimmen für die Anzahl der ausgegebenen
Nachkommastellen zu 100% überein. Die Ausgaben sowohl von AllTA als auch dem
Vergleichsprogramm sind im Anhang zu finden.
Im Folgenden wird Eingabe und Ausgabe des Programms AllTA kurz erläutert. Der
Quellcode aller Klassen (Header-Dateien und Implementations-Dateien) ist ebenfalls im
Anhang zu finden. Die Header-Dateien sind durchgehend dokumentiert und enthalten im
Prinzip die in Kapitel 7 angesprochenen Klassenprotokolle. Da es sich allerdings bei den
Klassen jeweils um Version 1.0 handelt, wird im Anhang noch ein fiktives Klassenprotokol
beigefügt, das exemplarisch die Dokumentation der Erweiterung der Klasse ElementFEM
beinhaltet. Die angenommene Versionsänderung enthält zwei Ausweitungen:
-
die Einfügung eines neuen Elementtypes (eine neue Kindklasse) und
-
die Berechnung der Element-Steifigkeitsmatrix durch numerische Integration.
Die numerische Integration ist im vorliegenden Programm noch nicht verwirklicht, da
die einzig bisher vorhandene Kindklasse (Beam3D) ihre Steifigkeitsmatrix direkt berechnet.
8.1
Dateneingabe
Die Dateneingabe erfolgt über eine Datei, in dem alle Informationen über die Struktur
und das zu lösende Problem spezifiziert werden. Der Input-File hat einen beliebigen Namen
88
Beispielprogramm
und ist vom Typ '*.dat' . Der Name der Datei muss dem Programm beim Starten als
Parameter übergeben werden, dabei entfällt die Endung.
Der Input-File enthält verschiedene Abschnitte, die jeweils mit einem 'Keyword'
anfangen. Die Reihenfolge dieser Abschnitte im Input-File ist unerheblich. Abschnitte enden
mit einer Zeile, die zwei Sternchen enthält (**). Die bereits implementierten Keywords sind:
-
Structure
-
Node
-
Material
-
Profile
-
ElementFEM
-
Load
Jede Zeile in einem Abschnitt enthält jeweils die Daten für ein Objekt der zu
erstellenden Struktur. Mit Ausnahme vom Abschnitt Structure fängt jede Zeile mit der
Nummer des Objektes an. Ebenfalls mit Ausnahme von Abschnitt Structure folgt auf jedes
Keyword die Anzahl der Objekte, die in diesem Abschnitt definiert werden.
Im Abschnitt Structure wird ausgelesen, welche Kindklasse von Structure erstellt wird
und welcher Art die Berechnung sein soll, d.h. welche Unterklasse von ProblemDomain von
Structure referenziert wird. Die übrigen Abschnitte repräsentieren die verschiedenen
Komponenten einer (FEM-) Struktur.
Das letzte Zeichen einer Zeile in einem Abschnitt ist ein Sternchen (*). Die
Zahlenwerte in einer Zeile werden über ihre direkt vorangestellten Namen identifiziert (z.B.
'E 200000' bei Material). Kommentare können überall zwischen oder nach Zeilen eingefügt
werden, sie sollten allerdings kenntlich gemacht werden. Sie dürfen allerdings nie zwischen
dem Namen eines Zahlenwertes und dem Zahlenwert selber stehen.
An Einheiten gebundene Werte müssen konform eingegeben werden.
Abschnitt Structure
Keyword-Zeile:
Structure
Daten-Zeile:
Analysis Type [Structure] [ProblemDomain] *
Structure :
=FEM (weitere noch nicht implementiert)
ProblemDomain : =static (weitere noch nicht implementiert)
8 Beispielprogramm
89
Abschnitt Node
Keyword-Zeile:
Node [n]
n:
Anzahl der Knoten
Daten-Zeile:
[i] nDofs [nDof] coord [nc c1 c2 … cnc ] fix [nf f1 f2 … fnf ] load [nl l1 l2 … lnl ] *
i:
nDof:
nc:
c1 c2 ... cnc:
nf:
f1 f2 … fnf :
nl :
l1 l2 … lnl :
Nummer des Knotens
Anzahl der Freiheitsgrade an diesem Knoten
Anzahl der Koordinaten
Knotenkoordinaten
Anzahl der gebundenen Freiheitsgrade
Nummern der gebundenen Freiheitsgrade
Anzahl der Knotenlasten
Nummern der Knotenlasten
Abschnitt Material
Keyword-Zeile:
Material [n]
n:
Anzahl der Materialien
Daten-Zeile:
[i] E [E-Modul] G [G-Modul] *
i:
E-Modul:
G-Modul:
Nummer des Materials
Elastizitätsmodul
Schubmodul
Abschnitt Profile
Keyword-Zeile:
Profile [n]
n:
Anzahl der Querschnitte
Daten-Zeile:
[i] Type [ProfilTyp] [h] A [A] Iy [Iy] Iz [Iz] IT [IT] *
i:
ProfilTyp:
h:
A:
Iy:
Iz:
IT:
Nummer des Querschnitts
=free Æ Explizite Eingabe der Attribute
=IPE, HEA, HEB Æ Auslesen aus Bibliothek
Höhe des Querschnitts (zum Auslesen aus Bibliothek)
Querschnittsfläche
Tragheitsmoment um die y-Achse
Tragheitsmoment um die z-Achse
Tragheitsmoment um die x-Achse (Stabachse)
90
Beispielprogramm
Abschnitt ElementFEM
Keyword-Zeile:
ElementFEM [n]
n:
Anzahl der Elemente
Daten-Zeile:
[i] Type [ElementTyp] nodes [n1 … nN] pro [pro] mat [mat] load [nl l1 l2 … lnl ] *
i:
ElementTyp:
n1 ... nN:
mat:
pro:
nl :
l1 l2 … lnl :
Nummer des Querschnitts
=Beam3D (weitere noch nicht implementiert)
Knotennummern (Anzahl abhängig von ElementTyp)
Nummer des Materials
Nummer des Profils
Anzahl der Elementlasten
Nummern der Elementlasten
Abschnitt Load
Keyword-Zeile:
Load [n]
n:
Anzahl der Lasten
Daten-Zeile:
[i] Type [LastTyp] [Verlauf] comp [nc c1 c2 … cnc ] Lc [nl l1 l2 … lnl ] *
i:
LastTyp:
Verlauf:
nc :
c1 c2 … cnc :
nl:
l1 l2 … lnl :
Nummer der Last
=ElementLoad, NodalLoad
der Verlauf von Lasten über die Stabachse (bei ElementLoad)
=const (weitere noch nicht implementiert)
Anzahl der Lastkomponenten (=Anzahl Dof bei Node !)
Lastkomponenten
Anzahl der Lastfälle zu denen die Last gehört
Nummer der Lastfälle
Beispiel für eine Input-Datei (siehe Kontrollrechnungen):
#Datei unsym_rahmen.dat
# Einheiten: kN, m
Structure
Analysis Type FEM static *
**
Node 4
1 nDofs 6
2 nDofs 6
3 nDofs 6
4 nDofs 6
**
Material 1
coord 3 0. 0. 0.
coord 3 0. 0. 9.
coord 3 12. 0. 0.
coord 3 15. 0. 9.
fix 3 2 4 6
load 1 2 *
fix 6 1 2 3 4 5 6 *
fix 3 2 4 6 *
fix 6 1 2 3 4 5 6 *
8 Beispielprogramm
91
1 E 10000e+03 G 0.8e+08 *
**
Profile 1
1 Type free A 0.05 Iy 0.01 Iz 1 IT 1
**
ElementFEM 3
1 Type Beam3D mat 1 nodes 2 1 pro 1 load 1 1 *
2 Type Beam3D mat 1 nodes 1 3 pro 1 *
3 Type Beam3D mat 1 nodes 3 4 pro 1 *
**
Load 2
1 Type ElementLoad const comp 6 0. 0. 8. 0. 0. 0. Lc 1 1 *
2 Type NodalLoad
comp 6 10. 0. 0. 0. 0. 0. Lc 1 2 *
**
8.2
Datenausgabe
Die Datenausgabe erfolgt in einer Datei, die denselben Namen trägt wie die InputDatei, allerdings vom Typ '*.log ' ist. Zur Kontrolle werden noch einmal alle Komponenten
der Struktur mit ihren Attributen ausgegeben. Danach erfolgt die Ausgabe der
Verschiebungen und Verdrehungen der Knoten und die Stabkräfte für jeden Lastfall. Für die
Stabkräfte wird der Wert an Stabanfang, -mitte und –ende ausgegeben. Output-Dateien sind
im Anhang eingefügt.
92
Literaturverzeichnis
Literaturverzeichnis
[1]
Gabriele Bannert, Martin Weitzel
Objektorientierter Softwareentwurf mit UML
Addison Wesley Longman Verlag GmbH, München 1999
[2]
Klaus-Jürgen Bathe
Finite-Element-Methoden
Springer-Verlag Berlin Heidelberg 1990
[3]
H. Beem, K. Brink, B. Lechtleitner
FEMAS: Finite Element Moduln Allgemeiner Strukturen
Ruhr-Univerität Bochum 1981
[4]
Christoph Butenweg, Carsten Ebenau
Entwicklung eines objektorientierten FE-Programms
Forum Bauinformatik 2000-Junge Wissenschaftler Forschen
Fortschritt-Berichte VDI: Reihe 4, Bauingenieurwesen
VDI-Verlag, Düsseldorf 2000
[5]
Grady Booch
Objektorientierte Analyse und Design
Addison-Wesley, Bonn, Paris [u.a.], 1994
[6]
Grady Booch, Jim Rumbaugh, Ivar Jacobson
Das UML-Benutzerhandbuch
2.Auflage, Addison-Wesley-Longman, Bonn [u.a.] 1999
[7]
Rostislav Chudoba
Finite Element Kernel with Metaobject Protocol
aus: Modern Software Tools for Scientific Computing
Birkhäuser, Boston, Basel, Berlin 1997
[8]
Rotislav Chudoba, Z. Bittnar, P. Krysl
Explicit finite element computation: An object-oriented approach
Computing in Civil and Building Engineering, Pahl & Werner (eds), S. 139-145
Balkema, Rotterdam 1995
[9]
Ute Claussen
Objektorientiertes Programmieren
2. aktual. Ausgabe, Springer-Verlag, Berlin [u.a.] 1998
[10] Guido Drexel
Hierarchische Strukturierung: Objektorientierte Programmierung am Beispiel CheOPS
http://www.sme.de/papers/oop-cheops.html#opattern
Stand 1997, (02.08.2001)
Literaturverzeichnis
93
[11] Yves Dubois-Pèlerin, Thomas Zimmermann, Patricia Bomme
Object-oriented finite element programming: II. A prototype programm in Smalltalk
Computer Methods in Applied Mechanics and Engineering, Vol. 98, S. 361-397
Elsevier Science Publishers B.V. 1992
[12] Yves Dubois-Pèlerin, Thomas Zimmermann
Object-oriented finite element programming: III. An efficient implementation in C++
Computer Methods in Applied Mechanics and Engineering, Vol. 108, S. 165-183
Elsevier Science Publishers B.V. 1993
[13] Helmut Eirund
Objektorientierte Programmierung
B.G. Teubner Stuttgart 1993
[14] Gisela Engeln-Müllges, Fritz Reutter
Numerik-Algorithmen mit ANSI C-Programmen
BI-Wissenschaftsverlag, Mannheim, Leipzig, Wien, Zürich 1993
[15] Otto von Estorff
Unterlagen zur Vorlesung: Nonlinear Structures
Stand: Wintersemester 1999/2000
Arbeitsbereich Meerestechnik II, Technische Universität Hamburg-Harburg
[16] Gregory L. Fenves
Object-Oriented Programming for Engineering Software Development
Engineering with Computers, Vol. 6, S. 1- 15
Springer-Verlag New York Inc. 1990
[17] Bruce W. R. Forde, Ricardo O. Foschi, Siegfried F. Stiemer
Object-oriented Finite Element Analysis
Computers & Structures, Vol. 34, S. 355-374
Civil-Comp Ltd and Pergamon Press plc 1990
[18] Till Jeske
Nitty-Gritty: C++
Addison-Wesley, München, Boston [u.a.] 2000
[19] Peter Junglas
Programmiersprachen für numerische Software – ein Überblick
http://www.tu-harburg.de/rzt/tuinfo/programmentwicklung/sprachen/numsoft/master.html
Stand vom 08.10.1999, (03.09.2001)
[20] Wilfried B. Krätzig
Tragwerke 2: Theorie und Berechnungsmethoden statisch unbestimmter Stabtragwerke
3. Auflage, Springer-Verlag Berlin Heidelberg 1997
[21] Wilfried B. Krätzig, Yavuz Başar
Tragwerke 3: Theorie und Anwendung der Methode der Finiten Elemente
Springer-Verlag Berlin Heidelberg 1997
94
Literaturverzeichnis
[22] Karl Kurbel
Programmierung und Softwaretechnik
Addison-Wesley, Bonn [u.a.] 1997
[23] Kenneth C. Louden
Programmiersprachen: Grundlagen, Konzepte, Entwurf
1. Auflage, International Thomson Publishing GmbH, Bonn 1994
[24] G. R. Miller
An Object-oriented Approach to Structural Analysis and Design
Computers & Structures, Vol. 40, Nr. 1, S. 75-82
Civil-Comp Ltd and Pergamon Press plc 1991
[25] NAG – Numerical Algorithms Group
Revision of ISO/IEC 1539-1 : 1997
(Information technology - Programming languages - Fortran)
http://www.nag.co.uk/sc22wg5/IS1539-1_200x.html, (03.09.2001)
[26] Bernd Oesterreich
Objektorientierte Softwareentwicklung: Analyse und Design mit der Unified Modeling
Language
4., aktual. Ausgabe, R. Oldenburg Verlag 1998
[27] Rational Software Corporation
UML Resource Center
http://www.rational.com/uml/index.jsp (03.09.2001)
[28] Georg Schmid
Zur Entwicklung objektorientierter Finite-Elemente-Programme
Institut für Statik und Dynamik der Luft- und Raumfahrtkonstruktionen
Universität Stuttgart, Stuttgart 1998
[29] U. Starossek
Vorlesungsunterlagen zur Vorlesung Baustatik II
Stand: Sommersemester 2001
Arbeitsbereich Statik und Dynamik der Baukonstruktionen, Technische Universität
Hamburg – Harburg
[30] Bjarne Stroustrup
Die C++ Programmiersprache
4., aktual. Ausgabe, Addison-Wesley, München, Boston [u.a.] 2000
[31] Rebecca Wirfs-Brock, Brian Wilkerson, Lauren Wiener
Objektorientiertes Software-Design
Carl Hanser Verlag München Wien, Prentice-Hall International Inc., London 1993
[32] Thomas Zimmermann , Yves Dubois-Pèlerin, Patricia Bomme
Object-oriented finite element programming: I.Governing principles
Computer Methods in Applied Mechanics and Engineering, Vol. 98, S. 291-303
Elsevier Science Publishers B.V. 1992
Anhang
Anhang
A.
Unified Modeling Language (UML 1.4)
Notationsübersicht
B.
Quellcode des Programms AllTA
C.
Vergleichsrechnungen
D.
Fiktives Klassenprotokoll der Klasse ElementFEM
95
A.
Unified Modeling Language (UML 1.4)
Notationsübersicht
B.
Quellcode des Programms AllTA
Reihenfolge der beigefügten Klassendeklarationen und –definitionen:
Hauptprogramm:
Struktur:
allta.cpp
struc.hpp
struc.cpp
struc_fem.hpp
struc_fem.cpp
comp.hpp
comp.cpp
Knoten:
node.hpp
node.cpp
Material:
material.hpp
material.cpp
Querschnitt:
profile.hpp
profile.cpp
Finite Elemente:
elem_fem.hpp
elem_fem.cpp
beam3D.hpp
beam3D.cpp
Lastfälle:
loadcase.hpp
loadcase.cpp
Lasten:
load.hpp
load.cpp
nodal_load.hpp
nodal_load.cpp
elem_load.hpp
elem_load.cpp
Freiheitsgrade:
dof.hpp
dof.cpp
Berechnungssteuerung:
problem_domain.hpp problem_domain.cpp
Basisklasse für Struktur-Komponenten
Komponenten:
static_fem.hpp
static_fem.cpp
Mathematische Klassen:
matrix.hpp
Hilfsklassen:
string.hpp
string.cpp
point.hpp
point.cpp
file_reader.hpp
file_reader.cpp
C.
Vergleichsrechnungen
Es folgen die Ausgaben von AllTA und 4H-NISI für zwei einfache Systeme:
1. symmetrischer ebener Rahmen mit
•
Einzelkraft am Knoten
•
konstanter Elementlast
2. unsymmetrischer ebener Rahmen
•
Einzelkraft am Knoten
•
konstanter Elementlast
D.
Fiktives Klassenprotokoll der Klasse ElementFEM
Selbständigkeitserklärung
Diese Diplomarbeit mit dem Titel „Konzeption und Realisierung eines zeitgemäßen
Programmsystems zur allgemeinen Tragwerksanalyse“ wurde von mir im Studiengang
Bauingenieurwesen und Umwelttechnik an der Technischen Universität Hamburg-Harburg
im Sommersemester 2001 angefertigt. Sie besteht aus 94 Seiten plus Anhang und einer CD,
die das in C++ geschriebene Beispielprogramm und Beispieldateien enthält.
Die Diplomarbeit wurde von mir ausschließlich unter Zuhilfenahme der im
Literaturverzeichnis aufgeführten Literatur verfasst und ist bisher weder an dieser noch an
anderen Universitäten bewertet worden.
Kathrin Telkamp
Matr.-Nr.: 9952
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement