next up previous contents 34
Nächste Seite: Literatur Aufwärts: Gitterbasierte Modellierung zur Simulation Vorherige Seite: B. Source-Code des eindimensionalen   Inhalt


C. Source-Code des hexagonalen Porenmodells

BEGIN
% %1
% Start des Programms
% #
  Comment       VERSION 1.0
  ---------------------------------------- Started :  SEP 1999 ------


     S     -------------      *****************************
           - K - m - H -      *  Kompost miete Hexagonal  *
     I     -------------      *****************************

     M
               * * *      --- Model of a grid-based Compost plant ---
     U         * K *
               * * *      --- with hexagonally arranged reaction  ---
     L
                          --- cells and their occasional merging  ---
     A

     Version  - 1.0 -
      LINUX
  ---------------------------------------------- State:  MARCH 2000 ---;

     Comment vers. 0.2: Änderung der Porennummerierung;
     comment vers. 0.3: Integration der Diffusionsgleichung;
     comment vers. 0.4: Integration von Bodenparamtern (porosität etc);
     comment vers. 0.5: Integration der Kohlenwasserstoffkinetik;
     comment vers. 0.6: Umwandlung der rechteckigen Versuchsmiete
                      in ein Trapez;
     comment vers. 0.7: Änderung der Reaktionskinetik;
     comment vers. 0.8: Integration eines Wassergradienten;
     comment vers. 0.9: Programmierung neuer Output-Klassen;
     comment vers. 0.10: Integration des Recovery-Systems;
     comment vers. 0.11: Runge-Kuttka 2.Ordnung;
     comment vers. 0.12: Anpassung des Wassergehaltes nach dem Wenden;

% /2
% Deklaration der externen Klasse GRPS, die einen graphischen
% Output ermöglicht.
% #
  EXTERNAL CLASS GRPS;

% %3
% Deklaration der globalen Parameter.
% #
  REAL    X_TOP,          Comment Breite des Trapez oben;
          X_BOTTOM,       Comment Breite der Trapez unten;
          Y_HEIGHT;       Comment Höhe der Miete;

  REAL    SIM_TIME,       Comment Dauer der Simualtion;
          TIMESTEP,       Comment Zeitschritt der Berechnungen;
          REC_INT,        Comment Intervall des Recovery-Outputs;
          UPD_INTERVAL;   Comment Zeitintervall mit dem der Wassergehalt
                                  nach dem Wenden angepasst wird;
  REAL    WAT_CHANGE;     Comment Rate der Anpassung des Wassergehalts an den
                                  Standardwert;
  INTEGER RST, RST_0;     Comment random start;
  REAL    LIST_INTERV,    Comment Intervall der Listen Ausgabe;
          DRAW_INTERV;    Comment Intervall der graphischen Ausgabe;
  REAL    HYDRO_BLACK,      Comment O2-Konzentration minimal. Darstellung
                                  in der Graphik schwarz;
          HYDRO_WHITE;      Comment O2-Konzentration maximal. Darstellung
                                  in der Graphik weiss;

  INTEGER OUTP_OPT1,      Comment Optionen de graphischen Outputs;
          OUTP_OPT2;
  REAL OXY_DIFF_RATE,     Comment Diffusionskoeffizient von Sauerstoff in Luft
                                  in [m^2/s];
       THON,              Comment  Theoretischer Sauerstoffbedarf für die
                                   Mineralisierung von 1g Diesleöl in g;
       PORO_TOTAL,        Comment Geasmtporosität;
       DENS_GRA,          Comment Dichte der festen Phase;
       DENS_WAT,          Comment Dichte von Wasser;
       WATER_CONT_MAX,    Comment Maximaler Wassergehalt in [kg/kgTS];
       WATER_CONT_MIN,    Comment Minimaler Wassergehalt;       
       RATE_BIOD_MAX,     Comment Maximale  Abbaurate [kg/m^3/Tag];
       K_C,               Comment Halbsättigungskonstante für die Dieselöl-
                                  Konzentration in der Substratkinetik;
       K_SO;              Comment Halbsättigungskonstante für die Sauerstoff-
                                  Konzentration in der Substratkinetik;
  REAL PI;                Comment Pi;


  INTEGER ROWS;         Comment Anzahl der Zellreihen in der Mietet;
  INTEGER X_CELLS;      Comment Maximale Anzahl der Zellen pro Reihe;
  INTEGER X_CperR;      Comment Anzahl der Zellen pro individueller
                                Reihe;

  INTEGER Y_HALF;       Comment ROWS / 2;
  REAL HEX,             Comment Seitenlänge eines Hexagons;
       HEX_VOL,         Comment Volumen eines Hexagons;
       AREA,            Comment Oberfläche, durch die Diffusion zur
                                Nachbarzelle stattfinden kann;
       DIST,            Comment Abstand zwischen zwei Porenzentren;
       WATER_DIFF;      Comment Maximaler Wassergradient in der Miete;
  REAL TS_PORE;         Comment Trockengewicht einer Pore in kg;
  INTEGER y_05, y_10;   Comment Hilfsvariablen zur Einteilung der Miete
                                in drei vertikale Zonen;
  REAL UPD_COUNT;       Comment Hilfsvariable, mit ermittelt wird, ob der
                                  Wassergehalt an den Standardwert angepasst
                                  werden muss;
  BOOLEAN MERGE;  Comment Boolsche Variable, dei angibt, ob gewendet wurde;
  TEXT T;  Comment Hilfsvariable für Textausgabe;
  INTEGER K, L, M, N,a, b, f, g; Comment Hilfsvariablen für Schleifen;
  REAL add_o, add_m , add_i, ave_o, ave_m, ave_i; Comment Hilfsvariablen;
  INTEGER counter_o, counter_m, counter_i; Comment Hilfsvariablen;

  REF (Infile)  INF;    Comment Referenzen auf die Input und Output-Files;
  REF (Outfile) OTF1, OTF2, OTF3;
  REF (OutFile) OTH1, OTH2, OTH3, oth, ave;
  ref (outfile) hyd, oxy, ore, hre, wre;
% %4
% Darstellung eines Titelbildschirms.
% #
                                                                   OutImage;
                                                                   OutImage;
                                                                   OutImage;
Outtext ("      UFT_KmH_KmH_KmH_KmH_KmH_KmH_KmH_KmH_KmH_KmH_UFT"); OutImage;
Outtext ("      U                                             T"); OutImage;
Outtext ("      U                                             T"); OutImage;
Outtext ("      U                 ------------                T"); OutImage;
Outtext ("      U               /  - K m H -   \              T"); OutImage;
Outtext ("      U              /  Vers.  10     \             T"); OutImage;
Outtext ("      U             /  K O M P O S T   \            T"); OutImage;
Outtext ("      U            /  MIETE  HEXAGONAL  \           T"); OutImage;
Outtext ("      U  _________/  CELLULAR AUTOMATON  \________  T"); OutImage;
Outtext ("      U                                             T"); OutImage;
Outtext ("      U                                             T"); OutImage;
Outtext ("      U        Programm to Simulate a Compost       T"); OutImage;
Outtext ("      U      Plant, which Degrades Hydrocarbons     T"); OutImage;
Outtext ("      U          through Microbial Activity.        T"); OutImage;
Outtext ("      U                                             T"); OutImage;
Outtext ("      UFT (Oliver Loenker, Broder Breckling)      UFT"); OutImage;
OutText ("                      1999, 2000                     "); OutImage;
                                                                   OutImage;
