Transcript

Schnelle Multipol-Methode

DIPLOMARBEIT

zur Erlangung des akademischen Grades

Diplom-Mathematiker

FRIEDRICH-SCHILLER-UNIVERSITÄT JENA

Fakultät für Mathematik und Informatik

eingereicht von Thomas Franz

geb. am 02.04.1978 in Saalfeld

Betreuer: Prof. Dr. G. Zumbusch

Jena, 14.07.2008

Zusammenfassung

Diese Arbeit befaßt sich mit der Berechnung von Wechselwirkungen zwi-schen geladenen Partikeln nach dem Coulombschen Gesetz. Werden dieKräfte für jedes Partikel einzeln berechnet, führt dies zu einem Algorith-mus der Ordnung O(N2). Dies ist in der Praxis für große Partikelzahlennicht praktikabel, wenn nicht sogar ummöglich, zu berechnen. Deshalb be-fassen sich viele Wissenschaftler mit Algorithmen, die diese Berechnungenvereinfachen und stark beschleunigen.Im Wesentlichen baut diese Arbeit auf den Artikeln von L. Greengard, V.Rohklin, R. Beatson und J. Carrier auf ([1], [2] und [3]). Sie entwickel-ten die Schnelle Multipol-Methode, einen Algorithmus, der die OrdnungO(NlogN) besitzt. Dadurch ist es möglich, auch für eine sehr große Parti-kelanzahl die Wechelwirkungen zu berechnen.Ziel der Diplomarbeit war die Umsetzung des Multipol-Algorithmus inJAVA, wobei hier besonders großer Wert auf die Parallelisierung mit Hilfevon Threads gelegt wurde.

Inhaltsverzeichnis

1 Grundlagen zur Entwicklung der Multipol-Methode 51.1 Multipolentwicklung . . . . . . . . . . . . . . . . . . . . 61.2 Verschieben der Multipol-Entwicklung . . . . . . . . . . . 81.3 Lokale Entwicklung . . . . . . . . . . . . . . . . . . . . . 91.4 Verschieben der lokalen Entwicklung . . . . . . . . . . . 111.5 Ableitung der Potenzreihen . . . . . . . . . . . . . . . . . 11

2 Der adaptive Multipol-Algorithmus 132.1 Notationen . . . . . . . . . . . . . . . . . . . . . . . . . . 132.2 Grundlegende Beschreibung des Algorithmus . . . . . . . 162.3 Formale Beschreibung des Algorithmus . . . . . . . . . . 182.4 Aufwandsanalyse . . . . . . . . . . . . . . . . . . . . . . 22

3 Wichtige Methoden aus dem Java-Programm 253.1 Aufbau des Baumes . . . . . . . . . . . . . . . . . . . . . 25

3.1.1 Sequentieller Teil . . . . . . . . . . . . . . . . . . 253.1.2 Paralleler Teil . . . . . . . . . . . . . . . . . . . . 27

3.2 Setzen der Listen . . . . . . . . . . . . . . . . . . . . . . 303.2.1 V-Liste . . . . . . . . . . . . . . . . . . . . . . . 333.2.2 U-Liste . . . . . . . . . . . . . . . . . . . . . . . 333.2.3 W-Liste . . . . . . . . . . . . . . . . . . . . . . . 34

3.3 Berechnung der Wechselwirkungen . . . . . . . . . . . . 353.3.1 UpwardPass . . . . . . . . . . . . . . . . . . . . . 353.3.2 Interaktionen zwischen den Boxen . . . . . . . . . 373.3.3 DownwardPass . . . . . . . . . . . . . . . . . . . 413.3.4 Partikelpositionen berechnen . . . . . . . . . . . . 43

4 Test des Programms 454.1 Absoluter Fehler . . . . . . . . . . . . . . . . . . . . . . 454.2 Messung der Laufzeiten . . . . . . . . . . . . . . . . . . . 46

4.2.1 Partikelanzahl . . . . . . . . . . . . . . . . . . . . 464.2.2 Expansionsterme . . . . . . . . . . . . . . . . . . 484.2.3 Parameter s . . . . . . . . . . . . . . . . . . . . . 48

4.3 Mehrprozessor-Systeme . . . . . . . . . . . . . . . . . . 494.3.1 Intel Pentium D805 . . . . . . . . . . . . . . . . . 504.3.2 Opteron . . . . . . . . . . . . . . . . . . . . . . . 504.3.3 Sun Fire T1000 . . . . . . . . . . . . . . . . . . . 53

4.4 Zusammenstoß zweier Körper . . . . . . . . . . . . . . . 54

5 Glossar 57

1 Grundlagen zur Entwicklung der Multipol-Methode

Wir gehen von einem 2-dimensionalen Modell mit einer großen Zahl vonPartikeln aus, welche paarweisen Wechselwirkungen, die durch dasCoulomb-Gesetz beschrieben werden, unterliegen.

Gegeben sei eine Punktladung, die sich im Punkt x0 = (x0, y0) ∈ R2 be-findet. Dann gilt für ein x = (x, y) ∈ R2\{x0}, dass das Potential und daselektrostatische Feld beschrieben werden durch folgende Ausdrücke:

φx0(x) = − log(||x − x0||) , (1.1)

undEx0(x) =

(x − x0)||x − x0||

2 . (1.2)

Es ist bekannt, dass φx0 in Gebieten, die x0 nicht enthalten, harmonischist. Zu jeder harmonischen Funktion u existiert eine analytische Funktionw : C → C, so dass u = <(w). Also erhält man, wenn man Punkte (x, y)mit der komplexen Zahl z = x + iy identifiziert

φx0(x) = <(− log(z − z0)) . (1.3)

Dabei giltφz0(z) = <(− log(z − z0)) = − log |z − z0| . (1.4)

Lemma 1.1. Wenn u(x, y) = <(w(x, y)) das Potential im Punkt (x,y) be-schreibt, so ist das Kraft-Feld gegeben durch

∇u = (ux, uy) = (<(w′),−=(w′)) , (1.5)

wobei (w′) die Ableitung von w ist.

Beweis. Für z = (a, b) mit |z| =√

a2 + b2 gilt:

(log |z|)′ =1|z|

(√a2 + b2

)′=

(a, b)|z|2. (1.6)

6 1 Grundlagen zur Entwicklung der Multipol-Methode

Weiterhin gilt:

(log z)′ =1z=

1a + ıb

=a − ıb

(a + ıb) (a − ıb)=

a − ıba2 + b2 =

(a,−b)|z|2

. (1.7)

Vergleich von (1.6) und (1.7) ergibt die Behauptung. �

1.1 Multipolentwicklung

In diesem Abschnitt werden die theoretischen Grundlagen für den Algo-rithmus entwickelt und Fehlerabschätzungen für die Näherungsformeln be-sprochen.

Die zu Grunde liegende Idee besteht darin, den Ausdruck log(z − zi) ineine Potenzreihe zu entwickeln. Für ein |y| < 1 hat die Taylor-Entwicklungvon log(1 − y) folgende Form

log(1 − y) = y +y2

2+

y3

3+ ... . (1.8)

Daraus ergibt sich dann

log(z − zi) = log(z) + log(1 −

zi

z

)= log(z) +

∞∑j=1

1j

(zi

z

) j, (1.9)

und für das Potential φx0 gilt

φz0(z) = q log(z − z0) = q

log(z) −∞∑

k=1

1k

(z0

z

)k . (1.10)

Lemma 1.2. (Multipol-Entwicklung)Angenommen, dass m Partikel mit Ladungen qi in den Punkten zi, mit |zi| <

r liegen (i = 1, ...,m). Dann gilt für ein z mit |z| > r, dass das durch dieLadungen hervorgerufene Potential φ(z) gegeben ist durch

1 Grundlagen zur Entwicklung der Multipol-Methode 7

φ(z) = a0 log(z) +∞∑

k=1

ak

zk , (1.11)

wobei

a0 =

m∑i=1

qi und ak =

m∑i=1

−qizik

k. (1.12)

Weiterhin gilt für p ≥ 1,

∣∣∣∣∣∣∣φ(z) − a0 log(z) −p∑

k=1

ak

zk

∣∣∣∣∣∣∣ ≤ 1p + 1

α

∣∣∣∣∣rz∣∣∣∣∣p+1≤

( Ac − 1

) (1c

)p

, (1.13)

wobei

c =∣∣∣∣∣zr

∣∣∣∣∣ , A =m∑

i=1

|qi| und α =A

1 −∣∣∣ rz

∣∣∣ . (1.14)

Beweis. Die Multipol-Entwicklung wird durch das Summieren über p Ter-me für m Punkte zi gebildet. Der Fehler ist beschränkt durch

∣∣∣∣∣∣∣φ(z) − a0 log(z) −p∑

k=1

ak

zk

∣∣∣∣∣∣∣ ≤∣∣∣∣∣∣∣∣∞∑

k=p+1

ak

zk

∣∣∣∣∣∣∣∣ . (1.15)

Einsetzen von (1.12) für ak ergibt

∣∣∣∣∣∣∣∣∞∑

k=p+1

ak

zk

∣∣∣∣∣∣∣∣ ≤ A∞∑

k=p+1

∣∣∣∣∣rz∣∣∣∣∣k = α

p + 1

∣∣∣∣∣rz∣∣∣∣∣p+1=

(A

p + 1

) (1

c − 1

) (1c

)p

, (1.16)

womit (1.13) gezeigt ist. �

8 1 Grundlagen zur Entwicklung der Multipol-Methode

Anmerkung: Für c ≥ 2 gilt∣∣∣∣∣∣∣φ(z) − a0 log(z) −p∑

k=1

ak

zk

∣∣∣∣∣∣∣ ≤ A(12

)p

. (1.17)

1.2 Verschieben der Multipol-Entwicklung

Das folgende Lemma zeigt, wie eine Multipol-Entwicklung verschobenwerden kann.

Lemma 1.3. (Verschieben der Multipol-Entwicklung)

φ(z) = a0 log(z − z0) +∞∑

k=1

ak

(z − z0)k (1.18)

sei die Multipol-Entwicklung des Potentials, dass duch m Ladungen q1, ...,

