08.3 Arbeitsschritte bei der Moduleinbindung

Zur Einbindung eines Moduls in ArcEGMO sind drei Arbeitsschritte notwendig:

  1. Erstellung und Kompilierung des Moduls und Einbindung in die Bibliothek module.lib,
  2. Anpassung der Deklarationsroutine mod_dec.cund anschließende Kompilierung und
  3. Linken des Gesamtsystems.

 

8.3.1 Erstellung eines Moduls

Jedes Modul setzt sich aus einer Deklarationsroutine und einer Folge von Subroutinen zur Beschreibung von hydrologischen Teilprozessen zusammen.

In dieser Deklarationsroutine wird eine Struktur belegt und an ArcEGMO übergeben, mit folgendem Inhalt:

  1. Name des Moduls,
  2. Raumdiskretisierungen, für die das Modul angewendet werden kann und
  3. Funktionspointer von Routinen, die dann an definierten Stellen innerhalb der Simulationshierarchie aufgerufen werden.

In Abbildung 8.3‑1 ist beispielhaft die Deklarationsroutine des Moduls EFL_MOD1 wiedergegeben. Es wird empfohlen, für die Integration eigener Module neben der folgenden Beschreibung auch ein Muster (z.B. …\Module\abi\efl_mod1.c) als Vorlage zu verwenden bzw. in einer Kopie dieser Vorlage direkt die gewünschten Änderungen vorzunehmen.

Über den hier angegebenen Modulnamen EFL_MOD1 (s. 4. in Abbildung 8.3‑1) wird das zu aktivierende Modul (s. Steuerdatei ARC_EGMO.STE – Kapitel 3) beim Programmstart ausgewählt. Gleichzeitig wird bei Start überprüft, ob die für die Simulation gewählte Raumdiskretisierung mit diesem Modul realisiert werden kann. Dazu werden die zulässigen Raumdiskretisierungen innerhalb der Deklarationsroutine vorgegeben (s. 3.).

Über den Namen der Deklarationsroutine wird diese dem System bekanntgemacht. Aus Gründen der Übersichtlichkeit sollte der Name dieser Routine (s. 2.) ebenso wie der Name der Datei, in der das Modul gespeichert ist, gleich dem Modulnamen sein.

Insgesamt können für ein Modul 6 Eintrittspunkte bereitgestellt werden. Diese Eintrittspunkte sind Funktionen, die vor, während und nach der Simulationszeitschleife aktiviert werden und für verschiedene Aufgaben wie die Parameterermittlung, die eigentliche Simulation und das Freigeben allokierter Speicherbereiche vorgesehen sind. Tabelle 8.3‑1 gibt einen Überblick.

Weiterhin besteht die Möglichkeit, über eine weitere Funktion, die an den Pointer ModulDT gebunden wird, die (aktuelle) Zeitdiskretisierung bzw. Berechnungszeitschrittweite des Moduls abzufragen.

 

#include <ben_lib.h>
#include „arc_egmo.h“
#include „Efl_Mod1.cpo“                                                   1
static ModulDeclare *md;
ModulDeclare * Efl_Mod1()                                                 2
{
/* Eintragen der Raumbezuege, fuer die das Modul eingesetzt werden kann*/
static char *Raumbezuege[]={„EFL“,“…};                                3
md = DbNew(ModulDeclare);
md->n_Rb = NumberOf(Raumbezuege);
GetRaumbezuege( &md->Raumbezuege, Raumbezuege, md->n_Rb );
/* Eintragen des Namens, ueber den das Modul in ArcEGMO.STE aktiviert werden soll */
strcpy( md->ModulName, „Efl_Mod1„);                                     4
/* Initialisierung des Modul – Aufruf in ArcEGMO vor Zeitschleife   */
md->ModulBIni  = EflMod1BIni; /* vor der Ortsschleife */                5
md->ModulIni    = EflMod1Ini; /* in  der Ortsschleife */                6
/* Subroutine fuer die Simulationen – Aufruf in ArcEGMO in der Zeitschleife */
md->ModulDT     = Met_DTd;    /* Zeitschrittweite fuer Modulabarbeitung */     8
md->ModulBRun = EflMod1BRun;  /* vor der Ortsschleife */                7
md->ModulRun   = EflMod1Run;  /* in  der Ortsschleife */                9
md->ModulERun  = EflMod1ERun; /* nach der Ortsschleife*/                10
/* Subroutine, ueber die eventuell allocierte Speicherbereiche wieder freigegeben werden oder abschliessende Auswertungen erfolgen – Aufruf nach Zeitschleife */
md->ModulClear = EflMod1Clear; /* oder z.B. DummyI1; */                 11
return(md);
}

