[Prev] [Next] [Home DissOnline]


B.2. Globale Regelinformationen

In den globalen Regelinformationen werden folgende Dinge festgelegt:

C++-Code:

          switch (op) {
          case INIT_RULES:
             // Name, Datum, Variablen, Phasen, Reaktoren, Kinetik
          case PREP_ROOT:
             // Vorbehandlungsfunktion für die Ausgangsmaterialien
          case PREP_EDUCT:
             // Vorbehandlungsfunktion für die Edukte
          case DISTRIBFUNC:
             // Nachbehandlungs(Verteilungs)funktion für alle Produkte
          case MODFUNC:
             // Modellfunktionen
          case FINISH:
             // Cleanup
          default:
             return BAD;
          }  
          return OK;

Tcl-Code:

          switch $op {
          INIT_RULES {
             # Name, Datum, Variablen, Phasen, Reaktoren, Kinetik
             }
          PREP_ROOT {
             # Vorbehandlungsfunktion für die Ausgangsmaterialien
             }
          PREP_EDUCT {
             # Vorbehandlungsfunktion für die Edukte
             }
          DISTRIBFUNC {
             # Nachbehandlungs(Verteilungs)funktion für alle Produkte
             }
          MODFUNC {
             # Modellfunktionen
             }
          FINISH {
             # Cleanup
             }
          default {
             return BAD
             }
          }

B.2.1. Variablen

Der Aufrufparameter val der C++-Regelfunktion ist ein Zeiger auf ein Objekt der Klasse rx_datex, über das der Austausch der Zeiger auf die Variablen erfolgt. Für die verschiedenen Variablentypen gibt es die Elementfunktionen put und get für Variablen sowie putco und getco für konstante Werte.

Die Deklaration der Variablen, die vom Kernsystem geholt werden bzw. an das übergeben werden, müssen in der ganzen Regelfunktion zugreifbar sein und dürfen nach dem Verlassen ihren Wert nicht verlieren. Variablen, die an das Kernsystem übergeben werden, wie zum Beispiel die Reaktivität (double), werden static deklariert und mit einem Anfangswert initialisiert. Für Variablen des Kernsystems, die gelesen werden, wie das Reaktionslevel (int), wird ein static const-Pointer deklariert.

In Tcl greifen die Funktionen put, get und putco intern auf den in Tcl nicht sichtbaren Pointer val zu.

C++-Code:

 static const int *var_level;
 static double var_reactivity = 0.;

Tcl-Code:

 # Für Variablen vom Kernsystem ist in Tcl
 # keine Deklaration nötig. Sie werden intern
 # automatisch als global deklariert.
 global var_reactivity
 set var_reactivity 0.0
Die Übergabe der Adressen der Variablen erfolgt dann unter INIT_RULES mit:

C++-Code:

 val->get("level", &var_level);
 val->put("reactivity", &var_reactivity);

Tcl-Code:

 get level var_level
 put reactivity var_reactivity
Kann die Adresse der Variable "level" nicht geholt werden, wird in C++ var_level auf 0 gesetzt. Um in Tcl zu überprüfen, ob die Variable "level" geholt werden konnte, kann der Rückgabewert des Kommandos get überprüft werden:

Tcl-Code:

 set flag [get level var_level]
Hat die Variable flag den Wert 1, konnte die Variable var_level abgeholt werden. Im anderen Fall hat flag den Wert 0. In Tcl besteht außerdem die Möglichkeit, bei put und putco den Namen der Variablen wegzulassen. Er ist dann identisch mit dem Namen, unter dem die Variable übergeben wird.

Die Variablen können dann in beliebigen Regelteilen folgendermaßen gelesen bzw. gesetzt werden:

C++-Code:

 int i = *var_level;
 var_reactivity = 1.4e-8;

Tcl-Code:

 set i var_level
 set var_reactivity 1.4e-8