Outtext ("      The Programm Reads the Infile  -> KMH1.INF <-  "); OutImage;
Outtext ("                                                     "); OutImage;


% %5
% Einlesen der Parameterwerte, mit denen die Simulation initialisiert
% wird, aus einer externen Datei.
% #
  INF :- NEW Infile("kmh1.inf");
  INF.Open (Blanks (120) );  Inf.InImage;
  X_TOP       := Inf.InReal;  Inf.InImage;
  X_BOTTOM    := Inf.InReal;  Inf.InImage;
  Y_HEIGHT    := Inf.InReal;  Inf.InImage;
  SIM_TIME    := Inf.InReal; Inf.InImage;
  REC_INT     := Inf.InReal; Inf.InImage;
  TIMESTEP    := Inf.InReal; Inf.InImage;
  UPD_INTERVAL:= inf.InReal; inf.InImage;
  WAT_CHANGE  := inf.InReal; inf.InImage;
  Rst         := Inf.InInt;  Inf.InImage;
    Rst_0     := Rst;  Comment RST-Wert wird konserviert.;
  List_Interv := Inf.Inreal; Inf.InImage;
  Draw_Interv := Inf.InReal; Inf.InImage;
  HYDRO_BLACK   := Inf.InReal; Inf.InImage;
  HYDRO_WHITE   := Inf.InReal; Inf.InImage;
  Outp_Opt1   := Inf.InInt;  Inf.InImage;
  Outp_Opt2   := Inf.InInt;  Inf.InImage;
  OXY_DIFF_RATE := Inf.InReal; Inf.InImage;
  THON := Inf.InReal; Inf.InImage;
  PORO_TOTAL := Inf.InReal; Inf.InImage;
  DENS_GRA := Inf.InReal; Inf.InImage;
  DENS_WAT := Inf.InReal; Inf.InImage;
  WATER_CONT_MAX := Inf.InReal; Inf.InImage;
  WATER_CONT_MIN := Inf.InReal; INf.InImage;
  RATE_BIOD_MAX := Inf.InReal; Inf.InImage;
  K_C := Inf.InReal; Inf.InImage;
  K_SO := Inf.InReal; inf.InImage;
  HEX := Inf.InReal; Inf.InImage;
  pi := Inf.InReal; Inf.InImage;

  INF.Close;

% %6
% Die Werte einiger globaler Variablen werden gesetzt:
% #
% /7
% Boolsche Variable merge wird auf falsch gesetzt.
% #
    MERGE := FALSE;
% /8
% Kalkulation der maximalen Anzahl der X- und Y_Zellen.
% #
  ROWS := (Y_HEIGHT / (2* HEX * Sin(pi/3))) - 0.5 * HEX * Sin(pi/3);
  X_CELLS := (2/3) * (X_BOTTOM / HEX - 0.5);
  Y_Half := ROWS/2;
% /9
% Kalkulation der Y-Koordinaten i bei 1/3 und 2/3 der Mietenhöhe.
% #
  y_10 := ROWS - ROWS / 3;
  y_05 := ROWS - 2*ROWS / 3;
% /10
% Kalkulation der Entfernung zwischen zwei Porenzentren.
% #
  DIST := SQRT(3) * HEX;        
% /11
% Kalkulation des Volumens eines Hexagons mit einer Tiefe von 0.01 m.
% #
  HEX_VOL := 0.03 * cos(pi/6) * (HEX**2);
% /12
% Kalkulation der Oberfläche zwischen zwei Poren-Nachbarn.
% #
  AREA := HEX * 0.01;
% /13
% Kalkulation des Trockengewichts einer Pore;
% #
  TS_PORE := DENS_GRA * HEX_VOL * (1 - PORO_TOTAL);     
% /14
% Kalkulation des maximalen Wassergradienten in der Miete.
% #
  WATER_DIFF := WATER_CONT_MAX - WATER_CONT_MIN;                        
% %15   
% Die Grenzen des graphischen Outputs werden festgelegt und die
% Programmklasse GRPS wird gestartet.
% #
  GRPS     (0.0,  0.0, (X_CELLS + 1), (2.5*ROWS + 1) , 0.0, 0.0, "gr")
     BEGIN
% %16
% Start der Programmklasse Simulation
% #
    SIMULATION BEGIN

        Comment Nachbarschastschema:
                       2 4        4 4       6 4       8 2
                 1 4        3 4        5 4       7 4
                       2 3        4 3       6 3       8 2
                 1 3        3 3        5 3       7 3
                       2 2        4 2       6 2       8 2
                 1 2        3 2        5 2       7 2
                       2 1        4 1       6 1       8 1
                 1 1        3 1        5 1       7 1

                          Nachbarschaft        Nachbarschaft
                            (x gerade)          (x ungerade)
         oben             x       y + 1       x       y + 1
         unten            x       y - 1       x       y - 1
         oben rechts      x + 1   y + 1       x + 1   y
         unten rechts     x + 1   y           x + 1   y - 1
         oben links       x - 1   y + 1       x - 1   y
         unten links      x - 1   y           x - 1   y - 1

         Nachbarschaftskodierung:
                  u , d   oben, unten                  u
                  ru    rechts oben               lu        ru
                  rd    rechts unten                  Pore
                  lu    links oben                ld        rd
                  ld    links unten                    d         ;

% /17
% Simulationsvariablen
% #
      REF (Pore) POR;
      REF (Pore) ARRAY PPP ( 0 : X_CELLS + 1,  0 : ROWS + 1);
      REF (Head) POREN_1, POREN_2;
      INTEGER counter;
      REAL X_OFFSET,    Y_OFFSET,
           X_OFFS_HALF, Y_OFFS_HALF,
           X_OFFS_3_4;
      REF (Legend) LEG;

% %18
% Prozedur, welche die graphischen grenzen eines Hexagons
% ermittelt.
% #
      PROCEDURE Scaling; BEGIN
        X_OffSet    := 0.6666666 * 0.9;
        Y_OffSet    := 0.5       * 0.9;
        X_Offs_Half := X_OffSet / 2.0 ;
        Y_Offs_Half := Y_OffSet / 2.0 ;
        X_Offs_3_4  := X_Offs_Half + (X_Offs_Half / 2.0);
      END of Scaling;
% %19
% Prozedur, welche die Anzahl der X-Zellen in Abhängigkeit von
% dem Y-Wert berechnet.
% #
      INTEGER PROCEDURE Update_X(F); INTEGER F;
        BEGIN
        REAL T_B,
             X_Upd, Y_Upd, x_Int;
             T_B := X_BOTTOM - X_TOP;
             Y_Upd := Y_HEIGHT - F * 2 * Sin(pi/3) * HEX -  0.5*Hex*Sin(pi/3);          
             X_Int := 2 * X_Upd + X_TOP;
             UPDATE_X := (2/3) * (X_INT / HEX - 0.5);
        END of Update_X;