qm , welche alle in einem Kreis D mit Radius R und Zentrum z0 liegen,erzeugt wird. Dann gilt für ein z, dass außerhalb des Kreises D1 mit Radius(R + |z0|) und dem Ursprung als Zentrum liegt

φ(z) = a0 log(z) +∞∑

l=1

bl

zl , (1.19)

wobei

bl = −a0 z0

l

l+

l∑k=1

ak z0l−k

(l − 1k − 1

), (1.20)

mit(

lk

)Binominalkoeffizient. Weiterhin gilt für ein p ≥ 1,

∣∣∣∣∣∣∣φ(z) − a0 log(z) −p∑

l=1

bl

zl

∣∣∣∣∣∣∣ ≤ A

1 −∣∣∣ |z0|+R

z

∣∣∣ ∣∣∣∣∣ |z0| + R

z

∣∣∣∣∣p+1

(1.21)

mit A definiert in (1.14).

1 Grundlagen zur Entwicklung der Multipol-Methode 9

Beweis. Die Formel für die Verschiebung der Multipol-Entwicklung ergibtsich aus folgenden Gleichungen

log(z − z0) = log(z(1 −

z0

z

))= log(z) −

∞∑l=1

1l

(z0

z

)l, (1.22)

und

(z − z0)−k =

∞∑l=k

(l − 1k − 1

)z0

l−k

zl , (1.23)

beide gültig für |z| > |z0|, durch Substituieren, Summieren und Abschnei-den. Die Fehlerschranke folgt aus der Eindeutigkeit der Multipol-Entwick-lung, die besagt, dass die indirekte Entwicklung um den Ursprung iden-tisch zur direkten Entwicklung sein muß. �

1.3 Lokale Entwicklung

Das folgende Lemma beschreibt, wie die Multipol-Entwicklung in eine lo-kale Entwicklung umgewandelt wird.

Lemma 1.4. (Lokale Entwicklung)Im Kreis D1 mit Radius R und Zentrum z0, wobei |z0| > (c + 1)R mit c > 1,seien m Partikel mit den Ladungen q1, ..., qm verteilt. Dann konvergiert dieMultipol-Entwicklung (1.18) innerhalb eines Kreises D2 mit Radius R unddem Ursprung als Zentrum. Im Inneren von D2 gilt dann für das Potential:

φ(z) =∞∑

l=0

bl zl, (1.24)

wobei

b0 = a0 log(−z0) +∞∑

k=1

ak

z0k (−1)k (1.25)

und für l = 1

10 1 Grundlagen zur Entwicklung der Multipol-Methode

bl = −a0

l z0l +

1z0

l

∞∑k=1

ak

z0k

(l + k − 1

k − 1

)(−1)k

. (1.26)

Der Fehler bei der Umwandlung ist beschränkt durch

∣∣∣∣∣∣∣φ(z) −p∑

l=0

bl zl

∣∣∣∣∣∣∣ < A(4e(p + c)(c + 1) + c2)c(c − 1)

(1c

)p+1

, (1.27)

mit A definiert in (1.14) und e Eulersche Zahl.

Beweis. Die Gleichung für die lokale Entwicklung ergibt sich aus folgen-den Ausdrücken

log(z − z0) = log(−z0

(1 −

zz0

))= log(−z0) −

∞∑l=1

1l

(zz0

)l

(1.28)

und

(z − z0)−k =

(1−z0

)k 11 − z

z0

k

=

(1−z0

)k ∞∑l=0

(l + k − 1

k − 1

) (zz0

)l

, (1.29)

beide gültig für |z| ≤ R. Der Beweis zur Fehlerschranke kann im Artikelvon Greengard und Rokhlin [2] nachgelesen werden. �

Anmerkung:

Wird in Lemma 1.4 das Feld φ(z) durch eine einzige Ladung q gelegen imPunkt z0 erzeugt, so haben die Terme bl folgende Form:

b0 = q log(−z0) (1.30)

und für l = 1bl = −

ql z0

l . (1.31)

1 Grundlagen zur Entwicklung der Multipol-Methode 11

1.4 Verschieben der lokalen Entwicklung

Lemma 1.5. Für komplexe Zahlen z, z0 und ak (k = 1, 2, ..., n) gilt

n∑k=0

ak(z − z0)k =

n∑l=0

n∑k=l

ak

(kl

)(−z0)k−l

zl =

n∑l=0

bl zl . (1.32)

Diese Formel ist exakt, so dass keine weiteren Fehler durch das Verschie-ben auftreten.

1.5 Ableitung der Potenzreihen

Um das Kraft-Feld eines Partkels zu berechnen, wird die Ableitung derPotenzreihe benötigt. Beachte, dass diese nach (1.5) gebildet werden muß.

F (z) =

< a0

z − z0+

∞∑k=1

k ak

(z − z0)k+1

,−= a0

z − z0+

∞∑k=1

k ak

(z − z0)k+1

.(1.33)

2 Der adaptive Multipol-Algorithmus

2.1 Notationen

In diesem Abschnitt werden alle wichtigen Definitionen und Begriffe for-muliert, die für die Durchführung des Algorithmus notwendig sind.

Als Simulationsbox bezeichnen wir das Gebiet (Quadrat), in dem die Par-tikel liegen und in der die Berechnungen durchgeführt werden. Diese Boxhat das Level 0 und ist die Wurzel des Baumes, den wir als Datenstrukturzur Speicherung benutzen.

.

.

.

.

.

..

..

.

. .

.

..

.

.

.

.

.

.

..

.

.

.

.

.

Nichtgleichmäßige Verteilung von Partikeln in der Simulationsbox

Von der Simulationsbox werden durch Halbieren der Seitenlängen 4 Kin-derboxen (Level 1) erzeugt und die Partikel auf diese verteilt.Im Baum werden jedoch nur diejenigen Boxen gespeichert, in denen sichnoch Partikel befinden.Von diesen Kinderboxen werden dann wiederum solange Kinderboxen(Level L+1) erzeugt, bis sich in einer Box nur noch maximal s Partikel be-finden.Der Parameter Level gibt also an, wie oft die Simulationsbox in diesemBereich unterteilt wurde.

Für eine Menge A von Boxen bezeichnet T(A) die Menge aller Partikel,die in A liegen.

14 2 Der adaptive Multipol-Algorithmus

Bl ist die Menge aller nichtleeren Boxen auf dem Level L. B0 enthält nurdie Simulationsbox selbst.

Enthält eine Box mehr als s Partikel bezeichnen wir sie als Elternbox,anderenfalls als kinderlos.

Eine Kinderbox entsteht durch die Teilung einer Elternbox.

.

.

.

.

.

..

..

.

. .

.

..

.

.

.

.

.

.

..

.

.

.

.

.

Beispiel für eine Unterteilung der Simulationsbox mit s = 4

Kollegen sind benachbarte (d.h. zwei Boxen haben mindestens einen ge-meinsamen Punkt) Boxen der gleichen Größe (auf dem selben Level). EineBox hat höchstens acht Kollegen.

b

c

c

c

c c c

Box (b) und ihre Kollegen (c)

Eine Box a nennen wir wohlseperiert zu b, wenn a und b nicht benachbartsind.

2 Der adaptive Multipol-Algorithmus 15

Jeder Box b auf dem Level l ordnen wir fünf Listen zu. Diese beinhaltenandere Boxen, welche in gewissen Beziehungen zur Box b stehen.

Ub Diese Liste ist leer, wenn b eine Elternbox ist. Anderenfalls enthältUb die Box b selbst und alle benachbarten kinderlosen Boxen vonb.⇒ Java-Methode

Vb Diese Liste wird gebildet von den Kindern der Kollegen von b’sEltern, die wohlseperiert zu b sind.⇒ Java-Methode

Wb Diese Liste ist leer, wenn b eine Elternbox ist. Ist b kinderlos, sowird Wb von allen Nachfahren von b’s Kollegen, deren Eltern be-nachbart sind mit b, die aber selbst nicht zu b’s Nachbarn gehören,gebildet.⇒ Java-Methode

Xb Diese Liste wird gebildet von allen Boxen c, so dass b ∈ Wc gilt.X ist die zu W duale Liste, also: c ∈ Wb ⇔ b ∈ Xc.Das bedeutet, dass Xb nicht erzeugt werden muß und Interaktionenin dieser Liste gleichzeitig mit denen in Wb durchgeführt werdenkönnen. Siehe hierzu auch die Erläuterungen zur MethodeWandXListInteraction. Alle Boxen in dieser Liste sind kinderlosund größer als b.

Yb Diese Liste beinhaltet alle Boxen, die wohlseperiert zu b’s Elternsind.

Y

YU

X

X

V V

VV

V V

U b

U U U V

V V V V

W W W W

W U U U

V V

X

Y Y

Box (b) und die zugehörigen Listen

16 2 Der adaptive Multipol-Algorithmus

Φb bezeichnet die Multipol-Entwicklung bis zum Term p um das Zentrumvon b des Feldes, dass durch alle Partikel in T(b).

Ψb bezeichnet die lokale Entwicklung bis zum Term p um das Zentrum vonb des Feldes, welches durch alle Partikel, die außerhalb von T(Ub)∪T(Wb)liegen, gebildet wird. Ψ b(r) ist das Ergebnis der Berechnung von Ψ b füreinen Partikel r in T(b).

Γb bezeichnet die lokale Entwicklung des Feldes um das Zentrum von b,welches von allen Partikeln in T(Vb) erzeugt wird.

∆b bezeichnet die lokale Entwicklung um das Zentrum von b, welche dasFeld, dass durch alle Ladungen in T(Xb) erzeugt wird, repräsentiert.

αb(r) bezeichnet das Feld für einen Partikel r ∈ T (b), welches durch al-le Partikel in T(Ub) erzeugt wird.

βb(r) bezeichnet das Feld für einen Partikel r ∈ T (b), welches durch al-le Partikel in T(Wb) erzeugt wird.

2.2 Grundlegende Beschreibung des Algorithmus