Immer, wenn man *var_level verwendet, erhält man das aktuell gültige Level. Für die Reaktivität holt sich das Kernsystem nach jeder erfolgreichen Reaktion den aktuellen Wert. Dies gilt im übrigen auch für alle anderen an das Kernsystem übergebenen Variablen, die vom Typ int oder double sind. Eine Reaktion ist beendet, wenn der entsprechende Regelteil verlassen wird oder wenn eine der beiden Funktionen save_active_ens_as_product bzw. save_ens_as_product aufgerufen wird. Die Werte der Variablen werden im Reaktionsfile unter /REACLOG mit ausgegeben. Wenn die Kinetik angeschaltet ist, wird die Variable reactivity vom Typ double benötigt. Sie gibt die Geschwindigkeitskonstante der Reaktion an bzw. die Wahrscheinlichkeit beim Modus prob_kin der Kinetik.

Als Variablen vom Kernsystem stehen zur Verfügung:

level, phase und reactor (alle vom Typ int), sowie zu Testzwecken temperature, pressure (beide double), hihi (int), program_name (Konstante const char*), string_array (Konstante const char *const *), variable_string (const char*) und array_probe (vector<int>).

B.2.2. Name und Datum

Wie unter dem Punkt Variablen schon angesprochen, können mit der Klasse rx_datex auch konstante Werte übergeben werden. Dies wird beispielsweise für den Namen und das Datum der Regeln verwendet.

C++-Code:

 val->putco("name","Regelname");
 val->putco("date","13.11.1996");

Tcl-Code:

 set name_var "Regelname"
 putco name name_var
 set date_var 13.11.1996
 putco date date_var
Vom Kernsystem wird der Regelname dann folgendermaßen abgeholt:

 const char *name;
 var->getco("name", &name);
 cout << "The name of the rules is " << name << endl;
Vergleicht man den C++-Code für die Übergabe von Konstanten mit dem der Variablen, so erkennt man, daß bei den Konstanten im Aufruf von putco die Variable selbst steht und bei getco der Zeiger auf die Variable und nicht, wie bei der Übergabe der Variablen in den Funktionen put und get, der Zeiger auf die Variable bzw. der Zeiger auf den Zeiger. Die Referenzierung der Konstanten ist gegenüber den Variablen bei der Übergabe also um eins erniedrigt.

B.2.3. Reaktoren und Phasen

Auch die Einstellungen der Reaktoren und Phasen werden im Teil INIT_RULES der Regeln festgelegt. Zunächst müssen die Anzahl der Reaktoren und Phasen sowie die Zugehörigkeit der Phasen zu den Reaktoren angegeben werden. Dies geschieht mit der Konstante "phases_per_reactor", die von Typ const int[] ist. Jede Zahl in diesem int-Array steht dabei für die Anzahl der Phasen im Reaktor. Das int-Array wird mit 0 abgeschlossen. Im folgenden Beispiel werden 2 Reaktoren mit zwei Phasen bzw. einer Phase definiert. Der Reaktor 1 enthält die Phasen 1 und 2 und der Reaktor 2 die Phase 3.

C++-Code:

 {
 static const int ppr[] = { 2, 1, 0 };
 val->putco("phases_per_reactor", ppr);
 }

Tcl-Code:

 global ppr
 set ppr {2,1,0}
 putco phases_per_reactor ppr
Als nächstes muß festgelegt werden, welche Verbindungen als Ausgangsmaterialien für die einzelnen Reaktoren dienen. Dabei ist zu beachten, daß die Startmaterialien für jeden Reaktor in die erste Phase dieses Reaktors gegeben werden. Im obigen Beispiel also in Phase 1 für den Reaktor 1 und in Phase 3 für den Reaktor 2. Für alle Reaktoren wird angegeben, wo die Startmaterialien herkommen. Dies sind grundsätzlich alle Verbindungen einer bestimmten Phase, die angegeben wird. Dementsprechend wird für jeden Reaktor die Nummer der Phase mit den Ausgangsmaterialien angegeben, wobei für den ersten Reaktor noch keine Strukturen aus einer anderen Phase zur Verfügung stehen. Für ihn wird die Phase 0 angegeben. Sollen nun im obigen Beispiel die Produkte aus Phase 2 in den Reaktor 2 übernommen werden, ist dies folgendermaßen zu kodieren:

C++-Code:

 {
 static const int inp_phase[] = { 0, 2 };
 val->putco("input_phase_for_reactors", inp_phase);
 }

Tcl-Code:

 global inp_phase
 set inp_phase {0,2}
 putco input_phase_for_reactors inp_phase
Normalerweise werden alle vom File eingelesenen Ausgangsmaterialien der Phase 1 zugeteilt, es besteht aber auch die Möglichkeit, sie in beliebige andere Phasen zu geben. Dazu kann im CTX-File für jedes Molekül die Eigenschaft M_PHASE angegeben werden, die dann die Nummer der Phase enthält. Beim Einfügen der Aggregate wird diese in die Eigenschaft AG_PHASE kopiert, die dann ausgewertet wird. Enthält das Eingabefile keine Phasenangabe, wird noch nachgesehen, ob in INIT_RULES eine Variable des Typs vector<int> unter dem Namen start_phase übergeben wurde. Ist dies der Fall, gibt sphs[0] die Phase für das erste Aggregat an. Kann keine Angabe über die Anfangsphase gefunden werden, kommt das Aggregat in die Phase 1. Im folgenden Beispiel wird angegeben, daß das Aggregat 1 in die Phase 3 kommt:

C++-Code:

 static vector<int> sphs(1);
 sphs[0] = 3;
 val->put("start_phase", &sphs);

Tcl-Code:

 global sphs
 set sphs {3}
 put start_phase sphs
Dabei ist es nur wichtig, daß in INIT_RULES die Variable für die Einträge der Phasen für die Ausgangsmaterialien übergeben wird. Die Einträge können auch erst während der Vorbehandlung der Ausgangsmaterialien gesetzt werden. Die Vorbehandlung kann abhängig von der Zahl der Eduktensembles mehrfach aufgerufen werden, wobei nach jedem Aufruf die Phasen für alle gerade vorbehandelten Aggregate gesetzt sein müssen, da sie direkt danach von EROS7 gelesen werden. Alle Aggregate werden von null ab mit jedem Aufruf von PREP_ROOT durchnumeriert, wobei für jedes Aggregat im Ensemble hochgezählt wird. Ist ein Aggregat ein zweites Mal enthalten, wird nicht hochgezählt.

Desweiteren kann für jeden Reaktor noch festgelegt werden, ob die Edukte ein Ausgangsgemisch darstellen oder ob sie getrennt voneinander behandelt werden sollen. Dafür gibt es für jeden Reaktor ein Flag (1=Gemisch, 0=jede Verbindung einzeln). Sollen zunächst im ersten Reaktor alle Ausgangsmaterialien miteinander reagieren, werden aber danach chromatografisch getrennt und getrennt voneinander, aber gleich, aufgearbeitet, ergibt sich folgender Code:

C++-Code:

 {
 static const int all_educts[] = { 1, 0 };
 val->putco("use_all_educts_together", all_educts);
 }

Tcl-Code:

 global all_educts
 set all_educts {1,0}
 putco use_all_educts_together all_educts
Jetzt fehlt nur noch, daß festgelegt wird, welche Verbindungen im Strukturfile ausgegeben werden. Um die Verbindungen der Phase 3 auszugeben, schreibt man:

C++-Code:

 val->putco("output_phase",3);

Tcl-Code:

 global ophase
 set ophase 3
 putco output_phase ophase
Die Angabe der Ausgabephase kann jedoch beim Aufruf von EROS7 mit der Option -p überschrieben werden.

Bei der Kodierung von "input_phase_for_reactors" und "use_all_educts_together" ist darauf zu achten, daß für alle Reaktoren ein entsprechender Wert angegeben ist, da intern die Größe des allocierten int-Arrays nicht abgeprüft werden kann.

B.2.4. Phaseneigenschaften

Für die definierten Phasen wird noch der Modus festgelegt, der bestimmt, wie die Phase ihre Edukte für Reaktionen zusammenstellt. Folgende Modi stehen zur Verfügung:

C++-Code:

 {
 static const int phprop[]={MIX, MIX, MONOMOLEC};
 val->putco("phase_property", phprop);
 }
In Tcl sind die oben angegebenen Modi als interne Variablen definiert, die nur gelesen werden können.