Abbildung 8.3‑1: Auszug aus dem Modul EFL_MOD1 – Moduldeklaration


Tabelle 8.3‑1: Moduleintrittspunkte

Funktionspointer Beispiel Aufruf Aufgabe
int ModulBIni (int) EflMod1BIni(n_efl) vor Zeitschleife, außerhalb Ortsschleife Modulinitialisierung, Speicherallokation
int ModulIni (int,int) EflMod1Ini(i_efl,i_rb) vor Zeitschleife, innerhalb Ortsschleife Parameterermittlung, Anfangswertfestlegung
int ModulBRun (int) EflMod1BRun(n_efl) in Zeitschleife, vor Ortsschleife
int ModulRun (int,int) EflMod1Run(n_efl,i_rb) in Zeitschleife, innerhalb Ortsschleife Simulation
int ModulERun (int) EflMod1Run(n_efl) in Zeitschleife, nach Ortsschleife
int ModulClear(int) EflMod1Clear(n_efl) nach Zeitschleife Speicherfreigabe
double* ModulDT() Met_DTd() in Zeitschleife Festlegung der Berechnungszeitschrittweite
n_efl – Anzahl der Elementarflächen,i_efl – aktuelle Elementarfläche,i_rb – übergeordneter Raumbezug, z.B. i_tg (nur bei Hydrotopklassenbezogener Modellierung interessant)

Abbildung 8.3‑2 zeigt am Beispiel des Moduls EFL_MOD1 die Routinen, die als Eintrittspunkte dienen.

 