Der Algroithmus kann als ein rekursiver Prozess angesehen werden, beidem durch Unterteilen der Simulationsbox bzw. deren Nachfolger, ein im-mer feiner werdendes Gitter erzeugt wird. Zu einer Box b auf dem Levell werden die Listen Ub, Vb, Wb, Xb und Yb erzeugt und die folgende Pro-zedur wird angewandt auf die Mengen der Partikel T(Ub), T(Vb), T(Wb),T(Xb) und T(Yb).

1. Für jede kinderlose Box b berechnen wir die Multipol-EntwicklungΦb nach (1.18), wobei wir für z0 das Zentrum der Box b wählen. Fürjede Elternbox B benutzen wir Lemma 1.3, um die Multipol-Entwick-lungen der Kinder in die Entwicklung ΦB zu verschieben.

2 Der adaptive Multipol-Algorithmus 17

2. Die Wechselbeziehungen zwischen den Partikeln in T(b) und T(Ub)werden direkt berechnet. Für jeden Partikel r ∈ T (b) berechnen wiralso αb(r). Im Programm wird die Box b seperat behandelt, um zu ver-hindern, dass durch Partikel, die sehr nahe beeinander liegen, Fehlerauftreten. (Anmerkung 1)

3. Wir benutzen Lemma 1.4, um für jede Box in Vb die Multipol-Ent-wicklung in eine lokale Entwicklung um das Zentrum von b zu über-führen. Die resultierenden Entwicklungen werden aufaddiert, um Γb

zu erhalten.

4. Für jeden Partikel r in b berechnen wir das Feld βb(r) durch Auswer-ten der Multipol-Entwicklung Φw in r bis zum Term p für jede Boxw ∈ Wb und addieren diese auf. Dies bedeutet, dass wir in (1.18) für zdie Position des Partikel r einzusetzen haben (z0 ist das Zentrum derBox w).

5. Das Feld jedes Partikels in T(Xb) wird in eine lokale Entwicklung umdas Zentrum von b konvertiert. Die erhaltenen Entwicklungen werdenaufaddiert, um ∆b zu erhalten.

6. Wir verschieben mit Hilfe des Lemmas 1.5 das Zentrum der lokalenEntwicklung ΓB von b’s Eltern B hin zu den Zentren von b und de-ren Geschwister. Wir addieren die lokalen Entwicklungen um Γb zuerhalten.

7. Für jede Box b berechnen wir die Summe der lokalen EntwicklungenΓb und ∆b für jeden Partikel r in b und addieren das Ergebnis mit αb(r)und βb(r), um das Feld für r zu erhalten.

Anmerkung 1:In jeder kinderlosen Box werden die Kräfte zwischen den Partikeln direktberechnet. Um die resultierende Kraft zwischen den zwei Teilchen (pi, pj)zu berechnen, muß durch das Abstandsquadrat ri j dividiert werden. Da einRechner nur über eine gegrenzte Rechengenauigkeit verfügt, benötigt manim Programm eine Anpassung für sehr nahe beeinander gelegene Partikel.Diese wird in der Methode computeSelfInteraction vorgenommen. ZweiPartikel, deren Abstand sowohl in x-, als auch in y-Richtung kleiner alsder in der Methode vorgebene Parameter softParam ist, werden um genaudiesen Betrag voneinander entfernt.

18 2 Der adaptive Multipol-Algorithmus

Anmerkung 2:In der beschriebenen Prozedur wurde nicht explizit die Wechselwirkungzwischen den Partikeln in T(b) und denen in T(Yb) berechnet. Da alle Bo-xen in Yb wohlseperiert zu b’s Eltern sind, wurden die Wechselwirkungenzwischen T(Yb) und T(b) bereits durch die Schritte (3) und (5) auf einemniedrigeren Level berechnet.

2.3 Formale Beschreibung des Algorithmus

Wähle eine Genauigkeit (ist im Programm vorgegeben und nur im Codeänderbar, Grundeinstellung ist 1e-15).

Vom Benutzer sind folgende Daten einzugeben:

• Länge eines Zeitschrittes (z.B. 0.1 für eine Zehntel Sekunde)

• Anzahl der Zeitschritte

• Anzahl der zu startenden Threads (ist nur ein Richtwert, die tatsäch-liche Anzahl hängt von der Struktur des Problems ab)

• Faktor für die Vergrößerung der Simulationsbox (abhängig von denzu bearbeitenden Daten empfiehlt sich eine starke Vergrößerung)

• Anzahl der Partikel (s), die in eine Box einsortiert werden (Voreinstel-lung: 40). Für die direkte Berechnung ohne Multipol-Methode gebenSie bitte einen Wert an, der größer ist, als die Partikelanzahl

• Anzahl der zu verwendenden Expansionsterme (p)

2 Der adaptive Multipol-Algorithmus 19

Schritt 1

Baumaufbau (buildTree)

do l = 1, 2, ...do bi ∈ Bl

if bi enthält mehr als s Partikel thenUnterteile bi in vier Boxen, ignoriere leere Boxen, nichtleere Bo-xen werden zu Bl+1 hinzugefügt.

end ifend do

end do

(nlev bezeichnet den höchsten Level der Verfeinerung und nbox die gesam-te Anzahl der in Schritt 1 erzeugten Boxen)

Schritt 2

Multipol-Entwicklung (UpwardPass)

Schritt 2.1do i = 1, ... , nbox

if ist eine kinderlose Box thenBenutze Lemma 1.1 um eine Multipol-Entwicklung Φb mit p Ter-men zu bilden, die das Feld, dass durch die Ladungen in bi erzeugtwird, außerhalb von bi repräsentiert.

end ifend do

Schritt 2.2do l = nlev-1, ... , 1

do bi ∈ Bl

if bi ist eine Elternbox thenBenutze Lemma 1.20 um die Entwicklung um das Zentrum je-der Kinderbox von bi in das Zentrum von bi zu verschieben. Dieresultierenden Entwicklungen werden addiert und man erhältΦb.

end ifend do

end do

20 2 Der adaptive Multipol-Algorithmus

Schritt 3

Wechselwirkungen mit Boxen in den U-Listen (UListInteraction)

do i = 1, ... , nboxif bi ist eine Kinderbox then

Für jeden Partikel r in bi berechne die Summe αb(r) aller Wech-selwirkungen zwischen r und allen Partikeln in T(Ubi).

end ifend do

Schritt 4

Wechselwirkungen mit Boxen in den V-Listen (VListInteraction)

do i = 1, ... , nboxdo bj ∈ Vbi

Wandle die Multipol-Entwicklung Φbj um bj’s Zentrum in eine lo-kale Entwicklung um bi’s Zentrum mit Hilfe des Lemmas 1.4 um.Addiere die Ergebnisse, um Γbi zu erhalten.

end doend do

Schritt 5

Wechselwirkungen mit Boxen in den W-Listen (WListInteraction)

do i = 1, ... , nboxif bi ist eine Kinderbox then

Berechne die Multipol-Entwicklung Φbj für jede Box bj ∈ Wbi umβbi(r) für jeden Partikel r in der Box bi zu erhalten.

end doend do

2 Der adaptive Multipol-Algorithmus 21

Schritt 6

Wechselwirkungen mit Boxen in den X-Listen (XListInteraction)

do i = 1, ... , nboxBenutze Lemma 1.24 und die darauf folgende Anmerkung, um dasFeld für jeden Partikel in T(Xb) in eine lokale Entwicklung ∆bi um dasZentrum von bi umzuwandeln.

end do

Schritt 7

Lokale Entwicklung (DownwardPass)

Schritt 7.1do l = 1 , ... , nlev-1

do bi ∈ Bl

if bi ist eine Elternbox thenBenutze Lemma 1.5 um das Zentrum der Entwicklung Γb in dieZentren von bi’s Kindern bj zu verschieben. Addiere die erhal-tenen Entwicklungen, um Γb zu erhalten.

end ifend do

end do

Schritt 7.2do i = 1, ... , nbox

if bi ist eine Kinderbox thenBerechne Ψ bi = Γbi + ∆bi.Für jeden Partikel r in bi berechne Ψ bi(r).Addiere Ψ bi(r), αbi(r) und βbi(r) um das Feld für r’s Position zu er-halten.

end ifend do

22 2 Der adaptive Multipol-Algorithmus

2.4 Aufwandsanalyse

Im Folgenden wird der Aufwand für die Durchführung jedes Schrittesbetrachtet. Eine ausführlichere Analyse und die zugrundeliegenden Sätzesind im Artikel von Greengard [1] zu finden.

Schritt Aufwand Erläuterung

1 N p Jeder Partikel wird auf jedem Level einer Box zu-geordnet (Aufbau des Baumes). Es gibt höchstensp Stufen der Verfeinerung (Annahme: wird die Si-mulationsbox noch stärker verfeinert, so ist auch dieAnzahl an Expansionstermen zu erhöhen).

2.1 N p Für jeden Partikel wird eine Multipol-Entwicklungmit p Termen berechnet.

2.2 52 p3N/s Das Zentrum der Entwicklung jeder Box wird in das

Zentrum der Elternbox verschoben. Die Anzahl derBoxen ist beschränkt durch 5pN/s und jede Ver-schiebung benötigt p2/2 Operationen.

3 44pNs Jede kinderlose Box b enthält höchstens s Partikelund der Aufwand für die Berechnung aller Wech-selwirkungen zwischen Partikeln in b und Ub istbeschränkt durch s2 (tatsächlich ist dieser Wert et-was kleiner, da im Programm für die Berechnungder Wechselwirkungen zwischen den Partikeln ineiner Box das 3. Newtonsches Gesetz angewendetwird). Die Anzahl der Boxen in allen Listen U istbeschränkt durch 44pN/s.

4 80p3N/s Die Liste V hat höchstens 32 Einträge. Es gibt ma-ximal 5pN/s Boxen und jede Verschiebung bedeuteteinen Aufwand von p2/2.

2 Der adaptive Multipol-Algorithmus 23

Schritt Aufwand Erläuterung

5 32p2N Jede kinderlose Box b enthält höchstens s Partikel.Die Berechnung der Wechselwirkungen zwischenPartikeln in b und einer Box in Wb erfordert einenAufwand ps. Es gibt maximal 32pN/s Boxen in denW-Listen.