Tcl-Code:

 global phprop
 set phprop "$MIX,$MIX,$MONOMOLEC"
 putco phase_property phprop

B.2.4.1. INERT

Eine Phase, die mit INERT gekennzeichnet ist, generiert selbst keine Reaktionen, dient allerdings als Aggregatspeicher für andere Phasen, die den Modus SURFACE oder auch MIX oder MIX_NO_A_A hat. Funktionsweise siehe Modus SURFACE.

B.2.4.2. MONOMOLEC

Der Begriff MONOMOLEC ist von monomolekular abgeleitet. In diesem Modus erzeugt die Phase Reaktionen, bei denen ein einziges Aggregat als Edukt verwendet wird. Die Phase erzeugt so Reaktionen erster und pseudoerster Ordnung.

B.2.4.3. MIX (Modus von EROS6) und MIX_NO_A_A

Ist die Phase im Modus MIX, produziert sie alle Reaktionen ausgehend von einem Aggregat und alle Reaktionen, die von allen möglichen Paaren aller Aggregate dieser Phase ausgehen. Im Modus MIX werden dabei auch die Reaktionen erzeugt, die zweimal das Aggregat X als Edukte haben. Im Modus MIX_NO_A_A werden diese Reaktionen nicht erzeugt. Zusätzlich werden noch alle Reaktionen wie im Modus SURFACE durchgeführt.

B.2.4.4. SURFACE

Im Modus SURFACE erzeugt die Phase alle Reaktionen, die von zwei Aggregaten ausgehen, wobei eines der Aggregate aus der Phase selbst stammt, wohingegen das andere aus einer angrenzenden Phase kommt. Dazu muß festgelegt werden, welche Phasen benachbart sind (oder in Kontakt stehen). Die Nachbarschaften werden als 0-terminiertes Array aus Zahlenpaaren angegeben. Zum Beispiel: 1, 2, 2, 3, 0. Dies bedeutet, daß Phase 1 mit Phase 2 in Kontakt steht und Phase 2 mit Phase 3. Die andere Phase ist häufig im Modus INERT und speichert nur eine bestimmte Gruppe von Verbindungen, wie für dem Einsatz zur kombinatorischen Chemie.

C++-Code:

 {
 static const int phct[]={ 1, 2, 2, 3, 0 };
 val->putco("phase_contacts",phct);
 }

Tcl-Code:

 global phct
 set phct {1, 2, 2, 3, 0}
 putco phase_contacts phct
Um Reaktionen nicht doppelt zu erzeugen, ist bei der Angabe der Phasenkontakte die Reihenfolge von Bedeutung. 1, 2 ist also nicht gleich 2, 1. Im ersten Fall werden die Reaktionen von Phase 1 und im zweiten von Phase 2 erzeugt. Dies macht keinen Unterschied, solange weder in Phase 1 noch in Phase 2 während der Reaktionsgenerierung neue Aggregate in einer der Phasen gebildet werden. Dies ist allerdings oft nicht der Fall, weshalb die Reihenfolge von Bedeutung ist.

B.2.4.5. TUBE (Modus von EROS5)

In diesem Modus werden die Aggregaten des Ausgangsensembles zusammengehalten und auch die Folgereaktionen nur mit den nach den vorher abgelaufenen Reaktionen vorliegenden Substanzen durchgeführt. Ist also im Ausgangsensemble ein Wassermolekül und wurde dies in einem ersten Hydrolyseschritt verbraucht, steht Wasser in den Folgereaktionen nicht mehr zur Verfügung, wohl aber die Reaktionsprodukte.

A + B C + D E F + G

Im Modus Tube ist keine Kinetik möglich.

B.2.5. Kinetik

Abschließend zu den Einstellungen der Phasen und Reaktoren muß noch das Kinetikmodell für jeden Reaktor gesetzt werden. Dabei stehen folgende Methoden zur Verfügung:

C++-Code:

 {
 static vector<double> sconc(1), vols(3), flow(3);
 static vector<int> to_phase(1), flow_to(3);
 sconc[0] = 0.10;
 to_pahse[0] = 1; // Aggregat 1 kommt in Phase 1 (default)
 vols[0] = 1.0; // Volumen für Phase 1
 vols[1] = 1.0; // Volumen für Phase 2
 vols[2] = 1.0; // Volumen für Phase 3
 flow[0] = 0.;
 flow[1] = 0.;
 flow[2] = 0.;
 flow_to[0] = 0;
 flow_to[1] = 0;
 flow_to[2] = 0;
 static const char *const kin_mode[]={ "gear", "gear" };
 val->putco("kinetic_model", kin_mode);
 val->putco("conversion_limit", 0.5);
 val->putco("reaction_time", 5.e7);
 val->putco("minimal_concentration", 1.e-10);
 val->put("start_conc",&sconc);
 val->put("start_phase", &to_pahse);
 val->put("phase_volume", &vols);
 val->put("phase_flow", &flow);
 val->put("pahse_flow_to", &flow_to):
 }

Tcl-Code:

 global kin_mode min_conc conv_lim reac_time sconc vols
 global to_phase
 set sconc(0) 0.1
 set to_phase(0) 1 # Aggregat 1 kommt in Phase 1 (default)
 set vols {1.0,1.0,1.0}
 set flow {0.,0.,0.}
 set flow_to {0,0,0}
 set kin_mode {"gear","gear"}
 set min_conc 1.e-10
 set conv_lim 0.5
 set reac_time 5.e7
 putco kinetic_model kin_mode
 putco conversion_limit conv_lim
 putco reaction_time reac_time
 putco minimal_concentration min_conc
 put start_conc sconc
 put start_phase to_phase
 put phase_volume vols
 put phase_flow flow
 put phase_flow_to flow_to
Hat man einen der Kinetikmodi gear, runge_kutta oder runge_kutta_merson gewählt, ist es auch möglich, für einzelne Reaktionstypen eine Kinetik nach Michaelis-Menten oder nullter Ordnung festzulegen. Diese Arten der Kinetik treten bei enzymatischen Reaktionen auf. Bei ihnen ist eine Gleichgewichtsreaktion zur Bildung des Enzym-Substrat-Komplexes der enzymkatalysierten Reaktion vorgelagert (siehe Abbildung 213).

Abbildung 213: Enzymreaktion.

Diese Einzelreaktionen können von EROS7 so erzeugt werden, es setzt allerdings voraus, daß das Enzym (bzw. eine vereinfachte Form) als Reaktand eingesetzt wird. Da dies oft nicht gewünscht wird, wurde für EROS7 auch die Kinetik nach Michaelis-Menten eingeführt (siehe Formel 17). Es ergibt sich eine vereinfachte Reaktion, wie sie in Abbildung 214 gezeigt ist.

Abbildung 214: Vereinfachte Enzymreaktion.

Sind solche Reaktionstypen in den Regeln enthalten, übergibt man zusätzlich zur reactivity-Variablen auch eine double-Variable unter dem Namen Km, in der für diese Reaktionstypen der Wert der Michaelis-Konstante übergeben wird. Der reactivity-Variable wird bei diesen Reaktionstypen das Produkt aus k2 und der Enzymkonzentration [E]0 zugewiesen. Der Reaktionstyp erhält das Attribut michaelis_menten_kinetics (siehe B.3.1). Befindet sich die Enzymreaktion ständig im Sättigungsbereich, kann man durch die Angabe des Attributs force_zero_order für den Reaktionstyp eine Kinetik nullter Ordnung erzwingen.

Ist der Gear-Algorithmus als Kinetik gewählt, kann mit EROS7 auch eine Mehrfachdosierung simuliert werden. Hierzu übergibt man eine const double unter dem Namen multi_dose mit der Zeit zwischen den Dosierungen. EROS7 erhöht dann die Konzentration der Ausgangsverbindungen in gleichen Zeitintervallen um die Anfangskonzentrationen. Soll mehrfach dosiert werden, aber nicht in gleichen Zeitabständen, kann unter dem Namen multi_dose auch ein vector<double> mit den Zeiten der Dosierung übergeben werden. Auch in diesem Fall wird mit der Anfangskonzentration der Ausgangsverbindungen begonnen. Wird als erste Zeit 0.0 Sekunden angegeben, kann jedoch auch mit der doppelten Konzentration angefangen werden.