% %20
% Prozedur, welche die Koordinaten der Poren in bestimmten Höhen
% und bei gegebener Anzahl der X-Zellen im Trapez ermittelt.
% #
      PROCEDURE Centralize(F,a,b);Name a,b; INTEGER F,a,b;
      BEGIN
                a:= (X_CELLS - F)/2;
                b := a + F -1;
      END of Centralize;                
% %21
% Instantiierung der Porenzellen und einer Peripherie um die
% Simulationsmiete.
% #
      PROCEDURE Generate_Pores; BEGIN
        INTEGER K, L;
        FOR K :=   0 step 1 until X_CELLS + 1 do BEGIN
          FOR L :=  0 step 1 until  ROWS + 1 do BEGIN
            PPP (K, L):- NEW PORE (K, L); Comment integer -> real;
% /22
% Die Sauerstoffkonzentration in der Außenluft wird auf 999.9 gesetzt.
% An diesem unrealistischen Wert können die Peripheriezellen an der
% Oberfläche erkannt werden.
% #
            PPP(K, L).P_OXY := 999.9;
          END of FOR;
        END of FOR;

% /23
% Berechnung der maximalen Anzahl von X-Zellen;
% #
       X_CperR := Update_X(1);
       Centralize(X_CperR,a,b);
       X_CELLS := b;
       counter := 1;
% %24
% Die Parameterwerte der Porenzellen werden gesetzt.
% Die Sauerstoffkonzentration in der Aussenluft wird auf den Wert bei
% 20°C gesetzt.
% Die Höhe der Kontamination wird festgelegt.
% #
       FOR L :=  1 step 1 until  ROWS  do BEGIN
       X_CperR := Update_X(L);
       Centralize(X_CperR,a,b);
       IF a = 0 THEN a:=1;
          FOR K := a step 1 until b  do BEGIN
            counter := counter + 1;
            PPP (K, L).Inside := true;
            PPP (K, L).Update_Pore_Center;
            PPP (K, L).Update_Neighbours;
            PPP (K,L).P_OXY := 0.275;
            PPP (k,L).C_HYDRO := 10;
            PPP (K,L).S_OXY_OLD := 0;
            PPP (K,L).Update_Water_Content;
            PPP (K,L).WATER_CONTENT := PPP(K,L).WAT_CONT_STANDARD;
            PPP (K,L).Update_Diff_COEFF;                
          END of FOR;
         END of FOR;

% /25
% Die Sauerstoffkonzentration an der Mietenunterseite wird auf
% -999.9 gesetzt. An diesem Wert können die Peripherie-Zellen unter
% der Miete erkannt werden
% #
        FOR K :=   0 step 1 until X_CELLS + 1 do BEGIN
          FOR L :=  0                           do BEGIN
            PPP(K, L).P_OXY := -999.9;
          END of FOR;
        END   of FOR;
% /26
% Nach Initialisierung der Porenparameter wird der Titelbildschirm
% vervollständigt.
% #
        OutText("                  Simulation is running ...");
        OutImage;OutImage;
        OutText("          Number of Pore Cells in Plant  : ");
        BreakOutImage;
        OutInt(counter,0); OutImage;

% /27
% Die Porenzellen werden aktiviert:
% #
        FOR K :=   1 step 1 until X_CELLS  do BEGIN
          FOR L :=  1 step 1 until  ROWS  do BEGIN
          If PPP(K,L).Inside then ACTIVATE PPP (K, L);
          END of FOR;
        END of FOR;

      END of Generate_Pores;

% %28
% Die Prozessklasse PORE wird instantiiert.
% #
      PROCESS CLASS PORE (X, Y); INTEGER X, Y; BEGIN
        BOOLEAN INSIDE,  Comment Boolsche Variable, die angibt, ob sich
                                  eine Zelle in der Miete befindet;
                UNEVEN;  Comment Boolsche Variable, mit der verschiedene
                                 Nachbarschaftsverhältnisse unterschieden
                                 werden können;
        REAL X_CENTER,   Comment Koordinaten des Zentrums der Pore;
             Y_CENTER,
             P_OXY,      Comment Sauerstoffkonzentration in der Porenluft
                                 in  [kg/m^3];
             R_OXY,       Comment Rate, mit der sich der absolute Sauer-                                
             S_OXY,      Comment Sauerstoff in Lösung [g/l = g/kg];
             S_OXY_OLD,  Comment Sauerstoff in Lösung bei t-1;
             P_HYDRO,    Comment Dieselölgehalt [g/Zelle];
             C_HYDRO,    Comment Dieselölkonzentration [g/kg TS];
             R_HYDRO,    Comment Hydrocarbon Rate;
             WATER_CONTENT, Comment Water_Content of the Cell;
             WAT_CONT_STANDARD, Comment water-content at t=0;
             Oxy_Diff_Eff,  comment Effektiver Diffusionskoeffizient;
             PORO_AIR,   Comment Luftpotosität;
             PORO_WAT, Comment Wasserporosität;
             AIR_VOL,    Comment Luftvolumenn;
             WATER_VOL,  Comment Wasservolumen;
             RANDOM_HOLD;Comment Zufallsvariable;
% /29
% Referenzen zu den 6 Nachbarn.
% #
        REF (Pore) NEI_UP,
                   NEI_DOWN,
                   NEI_RIGHT_UP,
                   NEI_RIGHT_DOWN,
                   NEI_LEFT_UP,
                   NEI_LEFT_DOWN;
% %30
% Prozedur, mit welcher das Poren-Zentrum in seine hexagonale
% Position gerückt wird.
% #
        PROCEDURE Update_Pore_Center; BEGIN
          Comment defining cell center, moving it to hexagonal position;
          X_Center := X;  Comment integer -> real;
          Y_Center := Y;
          If MOD (X, 2) = 0 then BEGIN
            Y_Center := Y_Center + 0.5;
          END of if mod 2;
        END of update_pore_center;
% %31
% Prozedur zur Ermittlung der Nachbarzellen.
% #
        PROCEDURE Update_Neighbours; BEGIN
          If MOD (X, 2) = 1 then Uneven := true
                            ELSE Uneven := false;
          If Uneven then BEGIN
            Comment Trifft zu, wenn Y ungerade ist;
            Nei_up         :- PPP (X  , Y+1 );
            Nei_down       :- PPP (X  , Y-1 );
            Nei_right_up   :- PPP (X+1, Y+1 );
            Nei_right_down :- PPP (X+1, Y   );
            Nei_left_up    :- PPP (X-1, Y+1 );
            Nei_left_down  :- PPP (X-1, Y   );
          END if uneven
          ELSE BEGIN
            Comment Trifft zu, wenn Y gerade ist;
            Nei_up         :- PPP (X  , Y+1 );
            Nei_down       :- PPP (X  , Y-1 );
            Nei_right_up   :- PPP (X+1, Y   );
            Nei_right_down :- PPP (X+1, Y-1 );
            Nei_left_up    :- PPP (X-1, Y   );
            Nei_left_down  :- PPP (X-1, Y-1 );
          END of if even;
        END of Update_Neighbours;