6 32p2N Jede Box in Xb enthält höchstens s Partikel. Die Be-rechnung der Wechselwirkungen zwischen Partikelnin einer Box Xb und der Box b erfordert einen Auf-wand ps. Es gibt maximal 32pN/s Boxen in den X-Listen.

7.1 10p3N/s Jede Box hat maximal 4 Kinder. Es kann nicht mehrals 5pN/s Boxen geben und der Aufwand für eineVerschiebung ist p2/2.

7.2 N p + N Für jeden Partikel wird eine Entwicklung mit p Ter-men berechnet. Das Summieren erfordert einen Auf-wand von N Operationen.

An dieser Analyse läßt sich gut erkennen, dass der Aufwand der Multipol-Methode bei zunehmender Partikelanzahl deutlich geringer ist, als wenndie Wechselwirkungen direkt berechnet werden (die Partikelanzahl N gehtin keinem Schritt quadratisch ein).

Wie sich das Programm auf die Änderung einzelner Variablen verhält, istim Kapitel 4.2 nachzulesen.

3 Wichtige Methoden aus dem Java-Programm

Nachdem in den vorherigen Kapiteln die Theorie und der Algorithmus ent-wickelt wurden, werden in diesem Kapitel die wichtigsten Methoden kurzerläutert.

3.1 Aufbau des Baumes

Das Programm liest die Partikeldaten aus einer Textdatei ein und erzeugtdie Simulationsbox. Anschließend wird die Methode buildTree aufgeru-fen, die den Baum aufbaut. Dazu werden ausgehend von der Simulations-box zunächst die Kinderboxen gebildet und die Partikel auf diese aufge-teilt (leere Boxen werden gelöscht). Von diesen werden dann wieder dieKinderboxen gebildet, bis genügend Boxen auf einem Level des Baumeserzeugt wurden. Mit diesen Boxen wird dann der parallele Baumaufbaugestartet und jeder Thread erzeugt dann einen Teilbaum.Aufgeführt sind die Klasse buildThread und alle Methoden, die für denAufbau des Baumes notwendig sind.

/*** Erzeugt den Baum.* @param root Simulationsbox* @param threads Anzahl der zu startenden Threads* @param length* @return boxes Boxen auf einem Level, Einstiegspunkt fuer* Parallelisierung*/public LinkedList <box> buildTree(box root, int threads, int length){

LinkedList <box> boxes = buildBoxes(root, threads, length);parallelBuild(boxes);

return boxes;}

3.1.1 Sequentieller Teil

/*** Erzeugt sequentiell den Baum, bis auf einem Level genuegend Boxen* vorhanden sind; diese werden dann weitergegeben , um den Baum ab da* parallel zu bauen.* @param level bis zu dem die Boxen erzeugt werden* @return LinkedList mit den erzeugten Boxen zum Starten der Threads*/

26 3 Wichtige Methoden aus dem Java-Programm

private LinkedList <box> buildBoxes(box Box, int threads, int length){

LinkedList <box> Boxes = new LinkedList <box>();LinkedList <box> newBoxes = new LinkedList <box>();

Boxes.add(Box);

int i = 0;int level_max = 0;double ver = 1.0;double minBox = (length / (double) (box.MAX_PARTICLES_PER_BOX));

while (ver < minBox) {ver *= 4.0;level_max++;

}

while ((i < level_max) && (Boxes.size() < threads)) {for (box b : Boxes) {

for (int j = 0; j < 4; j++) {b.createChild(j);

}b.setBoxes(); // Partikel aufteilenfor (int j = 0; j < 4; j++) {

if (b.children[j].ParticlesInBox.size() > 0)newBoxes.add(b.children[j]);

elseb.children[j] = null;

}}Boxes.clear();for (box b :newBoxes) {

Boxes.add(b);}i++;if ((Boxes.size() == 1)

&& (Boxes.getFirst().ParticlesInBox.size()> box.MAX_PARTICLES_PER_BOX))

{i = 0;level_max = 0;ver = 1.0;minBox = (Boxes.getFirst().ParticlesInBox.size() /

(double)box.MAX_PARTICLES_PER_BOX);while (ver < minBox) {

ver *= 4.0;level_max++;

}}newBoxes.clear();

}this.highestLevel = Boxes.getFirst().level;

return Boxes;}

3 Wichtige Methoden aus dem Java-Programm 27

/*** Teilt die Partikel der Box auf ihre Kinderboxen auf. Wird von* buildBoxes aufgerufen => sequentielle Erzeugung des Baumes.* Kinderboxen muessen vorher erzeugt werden.*/public void setBoxes(){

box child = new box();int i;complex center = this.getCenterOfBox();if (this.ParticlesInBox.size() <= MAX_PARTICLES_PER_BOX)

this.childless = true;if (this.ParticlesInBox.size() > MAX_PARTICLES_PER_BOX){

for (particle p : this.ParticlesInBox) {if (p.pos.x > center.x) {d

if (p.pos.y > center.y)child = this.children[0];

elsechild = this.children[1];

}else {

if (p.pos.y < center.y)child = this.children[2];

elsechild = this.children[3];

}child.ParticlesInBox.add(p);

}this.ParticlesInBox.clear(); /* Partikel aus der Elternbox

entfernen */}

}

3.1.2 Paralleler Teil

/*** Threads erzeugen, starten und auf Ende warten.* @param boxes Boxen auf einem Level zum Erzeugen der Threads*/private void parallelBuild(LinkedList <box> boxes){

buildThread[] runner = new buildThread[boxes.size()];int counter = 0;

for (box b : boxes){

runner[counter] = new buildThread(b);runner[counter].start();counter++;

}try{

for (int j = 0; j < boxes.size(); j++)runner[j].join();

28 3 Wichtige Methoden aus dem Java-Programm

}catch(InterruptedException e) {}

}

buildThread enthält den Code, der durch die erzeugten Threads abgearbei-tet wird.

public class buildThread extends Thread{

box Box;

public buildThread(box Box){

this.Box = Box;}

/*** Baut unterhalb der uebergebenen Box den Baum auf. Dazu wird die* Methode subdivide Box benutzt. Es werden nur Boxen gespeichert ,* in denen sich auch Partikel befinden.* @param Box Box aus der Liste boxes*/public void InsertParticlesInTree(box Box){

LinkedList <box> boxes = new LinkedList <box>();LinkedList <box> help = new LinkedList <box>();

boxes.add(Box);

while (boxes.isEmpty() == false) {for (box b : boxes) {

if (b.ParticlesInBox.size() >box.MAX_PARTICLES_PER_BOX) {b.subdivideBox();for (int i = 0; i < 4; i++) {

if (b.children[i] != null) {help.add(b.children[i]);

}}

}}boxes.clear();for (box h : help) {

boxes.add(h);}help.clear();

}}

@Overridepublic void run(){

InsertParticlesInTree(Box);}

}

3 Wichtige Methoden aus dem Java-Programm 29

/*** Teilt die Partikel der Elternbox auf ihre Kinderboxen auf,* existieren die Kinderboxen noch nicht, so werden sie erzeugt.* @return Aenderungen an der Baumstruktur*/public int subdivideBox(){

box child = new box();int change = 0;

complex center = this.getCenterOfBox();

for (particle p : this.ParticlesInBox) {if (p.pos.x > center.x) {

if (p.pos.y > center.y) {child = this.children[0];if (this.children[0] == null) {

child = this.createChild(0);change++;

}}else {

child = this.children[1];if (child == null) {

child = this.createChild(1);change++;

}}

}else {

if (p.pos.y < center.y) {child = this.children[2];if (child == null) {

child = this.createChild(2);change++;

}}else {

child = this.children[3];if (child == null) {

child = this.createChild(3);change++;

}}

}child.ParticlesInBox.add(p);

}this.ParticlesInBox.clear(); // Partikel in der Elternbox loeschenthis.childless = false; // this wird zur Elternbox

return change;}

Im Programm wurden sämtliche Schritte des Algorithmus parallelisiert. Dajedoch das Grundprinzip - sequentiell den Baum durchlaufen, bis genügendBoxen vorhanden sind - immer das Gleiche ist, wird im Folgenden nichtmehr darauf eingegangen.

30 3 Wichtige Methoden aus dem Java-Programm

3.2 Setzen der Listen

In diesem Abschnitt werden die Methoden aus dem Programm erläutert,die zum Setzen der Listen benutzt werden.

Zuerst folgen einige Methoden, die dafür benötigt werden, um festzustel-len, in welcher Beziehung zwei Boxen zueinander stehen.

/*** Ueberprueft , ob die Box, die uebergeben wird, ein Vorfahre der* aufrufenden Box ist.* @param ancestorBox potentielle Vorfahr-Box* @return true, wenn die ancestorBox ein Vorfahre ist,*/public boolean ancestorBox(box ancestorBox){

double x_center_distance , y_center_distance;boolean anc = true;double b_length = this.upper.x - this.lower.x;double anc_length = ancestorBox.upper.x - ancestorBox.lower.x;

if (b_length != anc_length){

x_center_distance = Math.abs(this.getCenterOfBox().x -ancestorBox.getCenterOfBox().x);

y_center_distance = Math.abs(this.getCenterOfBox().y -ancestorBox.getCenterOfBox().y);

if ((x_center_distance > (anc_length / 2.0)) ||(y_center_distance > (anc_length / 2.0)))anc = false;

}else

anc = false;

return anc;}

/*** Ueberprueft , ob zwei Boxen benachbart sind, also mind. eine* gemeinsame Ecke haben.* Sind sie benachbart , wird true zurueckgegeben.* @param Box2 potentielle Nachbarbox* @return true, wenn benachbart*/public boolean adjacentBoxes(box Box2){

double exact_seperation , x_seperation , y_seperation;boolean adj = false;box Box1 = this;

exact_seperation = (((Box1.upper.x - Box1.lower.x) / 2.0) +((Box2.upper.x - Box2.lower.x) / 2.0));

3 Wichtige Methoden aus dem Java-Programm 31

x_seperation = (double) Math.abs( Box1.getCenterOfBox().x -Box2.getCenterOfBox().x);

y_seperation = (double) Math.abs( Box1.getCenterOfBox().y -Box2.getCenterOfBox().y);

if ( (x_seperation == exact_seperation) &&(y_seperation <= exact_seperation))adj = true;

elseif ( (y_seperation == exact_seperation) &&

(x_seperation <= exact_seperation))adj = true;

elseadj = false;

return adj;}