B.2.6. Weitere globale Einstellungen

Zu den weiteren globalen Einstellungen gehören die Festlegung, was im Falle eines internen Fehlers zu geschehen hat. Fast alle Zugriffsroutinen auf das Ensemble geben ein Fehlerflag zurück. Da aber in aller Regel diese nicht überprüft werden, ist die Voreinstellung so, daß alle Reaktionen, bei denen ein Fehler aufgetreten ist, verworfen werden. Dies geschieht auch dann, wenn der entsprechende Regelteil FUNC mit OK zurückkehrt. Schreibt man Regeln, bei denen alle Fehlerflags überprüft werden und der Regelteil davon abhängig weitergeführt wird, kann man die interne Löschung von Reaktionen mit Fehlern folgendermaßen im Regelteil INIT_RULES abschalten:

C++-Code:

 val->putco("no_discard_on_error", 1);

Tcl-Code:

 global nodisonerr
 set nodisonerr 1
 putco no_discard_on_error nodissonerr
Analog der internen Fehlerüberprüfung findet auch eine Überprüfung der Korrektheit der Produkte statt. Der Modus für diese Valenzüberprüfung kann gesetzt werden mit:

C++-Code:

 val->putco("valence_mode", "organic");

Tcl-Code:

 global vmode
 set vmode organic
 putco valence_mode vmode
Es stehen die Möglichkeiten organic, inorganic, ms und ms-inorganic zur Verfügung. Hat der Modus den Wert none, ist die Valenzüberprüfung abgeschaltet.

B.2.7. Vorbehandlungsfunktionen für die Ausgangsmaterialien (PREP_ROOT)

Diese Funktion wird für jedes eingelesene Eduktensemble einmal aufgerufen. Hier können Vorbehandlungen der Ausgangsmaterialien, wie das Markieren saurer Wasserstoffatome oder funktioneller Gruppen vorgenommen werden. Es ist aber auch möglich, hier die Phasen, Konzentrationen und Zuflüsse für die Ausgangsverbindungen festzulegen (siehe B.2.3). In Bezug auf Modifikationen am Ensemble entspricht der Umfang der Möglichkeiten denen in FUNC der einzelnen Regeln (siehe unten). Im Unterschied von FUNC findet keinerlei Variablenaustausch statt und das vorbehandelte Ausgangsensemble ist dasjenige, das nach ein oder mehreren Reaktionen herausgekommen ist. In aller Regel ist allerdings keine Vorbehandlung nötig und es genügt folgende Zeile in dieser Funktion:

C++-Code:

 return OK;

Tcl-Code:

 return OK

B.2.8. Vorbehandlungsfunktionen für die Edukte (PREP_EDUCT)

Wie für die Ausgangsmaterialien kann auch für jedes Eduktensemble einer Reaktion eine Vorbehandlungsfunktion geschrieben werden. Auch sie hat den gleichen Funktionsumfang und das letzte Eduktensemble in der Reaktionsfolge ist das vorbehandelte. Eine Rolle spielt diese Funktion vorwiegend im Zusammenhang mit der Verteilungsfunktion oder zum Ausschluß bestimmter Verbindungen von der Weiterreaktion. In aller Regel kann aber auch diese entfallen:

C++-Code:

 return OK;

Tcl-Code:

 return OK

B.2.9. Die Verteilungsfunktion (DISTRIBFUNC)

Diese Funktion wird immer dann aufgerufen, wenn ausgehend von einem Eduktensemble alle Reaktionen durchgeführt wurden. Es besteht hier die Möglichkeit, zu entscheiden, ob einzelne Reaktionen verworfen werden sollen. Bei symmetrischen Reaktionen an unsymmetrischen Molekülen kann es nicht ganz ausgeschlossen werden, daß eine Reaktion mehrfach erzeugt wird. Die weiteren Reaktionen können verworfen werden, aber auch mit der ersten zusammengefaßt werden, indem man den Symmetriefaktor der ersten Reaktion auf die Summe aller Symmetriefaktoren setzt. Desweiteren können hier noch weitere Werte einer Reaktion berechnet werden. Ein gewichteter Reaktivitätswert bezüglich der Konkurrenzreaktionen wäre hier denkbar.

