controller(...) -->
loader(...)
--> read_ctl_file(...)
--> writeout_ctlfile(...)
--> do_node_select(...)
--> ini_global_data_defaults(...)
--> read_flood_file(...)
--> read_boundary_file(...)
--> read_sbound_file(...)
--> read_coord_file(...)
--> read_restart_file(...)
--> set_used_atoms(...)
--> read_ctl_file_new(...)
--> alloc_loader_buffers(...)
--> do_new_clustering(...)
--> read_parameter_data(...)
--> ini_my_forces(...)
--> ini_imob_and_pull(...)
--> set_my_data(...)
--> PCI_send_msg_all_node(...)
Diese Funktion hat für die Initialisierung von EGO entscheidende Bedeutung. Als erstes wird durch read_ctl_file(...) das Kontrolfile eingelesen, also in der Regel das File ctl.lis. Allerdings nur der Teil des Kontrollfiles mit dem festen Format. Danach folgt durch die Funktion writeout_ctlfile(...) die Ausgabe der eingelsenen Parameter auf den Bildschirm. Der jüngere Teil des Kontrollfiles mit dem freien Format wird etwas später durch die Funktion read_ctl_file_new(...) eingelesen.
do_node_select(...) hat nur für die parallele Version von EGO eine Bedeutung. In dieser Funktion wird letztendlich die Anzahl der Knoten bestimmt mit denen EGO rechnen soll. Ausserdem findet dabei zum ersten mal eine Kommunikation zwischen dem Masterknoten und den Slaveknoten statt.
In ini_global_data_defaults(...) werden die meisten Elemente der Struktur global_data mit default Werten belegt und einige Arrays allociert. Die default-Werte können sich aber im Laufe der Initialisierungsphase von EGO noch ändern. Dann werden die lis-files gelesen, in denen alle Daten für den Flooding-Algorithmus und das SBOUND stehen. In alloc_loader_buffers(...) werden viele Buffers allociert, die für das weitere Einlesen der lis-files und das Verteilen der Daten an die Knoten benötigt werden.
In read_coord_file(...) wird das coord.lis file eingelesen, das neben den Atomkoordinaten und Geschwindigkeiten auch andere wichtige Atomparameter, wie z.B. Partialladung und Atomtyp festlegen. Falls in dem Kontrollfile ein vorhandenes Restartfile spezifiziert wurde, wird in read_restart_file(...) das Restartfile eingelesen. Dabei werden die bereits von coord.lis stammenden Atomkoordinaten und Geschwindigkeiten mit denen im Restartfile vorhandenen Werten ersetzt.
Durch den Aufrufen der Funktion set_used_atoms(...) wird der Selectionstring global_data->writeout_atom_selection ausgewertet, der im Kontrollfile gesetzt wurde und festlegt ob alle, oder nur ein Teil der Atomkoordinaten wäherend einer MD-Simulation in EGO-output files geschrieben werden soll.
Nach dem Einlesen des Kontrolfile-Abschnitts in dem freien Format durch die Funktion read_ctl_file_new(...) wrden in der Funktion alloc_loader_buffers(...) alle Arrays der Struktur start_msg allociert. Diese Struktur wird später in do_new_clustering(...) benötigt um die für jeden Knoten individuellen Daten my_data aufzunehmen, die an die einzelnen Knoten verteilt werden.
Danach wird die Funktion do_new_clustering(...) aufgerufen, ... eine sehr wichtige Funktion, die nicht nur am Anfang von loader(...) aufgerufen wird, sondern periodisch auch während MD-Simulationen. Diese Funktion ist absolut essentiell für FAMUSAMM und erledigt im wesentlichen das Clustering, also den geschickten Aufbau der strukturuellen Basiseinheiten, der Cluster und Supercluster. Des weiteren werden ausgehend von dem Clustering in dieser Funktion die Daten (Atomkoordinaten, Clusterstruktur, Bindungslisten, usw.) für die einzelnen Slaves aufbereitet und an diese geschickt.
In der Funktion read_parameter_data(...) werden alle lis-files gelesen, in denen sich die Parameter des molekularen Kraftfeldes befinden. Dies sind die Parameter für die van der Waalskräfte, kovalenten Bindungskräften, Winkelkräften, Dihedralkräften und Improperkräften.
In der Funktion ini_my_forces(...) werden Arrays der Struktur my_force allociert, die, falls im Kontrollfile spezifiziert (z.B. BOND A*) , Kräfte speichern, die wähernd einer Simulation in entsprechende Files geschrieben werden. Wenn EGO restartet und bereits solche Files vorliegen werden sie in dieser Funktion auch auf die richtige Länge gestutzt, so dass durch das Restarten kein Überlapp von den auf Files geschriebenen Integrationsschritten entsteht. In der Funktion ini_imob_and_pull(...) wird die Initialisierung der Immobilisation- und der Pulling-Funktionalität durchgeführt.
Die Funktion set_my_data(...) wird nur in der sequentiellen EGO Version aufgerufen und macht nichts anderes als den Pointer der in do_new_clustering(...) gefüllten Struktur start_msg dem Pointer der Struktur my_data im Modul egcontro.c zuzuweisen. Dadurch wird im wesentlichen das gleiche erriehct wie in der parallelen EGO Version durch die Funktion PCI_send_msg_one_node(...), bei der die einzelnen start_msg Daten an die Slaves geschickt werden, die dort jeweils die my_data Struktur füllen.
Durch den Aufruf von PCI_send_msg_all_node(...) wird der Inhalt der Struktur global_data an die Slaves geschickt. Anders als der Inhalt von my_data ist der Inhlat von global_data auf jedem Knoten der selbe.
loader(...) -->
do_node_select(...)
--> PCI_set_no_nodes(...)
--> PCI_master_setup(...)
In dieser Funktion wird die Anzahl der Slaves no_nodes festgelegt mit der EGO rechnen wird. Dabei werden zum einen die im Kontrolfile angegebenen request_no_nodes mit den wirklich physikalisch vorhandenen Rechenknoten nProcs verglichen. Die Entscheidung mit wie vielen Slaves EGO dann rechnet findet in PCI_set_no_nodes(...) statt und hängt von Parallelrechnertyp und Parallelisierungsbibliothek ab.
Des weiteren wird in dieser Funktion das erste mal zwischen dem Master und den Slaves kommuniziert. Dies geschieht in der Funktion PCI_master_setup(...), wobei der Master den Knoten im wesentlichen mitteilt wieviele andere Knoten von EGO benutzt werden und welche ID-Nummern diese haben. Für die PVM-Version werden in PCI_master_setup(...) vorher jedoch die Slave-Knoten durch die Funktion spawn_pvm_task(...) gestartet .
loader(...) -->
ini_global_data_defaults(...)
Eine harmlose Funktion, in der nur Default-Werte für einige Elemente der Struktur global_data gesetzt werden und einige Arrays allociert werden. Die Default-Werte können sich aber im Laufe der Initialisierung noch verändern. Ausserdem werden einige Initialisierungen für die Strukturelemente von my_force vorgenommen. Die my_force Struktur dient dazu, Werte von Kräften und Energien einer Menge ausgewählter Atome (siehe z.B. PICKDIHE, DIHE) während einer Simulation in die entsprechenden Dateien zu schreiben. Die entsprechende Selektion findet in der Funktion read_ctl_file_new(...) und anschliessend die weitere Initialisierung der my_force Struktur in der Funktion ini_my_forces(...).
loader(...) -->
alloc_loader_buffers(...)
In dieser Funktion wird als erstes die Struktur start_msg allociert. Diese Struktur ist identisch mit der my_data Struktur, die später auf den Knoten verwendet wird (LOAD_MSG_ONE_NODE) und die für jeden Knoten individuelle Daten aufnimmt (z.B. Anzahl der zu behandelnden Atome, Atomdaten, usw.). Die start_msg Struktur auf dem Master-Knoten dient dazu, die für jeden Knoten indiviuellen Daten vorzubereiten (do_new_clustering(...)) und sie dann an die einzelnen Knoten zu senden (PCI_send_msg_one_node(...)) , wo sie dann empfangen und in der my_data Struktur abgelegt werden. In der start_msg Struktur kommen viele int-Listen vor, deren Grösse nicht genau vorherberechnet werden kann. Die berechnet Listenlängen (z.B. mxno_bond_excl, mxno_intern_bonds, usw.) sind daher hier nur Erfahrungswerte. Später, wenn die Listen belegt werden, wird immer überprüft, ob der allocierte Platz ausreicht. Wenn gegebenenfalls der Platz nicht ausreicht wird die entsprechende Liste reallociert.
Als zweites wird in dieser Funktion weitere Buffers der my_force Struktur allociert (siehe hierzu auch ini_global_data_defaults(...) und ini_my_forces(...)).
loader(...) -->
do_new_clustering(...)
--> CLU_buildup_clusters(...)
--> make_atommap(...)
--> readin_bondfile(...)
--> readin_exclfile(...)
--> readin_anglefile(...)
--> readin_dihefile(...)
--> read_shake_file(...)
--> distri_atomdata(...)
--> distri_harmonic(...)
--> distri_excl(...)
--> distri_excl14(...)
--> set_qmexclusionatom(...)
--> distri_shake(...)
--> distri_bonds(...)
--> distri_angles(...)
--> distri_dihe(...)
--> distri_impr(...)
--> distri_tree(...)
--> distri_pickselect(...)
--> PCI_send_msg_one_node(...)
Diese Funktion ist für den Startup von EGO und für jeden Reclustering-Schritt
absolut zentral!
Als erstes wird in dieser Funktion der Clustering-Algorithmus gestartet
(CLU_buildup_clusters(...)), der auf Basis der strukturellen Basisgruppen
Cluster und Supercluster formt, die dann im FAMUSAMM Algorithmus verwendet
werden. Die Cluster auf der obersten Hierarchieebene legen die Atome fest,
die dann den einzelnen Knoten zugeweisen werden, d.h. es werden nur immer
ganze Supercluster den Knoten zugeweisen (Siehe Diplomarbeit Abbildung
5.1, Seite 59). Da die Supercluster kompakte Raumgebiete des Simulationsvolumen
verkörpern, wird dadurch jedem Knoten ein Raumbereich zugeweisen für
die er die darin enthaltenen Atome zu integrieren hat. Da die Liste der
Atome, die einem Knoten zugeteilt werden, unabhängig von der Reihenfolge
im PDB-file ist, werden nach dem Clustering-Algorithmus die Atome so umsortiert,
dass die in einem Cluster enthaltenen Atome konsekutiev sind. Die entsprechenden
Umsortierungslisten werden in make_atommap(...) gebildet (global_data->old2new_map
und global_data->new2old_map).
Dann werden einige der lis-files gelesen und zwar diejenigen, welche
die Molekülstruktur festlegen:
readin_bondfile(...) liest z.B. die Liste der kovalenten Bindungen
zwischen den Atomen ein. Dieser Funktion wird die Umsortierungsliste global_data->old2new_map
übergeben, in der festgelegt ist, welche alte (old) Nummer im PDB-file
auf welche neue (new!) Nummer durch das Clustering gemappt wird. Genau
so läuft das auch mit dem der Exclusion-liste (VDW/ELEC Exclusions),
mit Winkelliste, dem Dihedralliste, der Improperliste und der Shakeliste.
Dann folgt eine For-Schleife über die Anzahl der Rechenknoten, in der die für jeden Knoten individuellen Daten vorbereitet und an diese geschickt werden. Die Variablen first und last geben dabei den Atomnummernbereich nach neuer Sortierung an, welche an den nächsten Knoten geschickt werden. In den jeweiligen distri_???(...) Funktionen (distri=distribute=auf die Knoten verteilen) werden dann aufgrund dieses Bereiches, die jeweiligen Daten für den Knoten extrahiert und in der start_msg Struktur abgelegt. Am Ende des Schleifenkörpers wird dann die Funktion PCI_send_msg_one_node(...) aufgerufen, die dann die Daten in der start_msg Struktur an den Knoten sendet. Auf dem Knoten wird dieses Datenpaket in die my_data Struktur ausgepackt.
loader(...) -->
read_parameter_data(...)