/*** Well-seperated bedeutet, dass die zwei Boxen durch die Laenge* der Boxen getrennt sein muss. Dabei gibt die groessere Box den* Abstand vor. Das heisst, dass die Zentren der Boxen wenigstens* in einer Richtung um das doppelte der Laenge der groesseren* Box auseinander liegen muessen.* @param Box2 potentielle wellSeperatedBox* @return true, wenn seperiert voneinander*/public boolean wellSeperatedBoxes(box Box2){

double min_ws_distance;double x_seperation , y_seperation;boolean well;box Box1 = this;double length1 = Box1.upper.x - Box1.lower.x;double length2 = Box2.upper.x - Box2.lower.x;

if(length1 > length2)min_ws_distance = length1 *2.0;

elsemin_ws_distance = length2 *2.0;

x_seperation = Math.abs(Box1.getCenterOfBox().x -Box2.getCenterOfBox().x);

y_seperation = Math.abs(Box1.getCenterOfBox().y -Box2.getCenterOfBox().y);

if ((x_seperation >= min_ws_distance) ||(y_seperation >= min_ws_distance))well = true;

elsewell = false;

return well;}

32 3 Wichtige Methoden aus dem Java-Programm

Die folgenden zwei Methoden bestimmen die Geschwister und die Kolle-gen einer Box.

/*** Erzeugt die Geschwister -Liste der aufrufenden Box.*/public void setSiblings(){

box pb, sb;

pb = this.parent;if (pb != null) {

for (int i = 0; i < 4; i++) {sb = pb.children[i];if ((sb != null) && (sb != this))

this.siblings.add(sb);}

}}

/*** Setzt die Kollegen der Box.* Dazu gehoeren die Geschwister und angrenzende Boxen der selben* Groesse. Also Cousin’s (Kinder der Geschwister der Elternbox* von this), die an this angrenzen.*/public void setColleagues(){

box pb, cb, cousin;

pb = this.parent;if(pb != null) {

for (box s : this.siblings)this.colleagues.add(s);

for (box pbc : pb.colleagues) {cb = pbc;for (int j = 0; j < 4; j++) {

cousin = cb.children[j];if (cousin != null) {

if (this.adjacentBoxes(cousin) == true)this.colleagues.add(cousin);

}}

}}

}

Die Listen für eine Box werden durch den Aufruf der MethodeconstructInteractionList initialisiert.

/*** Setzt die Listen V, U und W.

3 Wichtige Methoden aus dem Java-Programm 33

* @param root Simulationsbox*/public void constructInteractionList(box root){

this.setVList();if (this.childless == true) {

this.setUList(root);this.setWList();

}}

3.2.1 V-Liste

/*** VList wird gebildet von allen Kindern der Kollegen von* this’ Eltern, die wellSeperated zu this sind.*/private void setVList(){

box pb, cb, cousin;

pb = this.parent;if (pb != null) {

for (box pbc : pb.colleagues) {cb = pbc;for (int j = 0; j < 4; j++) {

cousin = cb.children[j];if (cousin != null) {

if(this.wellSeperatedBoxes(cousin) == true)this.Vlist.add(cousin);

}}

}}

}

3.2.2 U-Liste

/*** UList wird gebildet von allen kinderlosen Boxen,* die mit der aufrufenden Box benachbart sind.* @param root*/private void setUList(box root){

setUListHelper(this, root);}

/*** Rekursive Methode, um sich bis zu einer kinderlosen Box,* die an this angrenzt, herunter zu hangeln

34 3 Wichtige Methoden aus dem Java-Programm

* @param Box* @param pb*/private void setUListHelper(box Box, box root){

box child;

for (int i = 0; i < 4; i++){

child = root.children[i];if (child != null){

if (Box.adjacentBoxes(child) == true){

if (child.childless == true)Box.Ulist.add(child);

elsesetUListHelper(Box, child);

}else{

if (Box.ancestorBox(child) == true)setUListHelper(Box, child);

}}

}}

3.2.3 W-Liste

/*** W-Liste setzen. Dazu Aufruf von insertNonAdjacentChildren ,* welche ueberprueft , ob die Boxen nicht benachbart sind.*/private void setWList(){

for (box coSearch : this.colleagues) {if (coSearch.childless == false)

this.insertNonAdjChildren(coSearch);}

}/*** Ueberprueft , ob die Kinder von pb an die aufrufende Box angrenzen.* Ist dies nicht der Fall, so wird diese Box in die W-Liste* eingetragen.* @param pb Elternbox*/

private void insertNonAdjChildren(box pb){

box child;

for (int i = 0; i < 4; i++) {child = pb.children[i];if (child != null) {

if (child.childless == false)

3 Wichtige Methoden aus dem Java-Programm 35

this.insertNonAdjChildren(child);}else

this.Wlist.add(child);}

}}

3.3 Berechnung der Wechselwirkungen im Baum

3.3.1 UpwardPass

Der Baum wird im Post-Order-Verfahren traversiert, um sicherzustellen,dass eine Kinderbox vor ihrer Elternbox aufgesucht wird. Ist die Box bkinderlos, so wird die Methode computeMPExp aufgerufen. Dann wird dieMultipol-Entwicklung von der Box b zur Elternbox b.parent verschoben(shiftMPExp).

/*** Multipol-Terme entwickeln und zu den Eltern verschieben.* @param b Box*/public void upward(box b){

if (b.childless == true)computeMPExp(b);

if (b.parent != null)shiftMPExp(b, b.parent);

}

/*** Terme der Multipol-Entwicklung berechnen.* @param b Box fuer die die Terme berechnet werden*/private void computeMPExp(box b){

complex box_pos, z0, z0_pow_n, temp;complex[] result_exp = new complex[box.MAX_EXPANSION_TERMS];

box_pos = new complex(b.getCenterOfBox().x, b.getCenterOfBox().y);

for (int i = 0; i < box.MAX_EXPANSION_TERMS; i++)result_exp[i] = new complex();

for (particle p : b.ParticlesInBox) {z0 = p.pos.sub(box_pos);z0_pow_n = z0;result_exp[0] = result_exp[0].add(p.charge);

36 3 Wichtige Methoden aus dem Java-Programm

for (int j = 1; j < box.MAX_EXPANSION_TERMS; j++) {temp = z0_pow_n.mul(-p.charge).mul(inv[j]);result_exp[j] = result_exp[j].add(temp);z0_pow_n = z0_pow_n.mul(z0);

}}

for (int i = 0; i < box.MAX_EXPANSION_TERMS; i++)b.mp_expansion[i] = result_exp[i];

}

/*** Multipol-Entwicklung von der Kinderbox zur Elternbox verschieben.* @param cb Kinderbox* @param pb Elternbox*/private void shiftMPExp(box cb, box pb){

complex z0, z0_inv, z0_pow_n, z0_pow_minus_n;complex[] temp_exp = new complex[box.MAX_EXPANSION_TERMS];complex[] result_exp = new complex[box.MAX_EXPANSION_TERMS];complex child_pos , parent_pos , temp;

child_pos = cb.getCenterOfBox();parent_pos = pb.getCenterOfBox();

z0 = child_pos.sub(parent_pos);

z0_inv = new complex(1.0).div(z0);z0_pow_n = new complex(1.0);z0_pow_minus_n = new complex(1.0);result_exp[0] = cb.mp_expansion[0];

for (int i = 1; i < box.MAX_EXPANSION_TERMS; i++) {result_exp[i] = new complex();z0_pow_minus_n = z0_pow_minus_n.mul(z0_inv);temp_exp[i] = z0_pow_minus_n.mul(cb.mp_expansion[i]);for (int j = 1; j <= i; j++) {

temp = new complex(C[i - 1][j - 1]);temp = temp.mul(temp_exp[j]);result_exp[i] = result_exp[i].add(temp);

}temp = new complex(inv[i]);temp = temp.mul(cb.mp_expansion[0]);temp = result_exp[i].sub(temp);z0_pow_n = z0_pow_n.mul(z0);result_exp[i] = temp.mul(z0_pow_n);

}

for (int i = 0; i < box.MAX_EXPANSION_TERMS; i++)pb.mp_expansion[i] = pb.mp_expansion[i].add(result_exp[i]);

}

3 Wichtige Methoden aus dem Java-Programm 37

3.3.2 Interaktionen zwischen den Boxen

computeInteractions ruft die für die Berechnung der Wechselwirkungennotwendigen Methoden auf. Wie bereits erwähnt, werden die Wechselwir-kungen der Partikel in einer Box seperat berechnet (computeSelfInteracti-on).

/*** Wechelwirkungen zwischen b und den Boxen, die* sich in deren Listen befinden, berechnen.* @param b Box*/public void computeInteractions(box b){

if (b.childless == true) {computeSelfInteraction(b);UListInteraction(b);WandXListInteraction(b);

}else

VListInteraction(b);}

/*** Wechselwirkungen zwischen den Partikeln in einer Box berechnen.* Ist der Abstand zwischen zwei Partikeln zu gering, wird der Abstand* auf den Wert von softParam gesetzt. Nach dem 3. Newtonschen Gesetz* muss nur das Feld zwischen Partikel p1 und p2 berechnet werden.* @param b Box*/private void computeSelfInteraction(box b){

double denom, softParam = 1e-15;complex[] result = new complex[b.ParticlesInBox.size()];complex temp, sep;int i = 0;

particle[] b_particles = new particle[b.ParticlesInBox.size()];

for (particle p : b.ParticlesInBox) {b_particles[i] = p;result[i] = new complex();i++;

}

for (int k = 0; k < b_particles.length; k++) {for (int l = k+1; l < b_particles.length; l++) {

sep = b_particles[k].pos.sub(b_particles[l].pos);

if ((Math.abs(sep.x) < softParam) &&(Math.abs(sep.y) < softParam)) {if (sep.x >= 0.0)

sep.x = softParam;

38 3 Wichtige Methoden aus dem Java-Programm

elsesep.y = -softParam;

if (sep.y >= 0.0)sep.y = softParam;

elsesep.y = -softParam;

}denom = 1 / ((sep.x * sep.x) + (sep.y * sep.y));

temp = sep.mul(denom).mul(b_particles[l].charge);result[k] = result[k].add(temp);

temp = sep.mul(denom).mul(b_particles[k].charge);result[l] = result[l].sub(temp);

}b_particles[k].field = b_particles[k].field.add(result[k]);

}

i = 0;for (particle p : b.ParticlesInBox) {

p = b_particles[i];i++;

}}