/**************************************************************************/
/****              ModulInitialisierung                               *****/
/**************************************************************************/
static int EflMod1Ini( rb, dummy )
int rb, dummy;      /* rb gibt den aktuellen Raumbezug, hier die EFL an */
{
EflMod1_Ini( Vorgeschichte(), YearDay(),
Efl_Grundwasserflurabstand_Rep(rb),
Efl_Interzeptionskapazitaet  (rb),

Abi_Bodenspeicherfuellung    (rb,0));
return(0);
}
/**************************************************************************/
static int EflMod1BIni( nrb )   /* Hier Dummy-Routine, die nichts macht */
int nrb;     /* nrb ist die Anzahl der Raumbezuege, hier die der EFL */
{
return(0);
}
/**************************************************************************/
/****              Simulation                                         *****/
/**************************************************************************/
/* Mit den folgenden beiden Routinen kan die Simulation organisiert werden*/
/**************************************************************************/
static int EflMod1BRun( nrb )
int nrb;            /* nrb ist die Anzahl der Raumbezuege, hier die der EFL */
{
return(0);
}
/**************************************************************************/
static int EflMod1Run( rb, dummy )
int rb, dummy;      /* rb gibt den aktuellen Raumbezug, hier die EFL an */
{
EflMod1_Run( Res_KorNiederschlag(),

Abi_Bodenspeicherfuellung    (rb,0));
return(0);
}
/**************************************************************************/
/****              ModulClear                                         *****/
/**************************************************************************/
static int EflMod1Clear( n )
int n;
{
return(0);
}
/**************************************************************************/
static void EflMod1_Ini( vorgeschichte, ve, dhgw, wom, wz_max, wz_min, nfk, bod_dicke, woa, wma, wb )
int  ve;
double *vorgeschichte, *wom, *wz_max, *wz_min, *nfk, *bod_dicke, *woa, *wma, *wb, *dhgw;
{
double wz, wg;
*woa = 0.;
*wma = 0.;

Abbildung 8.3‑2: Auszug aus dem Modul EFL_MOD1 – Eintrittspunkte

 

Weiterhin sind, dies ist aber eine generelle Empfehlung bei C-Programmen, die lokalen Funktionsprototypen innerhalb des Moduls im Dateikopf festzuhalten, entweder direkt oder über eine Include-Datei (EFL_MOD1.cpo – s. 1. in Abbildung 8.3‑1). Gleiches gilt für die Prototypen der globalen Funktionen. Diese müssen dem Gesamtsystem bekannt gemacht werden. Dies erfolgt durch einen Eintrag in die Datei …modulemodule.pro (s. Abbildung 8.3‑3), wiederum entweder über direkte Einträge oder über eine Include-Datei (siehe …includeEFL_MOD1.gpo – Abbildung 8.3‑4).

 

#include „efl_mod1.gpo
#include „faltung.gpo“

#include „common.gpo“

Abbildung 8.3‑3: Prototypen-Datei module.pro

1  /* Prototypes generated by mkpro – do not edit! */
2  #ifndef _NO_PROTO
3  #define ARGS(p) p
4  #else
5  #define ARGS(p) ()
6  #endif
7  ModulDeclare * Efl_Mod1
ARGS((void));
8  void intzep ARGS((double*, double*, double*, double*, double*));
9  void infilt ARGS((double*, double*, double*, double*, double*));
10 #undef ARGS
11 /* *** End of Prototypes *** */

Abbildung 8.3‑4: Prototypen-Datei EFL_MOD1.GPO

 

Um Namenskonflikte zu vermeiden, ist bei der Erstellung eines Moduls anzustreben, dass nur wenige Routinen „global“ bekannt sind. Unter- bzw. nachgeordnete Routinen sollten deshalb „static“ deklariert werden, können aber sonst frei gestaltet werden. Sofern untergeordnete Subroutinen auch in anderen Modulen verwendet werden sollen, sind sie im Verzeichnis COMMON zu verwalten.


8.3.2 Anpassung der Deklarationsroutine

Über die Deklarationsroutine mod_dec.c (s. Abbildung 8.3‑5) wird ArcEGMO mitgeteilt, welche Module in der Bibliothek verfügbar sind.

Programmtechnisch werden dazu die in den Deklarationsroutinen der Module angelegten, einzelnen Pointerstrukturen auf ein Feld mdgespeichert. Die Belegungsreihenfolge ist unerheblich, ein neues Modul würde so im Beispiel auf die Feldadresse 13 gespeichert werden. Die Felddimension ANZ_MOD wäre dazu auf 14 zu erhöhen.

Beim Start von ArcEGMO werden aus der Modulbibliothek die zu aktivierenden Module gemäß den angegeben Namen in der Steuerdatei ARC_EGMO.STE ausgewählt.

#include <ben_lib.h>
#include „arc_egmo.h“
#define ANZ_MOD 13
static ModulDeclare *md[ANZ_MOD];
static FILE *fd_steu;
/**************************************************************************/
void ModulDeclaration()
{
md[ 0] = SiWaE();
md[ 1] = Efl_Mod0();
md[ 2] = Efl_Mod1();
md[ 3] = Efl_Mod2();
md[ 4] = EGMO_NA();
md[ 5] = EGMO_WH();
md[ 6] = Rd_Simp();
md[ 7] = KinWave();
md[ 8] = EGMO_GW();
md[10] = Q_ELS();
return;
}

Abbildung 8.3‑5: Subroutine mod_dec.c


8.3.3 Linken des Gesamtsystems

Zur Erstellung eines ausführbaren Programms sind im Rahmen eines Link-Laufes die folgenden Dateien miteinander zu verknüpfen:

  • Hauptprogramm arc_egmo.obj,
  • Definitionsroutine mod_dec.obj,
  • betriebssystemspezifische Ausgabefunktion prn_test.obj,
  • ArcEGMO Bibliothek arc_egmo.lib und
  • Modulbibliothek module.lib.
Nach oben scrollen