Der folgende Code zeigt, was intern ausgeführt wird, wenn die Verteilungsfunktion lediglich aus dem Befehl return OK; besteht:

C++-Code:

 {
 print << "DISTRIBFUNC called.\n";
 int    n_rxs=-1, irx, cur_rx;
 val->getco("#rxs", &n_rxs);
 if (n_rxs < 0) return BAD;
 static vector<int> ok_var;
 ok_var.resize(n_rxs);
 const vector<double> *vprob;
 val->get("reactivity", &vprob);
 const vector<int> *eqv_rxn, *ophs;
 val->get("eqv_rxs", &eqv_rxn);
 val->get("rxn_phase", &ophs);
 int cur_rx = 2, iphs = (*ophs)[0], cphs, irx2, cphs2;
 for (irx=1; irx<=n_rxs; irx++) {
    if ((*eqv_rxn)[irx] == cur_rx) {
       cur_rx++;
       ok_var[irx-1] = 1;
    } else {
       ok_var[irx-1] = 0;
    }
    cphs = (*ophs)[irx];
    if (((*eqv_rxn)[irx]==1)&&(iphs!=cphs)) {
       bool take = true;
       for (irx2=1; irx2<irx; irx2++) {
          cphs2 = (*ophs)[irx2];
          if (((*eqv_rxn)[irx2]==1)&&(cphs==cphs2)) {
             take = false;
             break;
          }
       }
       if (take) ok_var[irx-1] = 1;
    }
    print << "eqv product " << (*eqv_rxn)[irx] << "  ";
    if (ok_var[irx-1] == 1) {
       print << "accepting reaction ";
    } else {
       print << "rejecting reaction ";
    }
    print << irx << " with a probability of ";
    print << (*vprob)[irx-1] << endl;
 }
 val->put("rx_ok", &ok_var);
 return OK;
 }

Tcl-Code:

 print "DISTRIBFUNC called.\n"
 get "#rxs" n_rxns
 if {$n_rxs < 0} {return BAD}
 global ok_var
 resize ok_var $n_rxs
 get reactivity vprob
 get eqv_rxs eqv_rxn
 get rxn_phase ophs
 set cur_rx 2
 set iphs $ophs(0)
 for {set irx 1} {$irx<=$n_rxs} {incr irx} {
    set idx [expr $irx-1]
    if {$eqv_rxn($irx) == $cur_rx} {
       incr cur_rx
       set ok_var($idx) 1
    } else {
       set ok_var($idx) 0
    }
    set cphs $ophs($irx)
    if {{$eqv_rxn($irx)==1}&&{$iphs!=$cphs}} {
       set take 1
       for {set irx2 1} {$irx2<$irx} {incr irx2} {
          set cphs2 $ophs($irx2)
          if {{$eqv_rxn($irx2)==1}&&{$cphs==$cphs2}} {
             set take 0
             break
          }
       }
       if {$take} {set ok_var($idx) 1}
    }
    print "eqv product $eqv_rxn($irx)   "
    if {$ok_var($idx) == 1} {
       print "accepting reaction"
    } else {
       print "rejecting reaction"
    }
    print " $irx with a probability of $vprob($idx)\n"
 }
 put rx_ok ok_var
 return OK