/*** Ruft UList fuer b auf.* @param b Box*/private void UListInteraction(box b){

if (b.Ulist.isEmpty() == false) {for (box UListBox : b.Ulist)

UList(UListBox, b);}

}

/*** Berechnung der Wechselwirkungen zwischen b und den Boxen in b’s* U-Liste. Fuer jeden Partikel in b wird das Feld berechnet , dass* durch die Partikel in einer Box aus der U-Liste induziert wird.* @param sourceBox Box aus der U-Liste* @param destBox Box b*/private void UList(box sourceBox , box destBox){

complex result, tempVector , tempResult;double denom;complex sep;

for (particle dp : destBox.ParticlesInBox) {result = new complex();for (particle sp : sourceBox.ParticlesInBox) {

sep = sp.pos.sub(dp.pos);denom = 1 / ((sep.x * sep.x) + (sep.y * sep.y));tempVector = sep.mul(denom);

3 Wichtige Methoden aus dem Java-Programm 39

tempResult = tempVector.mul(sp.charge);result = result.sub(tempResult);

}dp.field = dp.field.add(result);

}}

/*** Aufruf von WList und XList* Benutzt wird dafuer nur die W-Liste der Box b, nur das bei* XList die Rollen von WListBox und b vertauscht sind.* @param b Box*/private void WandXListInteraction(box b){

for (box WListBox : b.Wlist)WList(WListBox, b);XList(b, WListBox);

}

/*** Aus der Multipol-Entwicklung um das Zentrum einer Box aus der* W-Liste wird das Feld fuer jeden Partikel r in b berechnet ,* dass durch die Partikel in der W-Liste induziert wird.* @param sourceBox Box aus der W-Liste* @param destBox Box b*/private void WList(box sourceBox , box destBox){

complex z0, z0_inv, result, term, source_pos;

source_pos = sourceBox.getCenterOfBox();for (particle dp : destBox.ParticlesInBox) {

result = new complex();z0 = dp.pos.sub(source_pos);z0_inv = new complex(1.0).div(z0);for (int j = box.MAX_EXPANSION_TERMS - 1; j > 0; j--) {

term = sourceBox.mp_expansion[j].mul(j);result = result.add(term);result = result.mul(z0_inv);

}result = result.add(sourceBox.mp_expansion[0]);result = result.mul(z0_inv);result.y = -result.y; //wegen komplexer Ableitungdp.field = dp.field.add(result);

}}

/*** Fuer jeden Partikel aus b wird das Feld, das auf das Zentrum einer* Box aus der W-Liste wirkt, in eine lokale Entwicklung umgewandelt.* destBox muss synchronisiert werden, da sonst mehrere Threads* gleichzeitig auf ein und die selbe Box schreibend zugreifen* koennten und somit das Ergebnis verfaelscht wird.* @param sourceBox Box b

40 3 Wichtige Methoden aus dem Java-Programm

* @param destBox Box aus der W-Liste*/private void XList(box sourceBox , box destBox){

synchronized(destBox){

complex z0, z0_inv, z0_pow_minus_n;complex result_exp[] = new complex[box.MAX_EXPANSION_TERMS];complex source_pos , dest_pos, temp;

dest_pos = destBox.getCenterOfBox();

for (int i = 0; i < box.MAX_EXPANSION_TERMS; i++)result_exp[i] = new complex();

for (particle sp : sourceBox.ParticlesInBox) {z0 = sp.pos.sub(dest_pos);z0_inv = new complex(1.0).div(z0);z0_pow_minus_n = z0_inv;result_exp[0] = new complex(Math.log(z0.abs()),

-z0.phi()).mul(sp.charge);for (int j = 1; j < box.MAX_EXPANSION_TERMS; j++) {

temp = z0_pow_minus_n.mul(sp.charge).div(j);result_exp[j] = result_exp[j].add(temp);z0_pow_minus_n = z0_pow_minus_n.mul(z0_inv);

}}for (int i = 0; i < box.MAX_EXPANSION_TERMS; i++)

destBox.x_expansion[i] =destBox.x_expansion[i].sub(result_exp[i]);

}}

/*** Ruft VList fuer die Box b auf.* @param b Box*/private void VListInteraction(box b){

if (b.Vlist.isEmpty() == false) {for (box VListBox : b.Vlist)

VList(VListBox, b);}

}

/*** Aus den Termen der Multipol-Entwicklungen einer Box aus* b’s V-Liste wird eine lokale Entwicklung um das Zentrum* von b gebildet.* @param sourceBox Box aus W-Liste* @param destBox Box b*/private void VList(box sourceBox , box destBox){

complex z0, z0_inv, result_exp , source_pos , dest_pos, temp;complex[] temp_exp = new complex[box.MAX_EXPANSION_TERMS];

3 Wichtige Methoden aus dem Java-Programm 41

complex[] z0_pow_minus_n = new complex[box.MAX_EXPANSION_TERMS];

source_pos = sourceBox.getCenterOfBox();dest_pos = destBox.getCenterOfBox();z0 = source_pos.sub(dest_pos);z0_inv = new complex(1.0).div(z0);z0_pow_minus_n[0] = new complex(1.0);temp_exp[0] = sourceBox.mp_expansion[0];

for (int i = 1; i < box.MAX_EXPANSION_TERMS; i++) {z0_pow_minus_n[i] = z0_pow_minus_n[i-1].mul(z0_inv);temp_exp[i] = z0_pow_minus_n[i].mul(sourceBox.mp_expansion[i]);

}

temp = new complex(Math.log(z0.abs()), -z0.phi());result_exp = temp_exp[0].mul(temp);for (int i = 1; i < box.MAX_EXPANSION_TERMS; i++) {

temp = temp_exp[i].mul(z0_pow_minus_n[i]);temp = temp.mul(Math.pow(-1, i));result_exp = result_exp.add(temp);

}destBox.local_expansion[0] =

destBox.local_expansion[0].add(result_exp);

for (int i = 1; i< box.MAX_EXPANSION_TERMS; i++) {result_exp = new complex();for (int j = 1; j < box.MAX_EXPANSION_TERMS; j++) {

temp = new complex(C[i+j-1][j-1]);temp = temp.mul(temp_exp[j]);temp = temp.mul(Math.pow(-1, j));result_exp = result_exp.add(temp);

}result_exp = result_exp.mul(z0_pow_minus_n[i]);temp = new complex(inv[i]);temp = temp.mul(temp_exp[0]);temp = temp.mul(z0_pow_minus_n[i]);result_exp = result_exp.sub(temp);

destBox.local_expansion[i] =destBox.local_expansion[i].add(result_exp);

}}

3.3.3 DownwardPass

Der Baum muß nun im Pre-Order-Verfahren traversiert werden, da es fürdas Verschieben der Lokalen Entwicklung notwendig ist, zuerst die Eltern-boxen zu besuchen. Wenn es sich bei b nicht um die root-Box handelt, wirddie Lokale Entwicklung von b’s Elternbox hin zu b verschoben. Anschlie-ßend wird für eine kinderlose Box b das Kraftfeld berechnet.

42 3 Wichtige Methoden aus dem Java-Programm

/*** Der Baum wird von der Wurzel her durchlaufen. Dabei wird die* lokale Entwicklung von Elternboxen hin zu den Kinderboxen* verschoben. Ist b kinderlos , so wird die lokale Entwicklung* berechnet.* @param b*/public void downward(box b){

if (b.parent != null)shiftLocalExp(b.parent, b);

if (b.childless == true)evaluateLocalExp(b);

}

/*** Verschiebt die lokale Entwicklung vom Zentrum der Box pb in* das Zentrum der Box cb.* @param pb ELternbox* @param cb Kinderbox*/private void shiftLocalExp(box pb, box cb){

complex z0, z0_inv, z0_pow_n, z0_pow_minus_n , temp;complex[] a = new complex[box.MAX_EXPANSION_TERMS];complex[] result_exp = new complex[box.MAX_EXPANSION_TERMS];

z0 = cb.getCenterOfBox().sub(pb.getCenterOfBox());z0_pow_n = new complex(1.0);z0_pow_minus_n = new complex(1.0);z0_inv = new complex(1.0).div(z0);

for (int i = 0; i < box.MAX_EXPANSION_TERMS; i++) {a[i] = z0_pow_n.mul(pb.local_expansion[i]);z0_pow_n = z0_pow_n.mul(z0);

}

for (int i = 0; i < box.MAX_EXPANSION_TERMS; i++) {result_exp[i] = new complex();for (int j = i; j < box.MAX_EXPANSION_TERMS; j++) {

temp = new complex(C[j][i]);temp = temp.mul(a[j]);result_exp[i] = result_exp[i].add(temp);

}result_exp[i] = result_exp[i].mul(z0_pow_minus_n);z0_pow_minus_n = z0_pow_minus_n.mul(z0_inv);

}

for (int i = 0; i < box.MAX_EXPANSION_TERMS; i++) {cb.local_expansion[i] =

cb.local_expansion[i].add(result_exp[i]);}

}

/*** Berechnet aus der lokalen Entwicklung um das Zentrum der Box b

3 Wichtige Methoden aus dem Java-Programm 43

* fuer jeden Partikel in b das induzierte Feld.* @param b Box*/private void evaluateLocalExp(box b){

complex z0, source_pos , result, temp;

for (int i = 0; i < box.MAX_EXPANSION_TERMS; i++)b.local_expansion[i] =

b.local_expansion[i].add(b.x_expansion[i]);

source_pos = b.getCenterOfBox();

for (particle p : b.ParticlesInBox) {result = new complex();z0 = p.pos.sub(source_pos);for (int j = box.MAX_EXPANSION_TERMS - 1; j > 0; j--) {

temp = new complex(j);result = result.mul(z0);temp = temp.mul(b.local_expansion[j]);result = result.add(temp);

}result.y = -result.y; //wegen komplexer Ableitungp.field = p.field.add(result);

}}