% %32
% Prozedur zur Berechnung des Wassergehaltes.
% #
        PROCEDURE Update_Water_Content;
        BEGIN
           INTEGER ARRAY count(1:X_CELLS);
           REAL res,c,d, x_Max, y_Max, vek_x, vek_y;
           INTEGER X_C,a,b;
           x_Max := ( X_CELLS) / 2 + 0.5;
           y_Max :=  ROWS;
           x_CperR := Update_X(y);
           c := WATER_DIFF / X_Max;
           d := WATER_DIFF / Y_MAX;
           FOR L :=  1 step 1 until  ROWS  do BEGIN
            X_C := Update_X(L);
            Centralize(X_C,a,b);
            IF a = 0 THEN a:=1;
            FOR K := a step 1 until b  do BEGIN
              count(K) := count(K)+1;
            END of FOR;
          END of FOR;
        
          IF x > x_Max THEN BEGIN
              Vek_X := ((X_CELLS -x -1) - (X_CELLS - X_CperR)/2) * c;
          END ELSE BEGIN
              IF x < x_Max THEN BEGIN
                Vek_X := (x -(X_CELLS - X_CperR)/2) * c;
              END ELSE BEGIN
                Vek_X := (x_Max -(X_CELLS - X_CperR)/2) * c;
             END of IF;
           END of IF;
                Vek_Y := (count(x) -y)* d;
           IF Vek_x < 0 THEN Vek_x :=0;
           WAT_CONT_STANDARD := WATER_CONT_MIN + Sqrt(Vek_X * Vek_Y);
           if WAT_CONT_STANDARD < 0.1 then WAT_CONT_STANDARD := 0.1;
        END of Update_Water_Content;
% %33   
% Prozedur, mit welcher der effektive Diffusionskoeffizient
% berechnet wird.
% Dabei wird die Luftporosität, die Wasserporosität, das Lustvolumen
% und das Wasservolumen ermittelt.
% #
        PROCEDURE Update_Diff_Coeff;
        BEGIN
           REAL v;
           PORO_WAT := WATER_CONTENT * ((1 - PORO_TOTAL) * DENS_GRA)/DENS_WAT;
           PORO_AIR := PORO_TOTAL - PORO_WAT;
           AIR_VOL := HEX_VOL * PORO_AIR;
           WATER_VOL := HEX_VOL * PORO_WAT;
           v := PORO_AIR**1.33;
           Oxy_Diff_Eff := OXY_DIFF_RATE * ((PORO_AIR/PORO_TOTAL)**2) * v;
        END of Update_Diff_COeff;
% %34
% Berechnung der Sauerstoffdiffusion mit einer Nachbarzelle.
% #
        PROCEDURE Oxy_Diffusion (Neighbour); REF (Pore) NEIGHBOUR; BEGIN
           REAL FROM_TO;

          If Neighbour.P_OXY < 999.0 then BEGIN
            Comment Trifft zu, wenn Nachbarzelle nicht Luftoberfläche ist;
            If Neighbour.P_OXY > -999.0 then BEGIN
            Comment Trifft zu, wenn Nachbarzelle nicht Mietenuntergrund ist;
% /35
% Aufruf der Prozedur rk (Runge-Kutta-Integration).
% #
              From_To := rk4(Neighbour.P_OXY,P_OXY);
              Neighbour.R_OXY := Neighbour.R_OXY - From_To;
        
              R_OXY := R_OXY +  From_To;
            END ELSE BEGIN
            Comment Trifft zu, wenn Nachbarzelle Mietenuntergrund ist,
                     nichts passiert;
            END of if;
          END of if ELSE BEGIN
            Comment Trifft zu wenn Nachbarzelle Luftoberfläche ist,
                   rk4 wird aufgerufen;
              From_To := rk4(0.275,P_OXY);
              R_OXY := R_OXY +  From_To;
          END of if;
        END of Oxy_Diffusion ;
% %36
% Prozedur, die den Abbau des Dieselöls kalkuliert.
% #
        PROCEDURE Biodegradation;
        BEGIN
           REAL RATE_BIOD;
           RATE_BIOD := (RATE_BIOD_MAX * TIMESTEP / ( 86400 ))*
              (S_OXY**10 / (K_SO**10 + S_OXY**10));
           R_HYDRO := RATE_BIOD * (C_HYDRO**2 / (C_HYDRO**2 + K_C**2)) * TS_PORE
        
        END of Biodegradation;