Die Variable #rxs gibt die Zahl der erfolgreich durchgeführten Reaktionen an und gibt damit die Dimension der Vektoren der anderen Variablen an. eqv_rxs ist die Äquivalenzklasse des Produkts, wobei 1 das Edukt selbst ist. Die Äquivalenzklasse des Produkts der ersten Reaktion bzw. die Phase für die Produkte (rxn_phase) erhält man mit dem Index 1; der Index 0 ist für das Edukt. Das Ergebnis der Verteilungsfunktion ist die Variable rx_ok, die mit 1 angibt, daß die Reaktion behalten wird bzw. mit 0, daß die Reaktion verworfen wird. Neben den Variablen #rxs, eqv_rxn, rxn_phase, rx_symmerty, rx_rule_nr und reactivity stehen in dieser Funktion auch alle Variablen der Reaktion zur Verfügung, die wie der Reaktivitätswert EROS7 bekanntgegeben wurden und vom Typ int oder double sind. Sie kommen dann hier als vector<int> bzw. vector<double> für alle Reaktionen eines Edukts an. Für die Reaktivität und alle weiteren während der Reaktion berechneten Variablen gilt Index 0 für die erste Reaktion. Nur für eqv_rxn, rxn_phase und rx_ok hat der Eintrag für die Reaktion 1 den Index 1.

Liefert die DISTRIBFUNC keinen vector<int> unter dem Namen rx_ok, wird der oben angegebene in EROS7 eingebaute Algorithmus verwendet, der alle Reaktionen verwirft, die identisch sind und deren Produkte in die gleiche Phase gehen (siehe Beispiel oben). Behalten wird nur die erste Reaktion. Daneben werden auch noch die invarianten Reaktionen verworfen, bei denen Edukt und Produkt identisch sind und der gleichen Phase angehören. Soll dies genutzt werden, sieht der Regelteil folgendermaßen aus:

C++-Code:

 return OK;

Tcl-Code:

 return OK
Kehrt die Funktion mit BAD zurück, werden alle Reaktionen dieses Edukts verworfen.

Will man hier die Reaktivität und / oder die Symmetriezahl einer Reaktion anpassen, so kann man dies tun, indem man die einen vector<double> als reactivity und einen vector<int> als symmetry übergibt. Die Reaktivität muß in diesem Fall von den Reaktionen in eine andere Variable geschrieben werden. Der von EROS7 berechnete Symmetriefaktor wird als vector<int> unter dem Namen rx_symmetry bereitgestellt. Es können hier aber auch weitere Werte für die Reaktionen berechnet werden. Werden sie an EROS7 zurückgegeben, werden diese auch bei den Reaktionen abgespeichert und im Reaktionsfile ausgegeben.

B.2.10. Die Modellfunktionen (MODFUNC)

In diesem Regelteil ist es möglich, dem Programm vom Benutzer definierte Berechnungsfunktionen zur Verfügung zu stellen. Welche Funktionen verwendet werden können und Daten vom Programm geliefert bzw. erwartet werden, hängt ganz vom Programm selbst ab. EROS7 verwendet derzeit keine dieser Funktionen. Der Code, der besagt, daß keine Modellfunktion vorhanden ist, sieht folgendermaßen aus:

C++-Code:

 return BAD;

Tcl-Code:

 return BAD
Wenn sie implementiert werden soll, sieht sie etwa folgendermaßen aus:

C++-Code:

 if (test) {
    val->putco("name", "meine Modellfunktion");
    return OK;
 } else {
    static vector<double> *in, out;
    val->get("var_of_eros7", &in);
    if (!in) return BAD;
    // mache etwas
    out[0] = 17.34;
    val->put("result_of_my_func", &out);
    return OK;
 }

Tcl-Code:

 if {$test} {
    set tvar "meine Modellfunktion"
    putco name tvar
    return OK
 } else {
    set flag [get var_of_eros7 in]
    if {$flag == 0} return BAD
    # mache etwas
    set out(0) 17.34
    put result_of_my_func out
    return OK
 }

B.2.11. Die Cleanup-Funktion (FINISH)

Diese Funktion wird aufgerufen, nachdem das gesamte Reaktionsnetzwerk aller Reaktoren aufgebaut wurde. Sie wird allerdings nur in Spezialfällen, wie der Nutzung von EROS7 als Schnittstelle zur chemischen Datenstruktur RICOS für andere Anwendungen (siehe 6.13), gebraucht, weshalb normalerweise folgender Code ausreicht:

C++-Code:

 return OK;

Tcl-Code:

 return OK


[Prev] [Next] [Home DissOnline]


Hoellering@CCC.Chemie.Uni-Erlangen.DE
Copyright © 1998, Höllering Universität Erlangen-Nürnberg. All rights reserved.