3.3.4 Partikelpositionen berechnen

Nachdem die Kraft-Felder für alle Partikel berechnet wurden, können nundie daraus resultierenden Auswirkungen auf die Partikel berechnet werden.Dazu dient die Methode computeParticlePositions, die für die Partikel inder Box b die neuen Werte für Position, Geschwindigkeit und Beschleuni-gung berechnet.

/*** Berechnet die Partikelpsoition nach dem Stoermer-Verlet* Verfahren. Anschliessend wird ueberprueft , ob der Partikel* seine Box bzw. sogar die Simulationsbox verlassen hat.* Er wird durch setFlags entsprechend markiert.* @param b* @param root*/public void computeParticlePosition(box b, box root){

complex force, new_acc;complex velTerm, accTerm, accMix;double t_pow_2 = Main.timeStep_Dur * Main.timeStep_Dur;

for (particle p: b.ParticlesInBox) {

44 3 Wichtige Methoden aus dem Java-Programm

force = p.field.mul(p.charge);new_acc = force.div(p.mass);

velTerm = p.vel.mul(Main.timeStep_Dur);accTerm = p.acc.mul(0.5 * t_pow_2);accMix = (p.acc.add(new_acc)).mul(Main.timeStep_Dur * 0.5);

p.pos = p.pos.add(velTerm).add(accTerm);p.vel = p.vel.add(accMix);p.acc = new_acc;

p.field = new complex(); //Feld loeschen

setFlags(p, b, root);}

}

/*** Ueberprueft , ob der Partikel seine Box oder eventuell sogar die* Simulationsbox verlassen hat* @param p zu untersuchender Partikel* @param Box in der sich der Partikel befindet* @param root Simulationsbox*/private void setFlags(particle p, box Box, box root){

if ((p.pos.x < Box.lower.x) || (p.pos.y < Box.lower.y) ||(p.pos.x > Box.upper.x) || (p.pos.y > Box.upper.y)) {

p.toRemove = true;

if ((p.pos.x < root.lower.x) || (p.pos.y < root.lower.y) ||(p.pos.x > root.upper.x) || (p.pos.y > root.upper.y)) {p.fitInRoot = false;

}else

p.fitInRoot = true;}else

p.toRemove = false;}

4 Test des Programms

In diesem Abschnitt werden einige Test besprochen, die mit dem Pro-gramm durchgeführt wurden.

4.1 Absoluter Fehler bei der Berechnung der Kraft in Abhän-gigkeit von den verwendeten Expansionstermen

Um die Genauigkeit der Multipol-Methode in Abhängigkeit der verwen-deten Expansionsterme zu überprüfen, wurde der die Partikelanordnungso gewählt, dass alle Formeln, die nicht exakt sind, benutzt werden. ProBox wurde ein Partikel erlaubt. Der Fehler wird für einen Partikel betrach-tet, dessen Box (im Folgenden b) eine andere Box in der VList hat. Die-se Box ist unterteilt in 4 Kinderboxen. Die Partikel in den Boxen wur-den nahe dem Rand platziert, umso einen großen Fehler bei der Multipol-Entwicklung zu provozieren. Diese Entwicklung wird anschließend zurElternbox verschoben, wobei dieser Schritt wieder fehlerbehaftet ist. DieMultipol-Entwicklung der Elternbox wird dann in eine lokale Entwicklungum das Zentrum der Box b konvertiert und die auf das Partikel wirkendeKraft berechnet. Für die Berechnungen wurde jeweils ein Zeitschritt ver-wendet.

1e−16

1e−14

1e−12

1e−10

1e−08

1e−06

0.0001

0.01

1

0 5 10 15 20 25 30 35 40 45 50

Abs

olut

er F

ehle

r

Expansionsterme

Fehler bei der Berechnung der Kraft durch die Multipol−Methode in Abhängigkeit der verwendeten Expansionsterme

||Fdir − Fmul||

Der absolute Fehler sinkt wie erwartet bei Erhöhung der Expansionsterme.

46 4 Test des Programms

Ab 40 Termen tritt eine Sättigung auf, die durch numerische Rundungs-fehler und anderen Faktoren hervorgerufen wird. Dies bedeutet für denpraktischen Einsatz der Multipol-Methode, dass man die Genauigkeit nichtbeliebig steigern kann. Die Verwendung von weniger als 10 Expansionster-men ist nicht zu empfehlen. Allgemein sollte bei vielen Zeitschritten undbei einer sehr großen Anzahl an Partikeln auch eine hohe Anzahl an Ter-men benutzt werden, um das Anwachsen des Fehlers einzudämmen (sie-he hierzu auch die Diskussion zu Zeitaufwand versus Anzahl verwendeterTerme).

4.2 Laufzeiten in Abhängigkeit von der Partikelanzahl und derWahl der Parameter

4.2.1 Laufzeiten in Abhängigkeit von der Partikelanzahl

Zuerst wird die Laufzeit für die direkte Methode betrachtet. In der Graphikist gut zu erkennen, dass dieser Algorithmus die Ordnung O(N2) besitzt.Die quadratische Funktion wurde mit gnuplot durch ein Regressionsver-fahren bestimmt.

0

100

200

300

400

500

600

0 10000 20000 30000 40000 50000

Zei

t in

Sek

unde

n

Partikelanzahl

Benötigte Zeit in Abhängigkeit der Partikelanzahl

Direkte Berechnung2.3e−7*x**2

Für die Messungen wurden nur wenige Partikel benutzt, da mit der Ver-dopplung der Partikelanzahl eine Vervierfachung der Rechenzeit einher-geht. Die Berechnung der Wechselwirkungen zwischen 1 Million Partikelhätte auf diesem Rechner ungefähr 64 Stunden benötigt.

4 Test des Programms 47

Bei der Erfassung der Laufzeiten der Multipol-Methode wurde die Anzahlder Partikel zwischen 100.000 und 1.5 Millionen variiert.

0

500

1000

1500

2000

2500

3000

3500

4000

0 1e+06 2e+06 3e+06 4e+06 5e+06 6e+06 7e+06 8e+06 9e+06 1e+07

Zei

t in

Sek

unde

n

Anzahl Partikel

Laufzeiten der Multipolmethode

Laufzeit2.3e-5*N*log(N)

Die Laufzeiten folgen zwar einem Trend, jedoch ist eine deutliche Trep-penbildung zu erkennen. Dieser Effekt tritt dadurch ein, dass eine Erhö-hung der Partikelanzahl nicht zwangsläufig zur Erhöhung des maximalenLevel im Baum führt. In einem Fall befinden sich in vier Geschwisterbo-xen im untersten Level nur wenig mehr als s Partikel. Andererseits ist esmöglich, dass fast alle Kinderboxen voll besetzt sind. Dadurch erhöht sichder Aufwand der direkten Berechnungen beträchtlich.Das folgende Schaubild verdeutlicht jedoch die Überlegenheit der Multipol-Methode gegenüber der direkten Berechnung der Wechselwirkungen.

0

100

200

300

400

500

600

0 5000 10000 15000 20000 25000 30000 35000 40000 45000 50000

Zei

t in

Sek

unde

n

Partikelanzahl

Vergleich Laufzeit Direkte Berechnung versus Multipol-Methode

Direkte BerechnungMultipol-Methode

48 4 Test des Programms

Es wurden 40 Expansionsterme verwendet, wobei der absolute Fehler beieinem Zeitschritt 1.3e-10 betrug.

4.2.2 Laufzeit in Abhängigkeit der verwendeten Expansionsterme

Die Anzahl der verwendeten Expansionsterme hat nicht nur einen großenEinfluß auf die Genauigkeit der Multipol-Methode, sondern auch auf dieLänge der Laufzeit einer Simulation. Bei der Wahl der Anzahl der verwen-deten Expansionsterme sollte man sich jedoch immer den Geschwindig-keitsvorteil der Multipol-Methode vor Augen führen und für eine Simula-tion 40 Entwicklungsterme benutzen.

0

100

200

300

400

500

600

0 500000 1e+06 1.5e+06 2e+06 2.5e+06 3e+06 3.5e+06 4e+06 4.5e+06

Lauf

zeit

in S

ekun

den

Verwendete Entwicklungsterme

Expansionsterme

10 Terme20 Terme30 Terme40 Terme

4.2.3 Laufzeit in Abhängigkeit des Parameters s

Der Parameter s gibt an, wieviele Partikeln in eine Box einsortiert werdendürfen. Bei dem für das Schaubild verwendete Problem wurden die Parti-kel gehäuft um den Mittelpunkt der Simulationsbox angeordnet. MehrereTests ergaben jedoch, dass die Ergebnisse repräsentativ für die meisten Par-tikelanordnungen sind.

Empfehlenswert sind demnach Werte zwischen 30 und 40 erlaubten Parti-keln pro Box.

4 Test des Programms 49

0

50

100

150

200

250

300

350

0 20 40 60 80 100 120

Zei

t in

Sek

unde

n

Partikel pro Box

Erlaubte Anzahl Partikel pro Box

Parameter s

4.3 Laufzeiten des Programmes auf verschiedenen Mehrpro-zessorsystemen

Das Programm wurde ausführlich auf mehreren Rechnern mit unterschied-licher Hardware auf die Effekte der Parallelisierung getestet. Theoretischmüßte der Algorithmus von einer höheren Anzahl an Kernen stark profi-tieren. Es gibt nur eine synchronisierte Methode, die die Parallelität ein-schränkt. In den ersten Ebenen des Baumes ist nur wenig Arbeit zu ver-richten, so dass die Erhöhung der Anzahl an Threads (der Baum muß dannsequentiell noch weitere Ebenen durchlaufen werden) nur zu einer unwe-sentlich höheren Laufzeit führt.Bei einer gleichmäßigen Verteilung der Partikel in der Simulationsbox emp-fiehlt es sich, ungefähr so viele Threads zu starten, wie vom Rechner par-allel bearbeitet werden können. Sind die Partikel ungleichmäßig verteilt,kann eine höhere Anzahl an Threads eine Beschleunigung der Laufzeitbewirken, allerdings ist hier zu beachten, dass die Erzeugung und die Ver-waltung der Threads durch das Betriebssystem ebenfalls Resourcen in An-spruch nimmt. Eine allgemein gültige Aussage kann nicht getroffen wer-den, da die Rechnerarchitektur und das verwendete Betriebssystem einenzu großen Einfluß haben.Für alle Messungen wurde das JDK 1.6 benutzt.