% %37   
% Kalkulation des Sauerstoffverbrauchs in Abhängigkeit
% von der Biodegradation.
% #
        PROCEDURE Oxy_Usage;
           BEGIN
           REAL USED_OXY;
           USED_OXY := R_HYDRO * THON;
           S_OXY_OLD := (S_OXY  * WATER_VOL * 1000 - USED_OXY) / (WATER_VOL*1000
        END of Oxy_Usage;
% %38
% Runge-Kutta-Integrationsverfahren zweiter Ordnung.
% #
        REAL procedure rk4(N_O,O); REAL N_O, O;
        BEGIN
           REAL k1, k2, k3, k4, t_half, y, y_N;
           t_half := TIMESTEP/2;
           k1 := OXY_DIFF_Eff * AREA * ((N_O - O) / DIST) * t_half;
           y := O + k1;
           y_N := N_O - k1;
           rk4 := OXY_DIFF_Eff * AREA * ((y_N - y) / DIST) * TIMESTEP ;
        END of rk4;
% %39   
% Passt den Wassergehalt nach Durchmischung in vorgegebenen
% Intervallen wieder dem Standardwert an.
% #
        PROCEDURE upd_wat_merge;
        BEGIN
           REAL change;
           change := (WATER_CONTENT - WAT_CONT_STANDARD)*WAT_CHANGE;
           WATER_CONTENT := WATER_CONTENT - change;
        END;
        
% %40
% Porenzellen werden auf ihre Aktivität vorbereitet.
% #
        Into (Poren_1);
        WHILE true do BEGIN
% /41
% Aufruf der Prozedur Oxy_Diffusion mit zur
% Berechnung des Sauerstofftransfers mit den
% beiden Nachbarzellen.
% #
          Oxy_Diffusion (NEI_UP        );
          Oxy_Diffusion (NEI_DOWN      );
          Oxy_Diffusion (NEI_RIGHT_UP  );
          Oxy_Diffusion (NEI_RIGHT_DOWN);
          Oxy_Diffusion (NEI_LEFT_UP   );
          Oxy_Diffusion (NEI_LEFT_DOWN );
% /42
% Der Sauerstoffflux wird zum Pool addiert.
% Falls die Konzentration unter Null sinkt, wird die
% Simulation abgebrochen und eine Fehlermeldung
% ausgegeben.
% #
          P_OXY := (P_OXY * AIR_VOL + R_OXY) / AIR_VOL;
          IF P_OXY < 0 THEN Error ("Kompartiment Overflow !");
% /43
% Berechnung des in Wasser gelösten Sauerstoffs mit dem
% Henry'schen Gesetz. 1 mol Luft nimmt bei 20°C 24,5 l
% Volumen ein, die Henry-Konstante hat den
% Wert: 0.0013 mol/(kg * bar).
% Anschließend wird der gelöste Sauerstoff aus der
% Porenluft substrahiert, wobei der noch gelöste
% Sauerstoff aus dem vorigen Zeitschritt addiert
% wird.
% #
          S_OXY := 0.0013 * 22.4  * P_OXY;
          P_OXY := (P_OXY * AIR_VOL -  WATER_VOL * (S_OXY - S_OXY_OLD))
                   / AIR_VOL;
          R_OXY := 0.0;
% /44
% Das Dieselölpool in der Zelle wird aus der
% Konzentration ermittelt.
% Danach wird die Prozedur Biodegradation aufgerufen.
% #
          P_HYDRO := C_HYDRO * TS_PORE;
          Biodegradation;
% /45
% Update des Dieselölpools und der Konzentration.
% #
          P_HYDRO := P_HYDRO - R_HYDRO;
          C_HYDRO := P_HYDRO / TS_PORE;
% /46   
% Aufruf der Prozedur Oxy_Usage.
% #
          Oxy_Usage;
        
          R_HYDRO := 0;
          R_OXY := 0;
% /47   
% Abfrage, ob der Wassergehalt angepasst werden muss.
% Wenn ja, wird die Prozedur Upd_wat_merge und
% Update_Diff_Coeff aufgerufen.
% #
          UPD_COUNT := Mod(Time,UPD_INTERVAL);
          IF MERGE AND UPD_COUNT = 0 THEN BEGIN
                Upd_Wat_Merge;
                Update_Diff_Coeff;
             END;
% /48
% Ermittlung der Zufallszahl Random_Hold.
% Durch sie wird bei jedem Zeitschritt eine
% andere Reihenfolge der Berechnung in den
% einzelnen Poren ermöglicht, um numerische
% Artefakte zu vermeiden.
% #
          Random_Hold := UNIFORM (0.0,TIMESTEP, Rst);
          HOLD (Random_Hold);
          HOLD (TIMESTEP - Random_Hold);
          S_OXY := 0;
        END of WHILE;
      END of pore;

% %49
% Prozessklasse Merge_Kompost wird instantiiert.
% Mit ihr werden zu bestimmten Zeitpunkten die
% Zellen durchmischt. Aus dem Dieselölgehalt
% wird ein Mittelwert gebildet, während die
% Wassergehalte zufällig verteilt werden.
% #
      PROCESS CLASS MERGE_COMPOST; BEGIN
        REF (Pore) POR;
        INTEGER K, L, M, N;
        WHILE Poren_1.Cardinal > 5 do BEGIN
          N := RANDINT (1, Poren_1.Cardinal - 1, Rst);
          Por :- Poren_1.first;
          FOR M := 1 Step 1 until N do Por :- Por.Suc;
          Por.Into (Poren_2);
        END of WHILE;
        WHILE not Poren_1.Empty do BEGIN
          Por :- Poren_2.first;
          N := RANDINT (1, Poren_2.Cardinal - 1, Rst);
          FOR M := 1 Step 1 until N do Por :- Por.Suc;
          Poren_1.First.Follow(Por);
        END of WHILE;

        FOR L :=  1 step 1 until  ROWS  do BEGIN
           X_CperR := Update_X(L);
           Centralize(X_CperR,a,b);
           IF a = 0 THEN a:=1;
           FOR K := a step 1 until b  do BEGIN
            Por :- Poren_2.First;
            Por.X := K;
            Por.Y := L;
            Por.Into (Poren_1);
            PPP (K, L) :- Por;
           END of FOR;
        END of FOR;

        FOR L :=  1 step 1 until  ROWS  do BEGIN
            X_CperR := Update_X(L);
            Centralize(X_CperR,a,b);
            IF a = 0 THEN a:=1;
            FOR K := a step 1 until b  do BEGIN
            PPP (K, L).Update_Pore_Center;
            PPP (K, L).Update_Neighbours;
            PPP (K, L).Update_Water_Content;
            PPP (K, L).P_OXY := 0.275;
            PPP (k, L).S_OXY := 0.0013 * 22.4  * PPP (K, L).P_OXY;
            PPP (K, L).S_OXY_OLD := 0;
         END of FOR;
        END of FOR;
        MERGE:= TRUE;
      END of merge_compost;
% %50
% Nach Aktivierung dieser Klasse wird in bestimmten
% Intervallen ein graphischer Output im
% Postscript-Format erstellt.
% Die Hexagone werden mit einer Graustufe in
% Abhängigkeit vom Dieselölgehalt gefüllt.
% Außerdem können optional die Zellkoordinaten
% ausgegeben werden.
% Am Ende wird eine Legende geschrieben.
% #
      PROCESS CLASS GRAPHIC_OBSERVER; BEGIN
        INTEGER L, M;
        REAL HYDRO_SHIFT,
             HYDRO_SHRINK;
        TEXT T;
        REF (Point) P1, P2, POI;
        REF (Polygon) Pol;
        REF (Legend) LEG, LEG1, LEG2;

        HYDRO_SHIFT := - HYDRO_BLACK;
        HYDRO_SHRINK := 1.0 / (HYDRO_WHITE - HYDRO_BLACK);

        WHILE true do BEGIN
           If Outp_opt1 = 1 then BEGIN
              Comment Darstellung der Dieselölgehalte in Graustufen;
                 FOR M :=  1 step 1 until  ROWS  do BEGIN
              X_CperR := Update_X(M);
              Centralize(X_CperR,a,b);
               IF a = 0 THEN a:=1;
               FOR L := a step 1 until b  do BEGIN

                Pol :- NEW Polygon;
                Inspect PPP (L, M) do BEGIN
                  Comment Exkpunkte des Hexagons werden generiert;
                  P1 :- NEW Point (X_Center - X_OffSet,
                                   Y_Center            );
                  P1.PutInto (Pol);
                  P1 :- NEW Point (X_Center - X_OffS_Half,
                                   Y_Center + Y_OffSet );
                  P1.PutInto (Pol);
                  P1 :- NEW Point (X_Center + X_OffS_Half,
                                   Y_Center + Y_OffSet );
                  P1.PutInto (Pol);
                  P1 :- NEW Point (X_Center + X_OffSet,
                                   Y_Center            );
                  P1.PutInto (Pol);
                  P1 :- NEW Point (X_Center + X_OffS_Half,
                                   Y_Center - Y_OffSet );
                  P1.PutInto (Pol);
                  P1 :- NEW Point (X_Center - X_OffS_Half,
                                   Y_Center - Y_OffSet );
                  P1.PutInto (Pol);
                  P1 :- NEW Point (X_Center - X_OffSet,
                                   Y_Center            );
                  P1.PutInto (Pol);
                  Comment Graustufe wir in Abhängigkeit vom
                          Sauerstoffgehalt ermittelt;
                  Pol.Gray := (C_HYDRO  - HYDRO_BLACK) * HYDRO_SHRINK;
                  Pol.Fill := true;
                  Pol.Display;
                END of inspect;
              END of FOR;
            END of FOR;
          END of outp_opt1;

          If Outp_opt2 = 1 then BEGIN
            Comment Koordinarten  werdem in Graphik ausgegeben;
            REF (Legend) Leg;
            TEXT TTT;
            TTT :- Blanks(2);
            FOR L := 1 step 1 until  (X_CELLS) do BEGIN
              FOR M := 1 step 1 until  (ROWS) do BEGIN
                P1 :- NEW Point (PPP (L, M).X_Center + X_OffS_Half,
                                 PPP (L, M).Y_Center - Y_OffS_Half );
                TTT.PutInt (L);
                Leg :- NEW Legend (P1, TTT);
                Leg. Size := 0.3;
                Leg.Display;

                P1 :- NEW Point (PPP (L, M).X_Center - X_OffS_Half,
                                 PPP (L, M).Y_Center - Y_OffS_Half );
                TTT.PutInt (M);
                Leg :- NEW Legend (P1, TTT);
                Leg. Size := 0.3;
                Leg.Display;
              END of FOR;
            END of FOR;
          END of if outp_opt2;

          Poi :- NEW Point (0.0, -2.5);
          T :- Blanks (80);
          T := "Kompostmiete Hexagonal, Format X: 1 ...       ,Y: 1 ...  ";
          T. Sub(42,4).PutInt (X_CELLS);
          T. Sub(58,4).PutInt (ROWS);
          Leg :- NEW Legend (Poi, T); Leg.Size := 0.5;
          Leg.display;
          Poi :- NEW Point (0.0, -1.5);
          T :- Blanks (120);
          T := "     Time: ";
          T. Sub(15,9).PutFix (Time,0);
          Leg :- NEW Legend (Poi, T); Leg.Size := 0.5;
          Leg.display;

          NEW_PAGE;

          HOLD (Draw_Interv);

        END of WHILE;

      END of GRAPHIC_OBSERVER;
% %51
% Nach Aktivierung dieser Klasse werden in bestimmten
% Intervallen die Dieselölgehalte aller Porenzellen
% in einen Output-File geschrieben:
% #
      PROCESS CLASS List_Hydro; BEGIN
        TEXT T;
        HYD :- NEW Outfile ("hydro.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          HYD.Open (Blanks (120));
        END ELSE BEGIN
          HYD.Open (Blanks (X_CELLS * 7));
        END;
        WHILE true do BEGIN
           hyd.outtext("Time:  "); hyd.breakoutimage;
           hyd.outint(time,0);hyd.outimage;
           FOR L :=  ROWS STEP -1 UNTIL 1  do BEGIN
                X_CperR := Update_X(L);
                Centralize(X_CperR,a,b);
                IF a = 0 THEN a:=1;
                FOR M := a step 1 until b  do BEGIN
                  hyd.outint(L,0);hyd.breakoutimage;
                  hyd.outtext("    ");hyd.breakoutimage;
                  hyd.outint(M,0);hyd.breakoutimage;
                  hyd.outtext("    ");hyd.breakoutimage;
                  HYD.OutReal(PPP (L, M).C_HYDRO,4 , 15);
                  hyd.outimage;
                END of FOR;
           END of FOR;
           hyd.outimage;hyd.outimage;
           HOLD (draw_Interv);
        END of WHILE;
      END of List_Hydro;
% %52
% Nach Aktivierung dieser Klasse werden in bestimmten
% Intervallen die gelösten Sauerstoffgehalte aller
% Porenzellen in einen Output-File geschrieben:
% #
      PROCESS CLASS List_Oxy; BEGIN
        OXY :- NEW Outfile ("oxy.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          OXY.Open (Blanks (120));
        END ELSE BEGIN
          OXY.Open (Blanks (X_CELLS * 7));
        END;
        WHILE true do BEGIN
           oxy.outtext("Time:  "); oxy.breakoutimage;
           oxy.outint(time,0);oxy.outimage;
           FOR L :=  ROWS STEP -1 UNTIL 1  do BEGIN
                X_CperR := Update_X(L);
                Centralize(X_CperR,a,b);
                IF a = 0 THEN a:=1;
                FOR M := a step 1 until b  do BEGIN
                  oxy.outint(L,0);oxy.breakoutimage;
                  oxy.outtext("    ");oxy.breakoutimage;
                  oxy.outint(M,0);oxy.breakoutimage;
                  oxy.outtext("    ");oxy.breakoutimage;
                  OXY.OutReal(PPP (L, M).S_OXY_OLD,4 , 15);
                  oxy.outimage;
                END of FOR;
           END of FOR;
           oxy.outimage;oxy.outimage;
           HOLD (draw_Interv);
           END of WHILE;
      END of List_Oxy;
% %53
% Nach Aktivierung dieser Klasse wird in bestimmten
% Intervallen der durchschnittliche Dieselölgehalt
% in der Gesamtmiete in einen File geschrieben.
% #
       PROCESS CLASS List_Observer_average; BEGIN
        INTEGER counter;
        REAL add;
        AVE :- NEW Outfile ("average.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          AVE.Open (Blanks (120));
        END ELSE BEGIN
          AVE.Open (Blanks (X_CELLS * 7));
        END;
        WHILE true do BEGIN
              add := 0;
              counter := 0;

              FOR M :=  ROWS STEP -1 UNTIL 1  do BEGIN
                X_CperR := Update_X(M);
                Centralize(X_CperR,a,b);
                IF a = 0 THEN a:=1;
                FOR L := a step 1 until b  do BEGIN
                  counter := counter +1;
                  add := add + PPP(L, M).C_HYDRO;
                END of FOR;
              END of FOR;
              add := add / counter;
              AVE.OutFix(Time,0,0); AVE.BreakOutImage;
              AVE.OutText("    "); AVE.BreakOutImage;
              AVE.OutReal(add,4,12); AVE.OutImage;
          HOLD (List_Interv);
        END of WHILE;
      END of List_Observer_average;
% %54
% Nach Aktivierung dieser Klasse wird in bestimmten
% Intervallen der durchschnittliche Dieselölgehalt
% im inneren Mietendrittel in einen File geschrieben.
% #
      PROCESS CLASS List_Observer_Hydro_inner; BEGIN
        OTH3 :- NEW Outfile ("hydro05.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          OTH3.Open (Blanks (120));
        END ELSE BEGIN
          OTH3.Open (Blanks (X_CELLS * 7));
        END;
        OTH3.OutImage;

        WHILE true do BEGIN
            counter_i := 0;
            add_i := 0;
            FOR M :=  Y_05 STEP -1 UNTIL 1  do BEGIN
            X_CperR := Update_X(M);
            Centralize(X_CperR,a,b);
            IF a = 0 THEN a:=1;
            f:= X_CperR/6 * 2 +a;
            g:= b - X_CperR/6 *2;
            FOR L := f step 1 until g  do BEGIN
              counter_i := counter_i +1;
               add_i := add_i + PPP(L, M).C_HYDRO;
            END of FOR;
          END of FOR;
            ave_i := add_i / counter_i;
            OTH3.Outint(Time,0); OTH3.BreakOutImage;
            OTH3.OutText("    "); OTH3.BreakOutImage;
            OTH3.OutReal(ave_i,4,12); OTH3.OutImage;
            HOLD (List_Interv);
         END of WHILE;
      END of List_Observer_inner;
% %55
% Nach Aktivierung dieser Klasse wird in bestimmten
% Intervallen der durchschnittliche Dieselölgehalt
% im mittleren Mietendrittel in einen File geschrieben.
% #
      PROCESS CLASS List_Observer_Hydro_medium; BEGIN
        OTH2 :- NEW Outfile ("hydro10.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          OTH2.Open (Blanks (120));
        END ELSE BEGIN
          OTH2.Open (Blanks (X_CELLS * 7));
        END;
        OTH2.OutImage;
        WHILE true do BEGIN
            counter_m := 0;
            add_m := 0;
            FOR M :=  Y_10  STEP -1 UNTIL 1  do BEGIN
              X_CperR := Update_X(M);
              Centralize(X_CperR,a,b);
              IF a = 0 THEN a:=1;
              f:= X_CperR/6 *  +a;
              g:= b - X_CperR/6;
               FOR L := a step 1 until b  do BEGIN
                 counter_m:= counter_m +1;
                 add_m := add_m + PPP(L, M).C_HYDRO;
               END of FOR;
            END of FOR;
            ave_m := (add_m - add_i) / (counter_m - counter_i);
            OTH2.Outint(Time,0); OTH2.BreakOutImage;
            OTH2.OutText("    "); OTH2.BreakOutImage;
            OTH2.OutReal(ave_m,4,12); OTH2.OutImage;
            HOLD (List_Interv);
        END of WHILE;
      END of List_Observer;
% %56
% Nach Aktivierung dieser Klasse wird in bestimmten
% Intervallen der durchschnittliche Dieselölgehalt
% im äußeren Mietendrittel in einen File geschrieben.
% #
      PROCESS CLASS List_Observer_Hydro_outer; BEGIN
        OTH1 :- NEW Outfile ("hydro15.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          OTH1.Open (Blanks (120));
        END ELSE BEGIN
          OTH1.Open (Blanks (X_CELLS * 7));
        END;
        OTH1.OutImage;
        WHILE true do BEGIN
            counter_o := 0;
            add_o := 0;
            FOR M := ROWS STEP -1 UNTIL 1  do BEGIN
              X_CperR := Update_X(M);
              Centralize(X_CperR,a,b);
              IF a = 0 THEN a:=1;
              FOR L := a step 1 until b  do BEGIN
                 counter_o := counter_o +1;
                 add_o := add_o + PPP(L, M).C_HYDRO;
              END of FOR;
            END of For;
            ave_o := (add_o - add_m) / (counter_o -counter_m);
              OTH1.Outint(Time,0); OTH1.BreakOutImage;
              OTH1.OutText("    "); OTH1.BreakOutImage;
              OTH1.OutReal(ave_o,4,12); OTH1.OutImage;
              HOLD (List_Interv);
        END of WHILE;
      END of List_Observer;
% %57
% Nach Aktivierung dieser Klasse wird in bestimmten
% Intervallen der durchschnittliche gelöste Sauer-
% stoffgehalt im inneren Mietendrittel in einen
% File geschrieben.
% #
      PROCESS CLASS List_Oberserver_Oxy_inner; BEGIN
        OTF3 :- NEW Outfile ("oxy05.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          OTF3.Open (Blanks (120));
        END ELSE BEGIN
          OTF3.Open (Blanks (X_CELLS * 7));
        END;
        OTF3.OutImage;
        WHILE true do BEGIN
            counter_i := 0;
            add_i := 0;
            FOR M :=  Y_05 STEP -1 UNTIL 1  do BEGIN
              X_CperR := Update_X(M);
              Centralize(X_CperR,a,b);
              IF a = 0 THEN a:=1;
              f:= X_CperR/6 * 2 +a;
              g:= b - X_CperR/6 *2;
              FOR L := f step 1 until g  do BEGIN
                counter_i := counter_i +1;
                add_i := add_i + PPP(L, M).S_OXY;
              END of FOR;
          END of FOR;
          ave_i := add_i / counter_i;
          OTF3.Outint(Time,0); OTF3.BreakOutImage;
          OTF3.OutText("    "); OTF3.BreakOutImage;
          OTF3.OutReal(ave_i,4,12); OTF3.OutImage;
          HOLD (List_Interv);
        END of WHILE;
      END of List_Observer_inner;
% %58
% Nach Aktivierung dieser Klasse wird in bestimmten
% Intervallen der durchschnittliche gelöste Sauer-
% stoffgehalt im mittleren Mietendrittel in einen
% File geschrieben.
% #
      PROCESS CLASS List_Oberserver_Oxy_medium; BEGIN
        OTF2 :- NEW Outfile ("oxy10.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          OTF2.Open (Blanks (120));
        END ELSE BEGIN
          OTF2.Open (Blanks (X_CELLS * 7));
        END;
        OTF2.OutImage;
        WHILE true do BEGIN
            counter_m := 0;
            add_m := 0;
            FOR M :=  Y_10  STEP -1 UNTIL 1  do BEGIN
                X_CperR := Update_X(M);
                Centralize(X_CperR,a,b);
                IF a = 0 THEN a:=1;
                f:= X_CperR/6   +a;
                g:= b - X_CperR/6;
                FOR L := f step 1 until g  do BEGIN
                  counter_m:= counter_m +1;
                  add_m := add_m + PPP(L, M).S_OXY;
                END of FOR;
            END of FOR;
            ave_m := (add_m - add_i) / (counter_m - counter_i);
            OTF2.Outint(Time,0); OTF2.BreakOutImage;
            OTF2.OutText("    "); OTF2.BreakOutImage;
            OTF2.OutReal(ave_m,4,12); OTF2.OutImage;
            HOLD (List_Interv);
        END of WHILE;
      END of List_Observer;
% %59
% Nach Aktivierung dieser Klasse wird in bestimmten
% Intervallen der durchschnittliche gelöste Sauer-
% stoffgehalt im äußeren Mietendrittel in einen
% File geschrieben.
% #
      PROCESS CLASS List_Oberserver_Oxy_outer; BEGIN
        OTF1 :- NEW Outfile ("oxy15.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          OTF1.Open (Blanks (120));
        END ELSE BEGIN
          OTF1.Open (Blanks (X_CELLS * 7));
        END;
        OTF1.OutImage;
        WHILE true do BEGIN
            counter_o := 0;
            add_o := 0;
            FOR M :=  ROWS STEP -1 UNTIL 1  do BEGIN
                X_CperR := Update_X(M);
                Centralize(X_CperR,a,b);
                IF a = 0 THEN a:=1;
                FOR L := a step 1 until b  do BEGIN
                  counter_o := counter_o +1;
                  add_o := add_o + PPP(L, M).S_OXY;
                END of FOR;
             END of FOR;
             ave_o := (add_o - add_m) / (counter_o -counter_m);
             OTF1.Outint(Time,0); OTF1.BreakOutImage;
             OTF1.OutText("    "); OTF1.BreakOutImage;
             OTF1.OutReal(ave_o,4,12); OTF1.OutImage;
             HOLD (List_Interv);
        END of WHILE;
      END of List_Observer;
% %60
% Nach Aktivierung dieser Klasse werden in bestimmten
% Intervallen die Wassergehalte  aller Porenzellen
% in einen File geschrieben:
% #
      PROCESS CLASS  List_Water_Content; BEGIN
        OTH :- NEW Outfile ("water.dat");
        If (X_CELLS * 7) < 120 then BEGIN
          OTH.Open (Blanks (120));
        END ELSE BEGIN
          OTH.Open (Blanks (X_CELLS * 7));
        END;
        WHILE TRUE DO BEGIN
        OTH.OutInt(Time,0);oth.OutImage;
            FOR M := 1 step 1 until ROWS  do BEGIN
            X_CperR := Update_X(M);
            Centralize(X_CperR,a,b);
            IF a = 0 THEN a:=1;
             FOR L := a step 1 until b  do BEGIN
              oth.outint(L,0);oth.breakoutimage;
              oth.outtext("    ");oth.breakoutimage;
              oth.outint(M,0);oth.breakoutimage;
              oth.outtext("    ");oth.breakoutimage;
              OTH.OutReal(PPP (L, M).WATER_CONTENT,4 , 0);
              oth.outimage;
            END of FOR;
          END of FOR;
            oth.OutImage;
            Hold(UPD_INTERVAL);
         END of WHILE;
         END of List_Water_Content;
% %61
% Nach Aktivierung dieser Klasse werden in bestimmten
% Intervallen die Sauerstoffgehalte aller Zellen in
% einen File geschrieben. Es werden jeweils nur die
% aktuellen Werte im File gespeichert, frühere Auf-
% zeichnungen werden überschrieben.
% Mit diesen Werten kann die Simulation nach einem
% Abbruch wieder gestartet werden.
% #
      PROCESS CLASS Recover_Oxy; BEGIN
         WHILE TRUE DO BEGIN
            ore :- NEW OutFile ("oxy_rec.dat");
            ore.Open (Blanks (X_CELLS * 7));
            ore.OutInt(Time,0);ore.OutImage;
             FOR L :=  1 step 1 until  ROWS  do BEGIN
                X_CperR := Update_X(L);
                Centralize(X_CperR,a,b);
                IF a = 0 THEN a:=1;
                FOR K := a step 1 until b  do BEGIN
                   ore.OutReal(PPP(K,L).P_OXY,3,12); ore.OutImage;
                 END of FOR     ;
              END of FOR;
              ore.Close;
              hold(REC_INT);
          END of WHILE;
      END of Recover_Oxy;
% %62
% Nach Aktivierung dieser Klasse werden in bestimmten
% Intervallen die Dieselölgehalte aller Zellen in
% einen File geschrieben. Es werden jeweils nur die
% aktuellen Werte im File gespeichert, frühere Auf-
% zeichnungen werden überschrieben.
% Mit diesen Werten kann die Simulation nach einem
% Abbruch wieder gestartet werden.
% #
      PROCESS CLASS Recover_Hydro; BEGIN
         WHILE TRUE DO BEGIN
            hre :- NEW OutFile ("hyd_rec.dat");
            hre.Open (Blanks (X_CELLS * 7));
            hre.OutInt(Time,0); hre.OutImage;
            FOR L :=  1 step 1 until  ROWS  do BEGIN
               X_CperR := Update_X(L);
               Centralize(X_CperR,a,b);
               IF a = 0 THEN a:=1;
               FOR K := a step 1 until b  do BEGIN
                  hre.OutReal(PPP(K,L).C_HYDRO,3,12); hre.OutImage;
               END of FOR;      
             END of FOR;
             hre.Close;
             Hold(REC_INT);     
          END of WHILE;
      END of Recover_Hydro;
% %63
% Nach Aktivierung dieser Klasse werden in bestimmten
% Intervallen die Wassergehalte aller Zellen in
% einen File geschrieben. Es werden jeweils nur die
% aktuellen Werte im File gespeichert, frühere Auf-
% zeichnungen werden überschrieben.
% Mit diesen Werten kann die Simulation nach einem
% Abbruch wieder gestartet werden.
% #
      PROCESS CLASS Recover_WAT; BEGIN
          WHILE TRUE DO BEGIN
            wre :- NEW OutFile ("wat_rec.dat");
            wre.Open (Blanks (X_CELLS * 7));
            wre.OutInt(Time,0);wre.OutImage;
            FOR L :=  1 step 1 until  ROWS  do BEGIN
               X_CperR := Update_X(L);
               Centralize(X_CperR,a,b);
               IF a = 0 THEN a:=1;
               FOR K := a step 1 until b  do BEGIN
                  wre.OutReal(PPP(K,L).WATER_CONTENT,3,12); wre.OutImage;
               END of FOR       ;
             END of FOR;
             wre.Close;
             Hold(REC_INT);
          END of WHILE;
      END of Recover_wat;

% %64
% Ende der Deklarationen.
% Die Prozedur Scaling und Generate-Pores wird
% aufgerufen und die Simulation dadurch gestartet.
% Die für den Output zuständigen Prozess-
% klassen werden anschließend aktiviert.
% #
      Poren_1 :- NEW Head;
      Poren_2 :- NEW Head;
      Scaling;
      Generate_Pores;
      ACTIVATE NEW List_Water_Content;
      ACTIVATE NEW Recover_Oxy;
      ACTIVATE NEW Recover_Hydro;
      ACTIVATE NEW Recover_Wat;
      ACTIVATE NEW List_Oxy;
      ACTIVATE NEW List_Hydro;
      ACTIVATE NEW List_Observer_Hydro_inner;
      ACTIVATE NEW List_Observer_Hydro_medium;
      ACTIVATE NEW List_Observer_Hydro_outer;
      ACTIVATE NEW List_Oberserver_Oxy_inner;
      ACTIVATE NEW List_Oberserver_Oxy_medium;
      ACTIVATE NEW List_Oberserver_Oxy_outer;
      ACTIVATE NEW List_Observer_average;
      ACTIVATE NEW Graphic_Observer;
% %65
% Aktivierung der Prozessklasse Merge_Compost
% zu bestimmten Zeitpunkten der Simulation.
% #
      ACTIVATE NEW Merge_Compost at 4838400; Comment 8 Wochen;
      ACTIVATE NEW Merge_Compost at 9676800; Comment 16 Wochen;
      ACTIVATE NEW Merge_Compost at 14515200; Comment 24 Wochen;
      ACTIVATE NEW Merge_Compost at 19353600; Comment 32 Wochen;
      ACTIVATE NEW Merge_Compost at 24192000; Comment 40 Wochen;
      ACTIVATE NEW Merge_Compost at 29030400; Comment 48 Wochen;

% %66
% Festlegung der Simulationsdauer.
% #
      HOLD (SIM_TIME); Comment setting duration of the simulation;

% %67
% Files werden geschlossen.
% #
      oth.Close;
      OTH1.Close;
      OTH2.Close;
      OTH3.Close;
      OTF1.Close;
      OTF2.Close;
      OTF3.Close;
      ave.Close;
      hyd.Close;
      oxy.Close;

    END of simulation;
  END of grawing;
END of program;



Oliver Loenker