50 4 Test des Programms

4.3.1 Intel Pentium D805

Dem System stehen nur 2 GB Arbeitsspeicher zur Verfügung, so dassnur Tests mit kleinen Partikelzahlen möglich waren. Auf diesem Rechnerist sowohl Linux als auch Windows XP installiert. Im Schnitt ergab sichauf beiden Betriebssystemen ein Speedup von 1.7 bei Verwendung von 4Threads.

4.3.2 AMD-System mit 4 Dualcore-Opteron 865 Prozessoren

Dieser Rechner verfügt über eine Speicherausstattung von 16 GB und wirdmit der Linux-Distribution CentOS 5.2 (Kernel 2.6.18) betrieben.

Um die Effizienz der Architektur zu bestimmen, wurde vorab mit einemProgramm getestet, das sich zu 100 Prozent parallelisieren läßt. Dabei han-delt es sich um numersiche Quadratur, bei der den Threads jeweils ein Teil-intervall zum Berechnen übergeben wird. Hierbei ist gesichert, dass dieThreads völlig unabhängig voneinander agieren können, ohne auf Datenvon anderen Threads zugreifen zu müssen.Das C-Programm stammt aus dem Buch von Bauke und Mertens [5] undverwendet pthreads. Entsprechend wurde das Programm in Java mitThreads umgesetzt (als netbeans-Projekt auf der CD).Der Algorithmus berechnet das Integral von f (x) =

√1 − x2 im Intervall

[0, 1]. Dabei wird die Anzahl der Stützstellen und die Anzahl an zu ver-wendenden Threads vorgegeben.

Für die Tests wurde die Anzahl an Stüzstellen auf 2e+9 festgestzt und dieLaufzeiten für 1 bis 8 Threads, entsprechend den zur Verfügung stehendenProzessoren, gemessen.

4 Test des Programms 51

0

10

20

30

40

50

60

70

80

1 2 3 4 5 6 7 8

Zei

t in

Sek

unde

n

Anzahl der verwendeten Threads

Vergleich der Laufzeiten zwischen C und Java

C-ProgrammJava-Programm

Um die Effizienz der jeweils verwendeten Technologien vergleichen zukönnen, wurde in der folgenden Graphik der Speedup beider Programmeaufgetragen.

0

1

2

3

4

5

6

7

8

1 2 3 4 5 6 7 8

spee

dup

Anzahl der verwendeten Threads

Vergleich des speedup zwischen C und Java

speedup des C-Programmsspeedup des Java-Programms

Das C-Programm skaliert besser bei Erhöhung der Anzahl an Threads, da-für ist das Java-Programm immer mindestens um den Faktor 2 schneller.Beim Kompilieren mit gcc wurden allerdings auch keine weiteren Optimie-rungen vorgenommen, so dass dieses Ergebnis sicher nicht repräsentativist, um allgemeine Aussagen über Geschwindigkeitsvorteile der einzelnenSprachen zu treffen.

52 4 Test des Programms

Ausgehend von den diesen Erkenntnissen und der Tatsache, dass im Pro-gramm eine Methode für den gleichzeitigen Zugriff von mehr als einemThread gesperrt werden muß, kann man auf dieser Maschine sicherlichkeinen Geschwindigkeitsgewinn vom Faktor 6 erwarten. Bei Erhöhung derAnzahl an Threads steigt außerdem die Wahrscheinlichkeit, dass mehrereThreads gleichzeitig schreibend auf ein und die selbe Box zugreifen wol-len. Die JVM (virtuelle Maschine) stellt diese dann in eine Warteschleifeund arbeitet sie nacheinander ab. Dadurch erhöht sich natürlich die Lauf-zeit.Probleme entstehen vielleicht auch durch den gleichzeitigen Lesezugriffauf die Boxen bei Bearbeitung der Listen. Eventuell könnte man dies da-durch verhindern, in dem man private Kopien der betreffenden Objekteanlegt. Dies würde aber wiederum zu einem höheren Speicherbedarf füh-ren.Im Mittel ergab sich eine Beschleunigung um den Faktor 4.1 bei Ver-wendung von 16 Threads. Aufgrund dessen, dass die Partikel gleichmäßigauf die Simulationsbox verteilt wurden, war die Benutzung von genau 8Threads nicht möglich. Es wurde jeweils ein Zeitschritt berechnet, p und swurden auf 40 gesetzt. Aufgetragen wurden die Zeiten für die Berechnun-gen der Wechselwirkungen, da diese den aufwändigsten Teil des Algorith-mus darstellen.

0

500

1000

1500

2000

2500

3000

3500

4000

0 1e+06 2e+06 3e+06 4e+06 5e+06 6e+06 7e+06 8e+06 9e+06 1e+07

Zei

t in

Sek

unde

n

Partikelanzahl

Laufzeiten des Programms bei Benutzung von 1, 4 bzw. 16 Threads

1 Thread4 Threads

16 Threads

4 Test des Programms 53

4.3.3 Sun Fire T1000

Diese Maschine wird mit dem Betriebssytem Solaris betrieben und ist inder Lage, 24 Threads simultan zu verarbeiten. Da der Rechner jedoch nurüber 2 GB Hauptspeicher verfügt, waren auch hier nur Tests mit kleinenPartikelzahlen möglich. Die Parameter p und s wurden wieder auf 40 ge-setzt und es wurde jeweils ein Zeitschritt berechnet.

0

500

1000

1500

2000

2500

3000

3500

4000

4500

100000 200000 300000 400000 500000 600000 700000 800000

Zei

t in

Sek

unde

n

Anzahl Partikel

Laufzeiten des Programms bei Verwendung von 1, 4, 16 bzw. 64 Threads

1 Thread4 Threads

16 Threads64 Threads

Es ist deutlich zu erkennen, dass sich die Laufzeiten bei Verwendung von64 gegenüber 16 Threads kaum verringern, obwohl der Maschine noch 8freie Threads zur Verfügung stehen. Hier treten wieder die bereits beimOpteron genannten Effekt ein.

Um einen Eindruck von der Leistungsfähigkeit der Maschine und des Pro-grammes zu bekommen, wurde in der folgenden Graphik die von einemProzessor verrrichtete Arbeit in Abhängigkeit der Anzahl der verwendetenThreads aufgetragen.Im Idealfall müßten alle Linien zusammenfallen. Aufgrund der bereits ge-troffenen Aussagen ist es jedoch klar, dass die Performance je Prozessormit Erhöhung der Anzahl an Threads abnehmen muß. Um einen noch hö-heren Parallelisierungsgrad zu Erreichen, müßte man die Anzahl an Pro-zessoren deutlich erhöhen.

54 4 Test des Programms

60

80

100

120

140

160

180

200

100000 200000 300000 400000 500000 600000 700000 800000

n/(p

*t)

Partikelanzahl

Sun Fire T1000

1 Thread4 Threads

16 Threads24 Threads

4.4 Zusammenstoß zweier Körper

Mit dem Programm wurde der Zusammenstoß zweier Körper simuliert.Die Körper sind so aufgebaut, dass ein Partikel jeweils von vier Partikelnmit entgegengesetzter Ladung (|q| = 1) umgeben ist (ähnlich dem Aufbauvon Salzkristallen). Der grüne Körper bewegt (v.y = −10) sich auf den ro-ten Körper zu. Beide Körper werden durch den Aufprall zerstört.Es wurden 13.000 Zeitschritte der Weite 5e-9 berechnet, wobei der ver-wendete Rechner (AMD 3000+) dafür 40 Stunden benötigte (die direkteBerechnung hätte mindestens 120 Stunden in Anspruch genommen). DieSimulationsbox wurde um den Faktor 2 vergrößert und die Parameter s undp auf 40 festgesetzt.

Begin der Simulation Simulation nach 5e-6 Sekunden

4 Test des Programms 55

Simulation nach 1e-5 Sekunden Simulation nach 1.5e-5 Sekunden

Simulation nach 2e-5 Sekunden Simulation nach 2.5e-5 Sekunden

Simulation nach 3e-5 Sekunden Simulation nach 3.5e-5 Sekunden

56 4 Test des Programms

Simulation nach 4e-5 Sekunden Simulation nach 4.5e-5 Sekunden

Simulation nach 5e-5 Sekunden Simulation nach 5.5e-5 Sekunden

Simulation nach 6e-5 Sekunden Simulation nach 6.5e-5 Sekunden

5 Glossar

Post-Order-Traversieren Zuerst werden Boxen auf dem untersten Leveldes Baumes besucht. Das bedeutet, dass Kinderboxen vor ihren Elternbesucht werden.

Pre-Order-Traversieren Der Baum wird von der Wurzel her durchlau-fen. Also Elternboxen vor ihren Kinderboxen.

Speedup Dieser Wert gibt an, um welchen Faktor ein paralleles Programmgegenüber dem sequentiellen Abarbeiten beschleunigt wird.

Literaturverzeichnis

[1] J. Carrier, L. Greengard and V. Rokhlin: A fast adaptive multipolealgorithmn for particle simulations.Technical Report 496, Yale Computer Science Department (1986).

[2] L. Greengard and V. Rokhlin: A Fast Algorithm for Particle Simulati-ons.J. Comput. Phys. 73, 325-348 (1987).

[3] R. Beatson and L. Greengard: A short course on fast multipole me-thods.→ Artikel

[4] Rainer Oechsle: Parallele Programmierung in Java.Hanser Fachbuch; 2.Auflage (2007).

[5] Heiko Bauke und Stephan Mertens: Cluster Computing.Springer, Berlin; 1. Auflage (2005).